CYGPKG_DEVS_I2C_MCFxxxx -- eCos Support for the Freescale Coldfire I2C Bus
Several processors in the Freescale ColdFire family come with one or
more on-chip I2C bus devices. This package
provides an eCos I2C bus driver. It was
originally developed on an MCF5280 but should work with any ColdFire
processor that uses a compatible bus device. The driver implements the
functionality defined by the generic I2C
The hardware does not support DMA or fifos, so usually a transfer will
involve an interrupt for every byte transferred. Since the
I2C bus typically runs at 100KHz large
transfers will consume much of the available cpu time.
This package does not provide any cyg_i2c_bus
structures. The number of I2C buses varies
between ColdFire processors. If multiple buses are available then
exactly which one(s) are in use on a given hardware platform depends
entirely on that platform. The desired I2C
bus speed also depends on the platform, and there may be other issues
such as how the processor pins should be set up. Hence it is left to
other code, usually the processor HAL, to instantiate the bus
structure(s). This driver package supplies the necessary functions and
utility macros. Similarly this package does not provide any
cyg_i2c_device structures. Which
I2C devices are hooked up to which
I2C bus is entirely a characteristic of the
hardware platform, so it is up to the platform HAL to
instantiate the necessary structures.
The driver will operate in interrupt-driven mode if interrupts are
enabled when a transfer is initiated. Otherwise it will operate in
polled mode. This allows the driver to be used in a variety of
configurations including inside RedBoot.
The I2C bus driver package should be loaded
automatically when selecting a target containing a suitable ColdFire
processor, and it should never be necessary to load the package
explicitly. If the application does not use any of the
I2C functionality, directly or indirectly,
then all the I2C code should be removed at
link-time and the application does not suffer any overheads.
By default the driver assumes a single I2C
bus and optimizes for that case. For example options like the ISR
vector and priority are handled by compile-time
#define's in the platform HAL's exported header
files rather than by per-bus structure fields. This helps to reduce
both code and data overheads. If the driver should support multiple
I2C buses then
CYGHWR_DEVS_I2C_MCFxxxx_MULTIPLE_BUSES should be
enabled. Typically this will be done by the processor HAL using a CDL
requires property. If bus instantiation happens
outside the processor HAL and hence the HAL's header files do not
provide the appropriate definitions, then this configuration option
should also be defined.
The only other configuration options in this package provide control
over the compiler flags used to build the driver code.
Defining the Bus and Devices
For most hardware targets the processor HAL will instantiate the
cyg_i2c_bus and the platform HAL will
instantiate the cyg_i2c_device structures.
Between them they will also initialize the hardware so that the
I2C-related pins are connected
appropriately. Some development boards have no
I2C devices, but the
I2C bus signals are accessible via an
expansion connector and I2C devices can be
put on a daughter board. In such cases it may be necessary for the
application to instantiate the device structures.
To facilitate bus instantiation the header file cyg/io/i2c_mcfxxxx.h provides a utility
macro CYG_MCFxxxx_I2C_BUS. This takes six
The name of the bus, for example
hal_dnp5280_i2c_bus. This name will be used when
instantiating the I2C devices.
An initialization function. If no platform-specific initialization is
needed then this can be the cyg_mcfxxxx_i2c_init
function exported by this driver. Otherwise it can be a
platform-specific function which, for example, sets up the relevant
pins appropriately and then chains into
The base address of the I2C bus. For
example on an MCF5282 with the IPSBAR set to its usual value of
0x40000000, the I2C bus is at location
The interrupt vector, for example
CYGNUM_HAL_ISR_I2C_IIF on an MCF5282.
The interrupt priority. Typically this will be a configurable option
within the platform HAL.
A value for the I2C bus's I2FDR register.
That register controls the bus speed. Typical bus speeds are 100KHz
and 400KHz, depending on the capabilities of the attached devices.
There is no simple relationship between the system clock speed, the
desired bus speed, and the FDR register. Although the driver could
determine the FDR setting using a lookup table and appropriate code,
it is better to determine the correct value once during the porting
process and avoid unnecessary run-time overheads.
For the common case where only a single I2C
bus should be supported
disabled), the last four parameters should be provided by preprocessor
#define's, typically in cyg/hal/plf_io.h which gets
#include'd automatically via
cyg/hal/hal_io.h. This header can also define the
HAL_I2C_EXPORTED_DEVICES macro as per the generic
On this particular platform the I2C bus is
only accessible on an expansion connector so the support is
conditional on a configuration option
CYGHWR_HAL_M68K_DNP5280_I2C. The interrupt priority
and I2FDR values are also controlled by configuration options. On
other platforms the I2C support may not be
conditional and the priority and/or FDR values may be hard-wired.
The I2C bus instantiation should happen in
an ordinary C or C++ file, typically in the platform HAL. The
corresponding object file should go into
libtarget.a and the file should only contain
I2C-related code to get the maximum benefit
of linker garbage collection.
Obviously if CYGHWR_DEVS_I2C_MCFxxxx_MULTIPLE_BUSES
is enabled then the singleton macros may not be defined and the
appropriate numbers should be used directly. This example assumes no
special initialization is needed. If there are special initialization
requirements then a custom function can be used instead of
cyg_mcfxxxx_i2c_init, and the custom function
should chain to the latter.
I2C device structures can be instantiated
in the usual way, for example: