CYGPKG_DEVS_SERIAL_MCFxxxx — eCos Support for the MCFxxxx On-chip Serial Devices


All members of the Freescale MCFxxxx ColdFire family of processors contain a number of on-chip UARTs for serial communication. They all use very similar hardware. There are some variations such as different fifo sizes, and some processors contain extra functionality such as autobaud detection, but a single eCos device driver can cope with most of these differences. The CYGPKG_DEVS_SERIAL_MCFxxxx package provides this driver. It will use definitions provided by the variant HAL CYGPKG_HAL_M68K_MCFxxxx, the processor HAL and the platform HAL.

The driver provides partial support for hardware flow control and for serial line status. Only CTS/RTS hardware flow control is supported since the UART does not provide DTR/DSR lines. Similarly only line breaks, and certain communication errors are supported for line status since the UART does not provide other lines such as DCD or RI. On some platforms it should be possible to emulate these lines using GPIO pins, but currently there is no support for this.

Once application code accesses a UART through the serial driver, for example by opening a device /dev/ser0, the driver assumes that it has sole access to the hardware. This means that the UART should not be used for any other purpose, for example HAL diagnostics or gdb debug traffic. Instead such traffic has to go via another communication channel such as ethernet.

Configuration Options

The MCFxxxx serial driver should be loaded automatically when selecting a platform containing a suitable processor, and it should never be necessary to load it explicitly. The driver as a whole is inactive unless the generic serial support, CYGPKG_IO_SERIAL_DEVICES, is enabled. Exactly which UART or UARTs are accessible on a given platform is determined by the platform because even if the processor contains a UART the platform may not provide a connector. Support for a given UART, say uart0, is controlled by a configuration option CYGPKG_DEVS_SERIAL_MCFxxxx_SERIAL0. The device driver configuration option in turn depends on a HAL configuration option CYGHWR_HAL_M68K_MCFxxxx_UART0 to indicate that the UART is actually present and connected on the target hardware. If a given UART is of no interest to an application developer then it is possible to save some memory by disabling this option.

For every enabled UART there are a set of configuration options. The following use SERIAL0 as an example, though each UART device available will have its own unique SERIALn naming:

Each serial device should have a unique name so that application code can open it. The default device names are /dev/ser0, /dev/ser1, and so on. It is only necessary to change these if the platform contains additional off-chip UARTs with clashing names.
By default the driver arranges for the UARTs to interrupt at a low interrupt priority. Usually there will be no need to change this because the driver does not actually do very much processing at ISR level, and anyway UARTs are not especially fast devices so do not require immediate attention. On some Coldfires with MCF5282-compatible interrupt controllers care has to be taken that all interrupt priorities are unique.
Each UART will be initialized to a given baud rate. The default baud rate is 38400 because in most scenarios this is fast enough yet does not suffer from excess data corruption. Lower baud rates can be used if the application will operate in an electrically noisy environment, or higher baud rates up to 230400 can be used if 38400 does not provide sufficient throughput.
The serial driver will maintain software buffers for incoming and outgoing data. The former allows data to continue to arrive even if the application is still busy processing the previous transfer, and thus potentially improves throughput. The latter allows the application to transmit data without immediately blocking until the transfer is complete, often eliminating the need for a separate thread. The size of these buffers can be controlled via this configuration option, or alternatively these buffers can be disabled completely to save memory.

If the serial driver has been configured with buffering (non-zero CYGNUM_DEVS_SERIAL_MCFxxxx_SERIALn_BUFSIZE option) then this RX ISR specific option allows extra ISR buffering to be used to minimise the chances of dropped characters at high baud rates. The use of this extra ISR->DSR buffer reduces the number of DSR calls needed to pass data to the higher I/O layer whilst also minimising the latency in processing individual received characters.


If debugging using RedBootGDB over Ethernet”, due to the increased ISR and DSR latency from the debugging support, the I/O and ISR buffers may need to be very large to minimise the chance of dropped characters at high baud rates (e.g. 230400). For example the CYGPKG_IO_SERIAL test serial3 (against the hosted ser_filter) can, when debugging via BDM (i.e. no RedBoot) and configured with diagnostics at 115200 using UART0, run the test at 230400 using UART1 successfully with CYGNUM_DEVS_SERIAL_MCFxxxx_SERIAL1_BUFSIZE of 128-bytes and a CYGNUM_DEVS_SERIAL_MCFxxxx_SERIAL1_ISR_BUFSIZE of 32-bytes. However, if RedBootGDB over Ethernet” debugging is used, with diagnostics over the Ethernet/RedBoot channel, then the test running at 230400 over UART1 will complete without dropped characters with CYGNUM_DEVS_SERIAL_MCFxxxx_SERIAL1_BUFSIZE of 8192-bytes and a CYGNUM_DEVS_SERIAL_MCFxxxx_SERIAL1_ISR_BUFSIZE of 4096-bytes. If even larger (e.g. 64K) continuous 230400 transfers are required then those buffers need to be further increased. This is an unfortunate side-effect of the ISR/DSR latencies introduced by RedBoot Ethernet based debugging.

Careful application specific tuning of the buffer sizes, and potentially the CYGNUM_DEVS_SERIAL_MCFxxxx_SERIALn_ISR_PRIORITY, may be needed to ensure the desired baud rate and bandwidth requirements are met. If the ISR latency is too high, or the application thread reading data from the serial I/O layer cannot empty the CYGNUM_DEVS_SERIAL_MCFxxxx_SERIALn_BUFSIZE quickly enough, then characters can still be dropped even with large buffers.

It is important that any thread priorities and/or scheduling requirements match the desired UART device use, and that the higher-level buffering and DMA receive buffers are tuned to match the worse-case load.

If the processor HAL is capable of supporting eDMA and the specific UART device is configured to use buffering, by setting a suitable CYGNUM_DEVS_SERIAL_MCFxxxx_SERIALn_BUFSIZE value, then DMA specific options are made available:


This option, when enabled, allows eDMA support for the UART device to be configured via the following configuration options:

If I/O buffering is configured then this option allows eDMA to be used for transmissions. This can greatly reduce the number of ISR and DSR operations needed to support transmission, reducing the CPU load needed.

By default the driver arranges for the UART DMA to interrupt at the highest priority. For lower baud rates this is less critical, but when configured for high baud rates (e.g. 115200 or higher, and especially for ColdFire processors with UARTs with a shallow hardware FIFO) the aim is to minimise the interrupt latency for DMA buffer switch events.


eDMA use for RX is not yet implemented.

There are additional options in the generic serial I/O package CYGPKG_IO_SERIAL which will affect this driver. For example CYGPKG_IO_SERIAL_FLOW_CONTROL and its sub-options determine what flow control mechanism (if any) should be used.

This package also defines some configuration options related to testing. Usually these options are of no interest to application developers and can be ignored.


The generic driver needs some information from other packages about the exact hardware, for example how many UARTs are available and where in memory they can be accessed.

  1. Another package, usually the processor HAL, should provide one or more options CYGHWR_HAL_M68K_MCFxxxx_UART0, CYGHWR_HAL_M68K_MCFxxxx_UART1 or CYGHWR_HAL_M68K_MCFxxxx_UART2. These may be calculated or user-configurable depending on the processor.
  2. The device driver will also look for symbol definitions CYGHWR_HAL_M68K_MCFxxxx_UART0_RTS and CYGHWR_HAL_M68K_MCFxxxx_UART0_CTS, and the equivalents for the other UARTs, to determine whether or not these handshake lines are connected. These may be configuration options or they may be statically defined in a HAL I/O header file. The platform HAL should also implement the generic serial package's interface CYGINT_IO_SERIAL_FLOW_CONTROL_HW if appropriate.
  3. If RTS is connected then the driver will also look for a symbol CYGHWR_HAL_M68K_MCFxxxx_UART0_RS485_RTS. This enables partial support for RS485 communication in that the device driver will arrange for the RTS line to be asserted during a transmit. The driver has no support for more advanced RS485 functionality such as multidrop.

In addition the driver assumes the standard MCFxxxx HAL macros are defined for the UART base addresses and the registers. The driver primarily targets MCF5282-compatible UARTs but there is also some support for functionality available on other members of the Coldfire range, for example the MCF5272's fractional baud rate support.

The HAL can optionally define the HAL_PLF_DEVS_SERIAL_MCFxxx_XMIT_HOOK. macro to provide code called to indicate when the driver transmissions are started and stopped. The macro is passed the base H/W address for the device in use (to identify the port when multiple serial interfaces are active) as well as a boolean indicating the start (true) and stop (false) status for TX.