On-chip Subsystems and Peripherals — Hardware Support

Hardware support

On-chip memory

The ST STM32 parts include on-chip SRAM, and on-chip FLASH. The RAM can vary in size from as little as 4KiB to 128KiB. The FLASH can be up to 1024KiB in size depending on model. There is also support in some models for external SRAM and Flash, which eCos may use where available.

Typically, an eCos platform HAL port will expect a GDB stub ROM monitor or RedBoot image to be programmed into the STM32 on-chip ROM memory for development, and the board would boot this image from reset. The stub ROM/RedBoot provides GDB stub functionality so it is then possible to download and debug stand-alone and eCos applications via the gdb debugger using serial interfaces or other debug channels. The JTAG interface may also be used for development if a suitable JTAG device is available. If RedBoot is present it may also be used to manage the on-chip and external flash memory. For production purposes, applications are programmed into external or on-chip FLASH and will be self-booting.


The package CYGPKG_DEVS_FLASH_STM32 ("STM32 Flash memory support") provides a driver for the on-chip flash. This driver conforms to the Version 2 flash driver API, and is automatically enabled if the generic "Flash device drivers" (CYGPKG_IO_FLASH) package is included in the eCos configuration. The driver will configure itself automatically for the size and parameters of the specific STM32 variant which has been selected in the eCos configuration.

Cache Handling

The STM32 does not contain any caches, however, the variant HAL supplies the cyg/hal/hal_cache.h header to satisfy generic code. This header describes zero sized caches and provides null macros for the required functions.

Serial I/O

The STM32 variant HAL supports basic polled HAL diagnostic I/O over any of the on-chip serial devices. There is also a fully interrupt-driven serial device driver suitable for eCos applications for all on-chip serial devices, and where appropriate for the target platform, DMA can be used to reduce the CPU load. The serial driver consists of an eCos package: CYGPKG_IO_SERIAL_CORTEXM_STM32 which provides all support for the STM32 on-chip serial devices. Using the HAL diagnostic I/O support, any of these devices can be used by the ROM monitor or RedBoot for communication with GDB. If a device is needed by the application, either directly or via the serial driver, then it cannot also be used for GDB communication using the HAL I/O support. An alternative serial port should be used instead.

Depending on the STM32Fx series processor configured, the HAL defines CDL interfaces from CYGINT_HAL_STM32_UART0 up to CYGINT_HAL_STM32_UART7 for each of the available UARTs. For F1 series devices the range is 0..4. For F2 and F4[01] family members the range is 0..5 (4 USARTs and 2 UARTs). For F4[23] and F7 devices the range is 0..7 (4 USARTs and 4 UARTs). The platform HAL CDL should contain an implements directive for each such UART that is available for use on the board. This will enable use of the UART for diagnostic and application use.


eCos uses a numbering scheme for UARTs which starts at 0, whereas STM32 documentation uses a numbering scheme which starts at 1. Be sure to check which numbering scheme is relevant when interpreting UART numbers in CDL options or eCos interfaces (eCos numbering) or hardware-specific definitions (ST numbering).

The STM32 USARTs provide TX and RX data lines plus hardware flow control using RTS/CTS for those UARTs that have them connected.

The CYGPKG_IO_SERIAL_CORTEXM_STM32 package provides a number of CDL options that allow the size and location of buffers to be configured. These settings, in conjunction with platform specific manifests for DMA stream/channel configuration, are used to control how data is buffered by the STM32 UART driver. For the options listed below, the relevant UART controller is specified by replacing x with the logical eCos interface number.

This option specifies the size of both the input and output buffers for the common serial I/O driver layer, which sits above the low-level STM32 specific driver. When using high baud rates, to avoid overrun, the buffer size may need to be increased to cope with the application serial handler thread switching latency. If the device should only be used in polled mode then this option can be disabled by setting the value to 0. Typically the device driver will run in interrupt or DMA mode (as configured by the platform), such that it will perform some buffering of both incoming and outgoing data.
By default the common serial I/O buffers of the size specified by the CYGNUM_IO_SERIAL_CORTEXM_STM32_SERIALx_BUFSIZE option are held in the main application data memory as defined by the active CYG_HAL_STARTUP configuration. For the majority of standard serial uses this will be sufficient, and this option can remain disabled. However, this option can be enabled to force the buffers to be placed into on-chip SRAM, which may be required when using very high communication rates with applications that use off-chip data memory. This option is ignored if the CYG_HAL_STARTUP configuration already selects the on-chip SRAM for application data.

This option controls the size of the low-level UART driver RX buffer.

When interrupt transfers are being used then this option specifies the size of the RX buffer used to provide FIFO-alike operation to minimise the possibility for dropped characters when waiting for the UART DSR to be processed. A minimal buffer size is enforced since if the processor is using off-chip RAM then it may be too slow to handle higher baud rates.

For DMA enabled RX this buffer is used to reduce the overall STM32 serial driver ISR and DSR system overhead. For DMA an interrupt will only be generated when 50% of the buffer size has been received, or when the receiver has been idle for some time. This reduces overall system load at the expense of making the driver slightly less “responsive” for non-continuous transfers. The DMA suport actually splits the buffer into two equal sized buffers and uses the hardware double-buffer support to automatically switch between buffers.

Serial overrun mitigation

Ideally it is prudent for UART connections to use hardware flow control where possible, since it provides a mechanism for both ends of a connection to throttle the data flow to avoid buffer overrun. This is especially true when using very high baud rates, since many characters could be received within the ISR, DSR and scheduling latencies of a running application.

If H/W flow control is not available then, especially when using higher baud rates, it is critical that the application developer understands the serial transfer requirements, and that the STM32 UART driver processing method and configured buffering is tuned to avoid (or at least minimise the possibility of) overrun. When H/W flow control is not being used then it may not be possible to avoid overrun completely, since the remote end can always transmit more data than the receiver has buffer space for. The possibility of overrun can be mitigated by ensuring a suitable software “throttling” handshake mechanism between the transmitted and receiver, or by ensuring that the receiver has sufficient buffer space at both the low-level driver reception layer (CYGNUM_IO_SERIAL_CORTEXM_STM32_SERIALx_RXBUFSIZE) and the higher-level common serial/application layer (CYGNUM_IO_SERIAL_CORTEXM_STM32_SERIALx_BUFSIZE) to cope with the worst-case scheduling latency of the application.


When DMA usage is configured by the specific STM32 platform support (implemented by provision of a suitably named manifest describing the stream/channel configuration), the UART DSR MUST have copied data out of the RX buffer into the common serial buffers BEFORE the second DMA buffer has been filled. For example, at 10.5MHz over 1000 8N1 characters can be received in 1-millisecond. The buffer depth should be tuned accordingly to cope with the worst-case UART driver DSR latency to ensure that the automatic hardware switch on DMA buffer fill does not cause data which has not yet been copied to the higher serial layer to be overwritten.

Further, when using DMA, the RX IDLE support is used to force data to be passed to the common serial layer in a timely fashion. This avoids the eCos receiver application having to wait for a complete DMA buffer fill for pending data, which is useful for “character” based serial protocols. The downside is that due to the IDLE implementation having to disable the DMA stream temporarily, if the remote end transmits multiple characters shortly after IDLE is detected by the STM32 receiver then the DMA ISR latency may affect whether RX overrun occurs before the handler can re-enable the DMA stream. The CYGNUM_IO_SERIAL_CORTEXM_STM32_SERIALx_RXINTR_PRI configuration option can be tuned to ensure that the DMA interrupt priority is sufficiently high to minimise the possibility of overrun.



The I/O controller found on newer STM32 designs (e.g. F7, H7 or L4 families) only supports divided transactions with repeated START conditions. The hardware is not capable of splitting a transaction without generating a START.

So all transaction calls between the cyg_i2c_transaction_begin() and cyg_i2c_transaction_end() calls should use true for the send_start parameter.


The STM32 HAL relies on the architectural HAL to provide support for the interrupts directly routed to the NVIC. The cyg/hal/var_intr.h header defines the vector mapping for these.

In addition support is present for interrupts EXTI5 to EXTI15 that share NVIC vectors. These are decoded by a springboard ISR routine that decodes the interrupt from the EXTI_PR register and calls hal_deliver_interrupt in the architectural HAL to deliver it to the real ISR. Variant specific macros are also defined to permit the masking and configuration of these interrupts.


The variant HAL provides support for packaging the configuration of a GPIO line into a single 32-bit descriptor that can then be used with macros to configure the pin and set and read its value. Details are supplied later.


The variant HAL provides support for MultiMediaCard (MMC) and Secure Digital (SD) media cards via the CDL component CYGPKG_HAL_STM32_MMCSD ("On-chip MMC/SD driver"). This makes use of the STM32 SDIO on-chip interface. NOTE: No support is yet in place for Secure Digital Input Output (I/O) cards.

If enabled this driver allows use of MultiMedia Cards (MMC cards) and Secure Digital (SD) flash storage cards within eCos, exported as block devices. This makes them suitable for use as the underlying devices for filesystems such as FAT.

This driver provides the necessary support for the generic MMC bus layer within the CYGPKG_DEVS_DISK_MMC package to export a disk block device. The disk block device is only available if the generic disk I/O layer found in the package CYGPKG_IO_DISK is included in the configuration.

The block device may then be used as the device layer for a filesystem such as FAT. Example devices are "/dev/mmcsd0/1" to refer to the first partition on the card, or "/dev/mmcsd0/0" to address the whole device including potentially the partition table at the start.

If the driver is enabled, the following options are available to configure it:

This indicates that the driver should operate in interrupt-driven mode if possible. This is enabled by default if the eCos kernel is enabled. Note though that if the driver finds that global interrupts are off when running, then it will fall back to polled mode even if this option is enabled. This allows for use of the MMC/SD driver in an initialisation context.
This option enables the power-saving feature that will disable the SD clock when the device is idle. This feature can normally be safely enabled on all STM32 platforms.

USB OTG Controllers

The STM32 series supports two different USB OTG controller implementations: OTG1 FS and OTG2 HS. If a specific STM32 microcontroller contains both controllers then configuration support is provided to enable you to select specific operation modes for each.

If only CYGPKG_IO_USB_HOST host support is enabled then both controllers will operate in host mode. Similarly, if only CYGPKG_IO_USB_TARGET is enabled then both controllers will operate in peripheral mode.

If both options are enabled then the controllers will default to host mode. To force a specific controller into peripheral mode then CYGHWR_DEVS_USB_STM32_OTG_FS or CYGHWR_DEVS_USB_STM32_OTG_HS should be set to "TARGET".

If only one controller is in target mode, then CYGHWR_IO_USB_TARGET_PCDI_DEFAULT, and thus CYGHWR_IO_USB_TARGET_PCDI, will be set to that controller. If both controllers are in target mode then the FS controller will be used as the default. If you want to select the other controller then this will need to be set explicitly.


The STM32 HS OTG2 controller support is currently limited to use in FS speed mode only. In addition, dynamically changing controller mode between host and target is not supported at this time.


eCos includes RTC (known in eCos as a wallclock) device drivers for the on-chip RTC in the STM32 family. For the F1 processor family this is located in the package CYGPKG_DEVS_WALLCLOCK_STM32 ("STM32 RTC wallclock support"), and for the F2, F4, F7, L4 and H7 processor families this is located in the package CYGPKG_DEVS_WALLCLOCK_STM32F2 ("STM32F2 RTC wallclock support").

On the F1 processor family, the wallclock driver can be configured with three different clock sources using the CDL configuration option CYGHWR_DEVS_WALLCLOCK_STM32_RTC_SOURCE ("RTC clock source"): LSE for the low-speed 32.768KHz external clock, LSI for the low-speed internal clock, or HSE_128 for the high-speed external clock with a fixed divider of 128. The decision of which source to use depends on the desired clock stability and hardware configuration, and power requirements. Consult the STM32 documentation for more details.

The F2, F4, F7, L4 and H7 processor families are similar, except that the LSI clock is at 32KHz clock, and the CDL option name is CYGHWR_DEVS_WALLCLOCK_STM32F2_RTC_SOURCE.

Profiling Support

The STM32 HAL contains support for gprof-base profiling using a sampling timer. The default timer used is Timer 6, which is one of the basic timers, leaving the more complex timers for application code. The timer used is selected by a set of #defines in src/stm32_misc.c which can be changed to refer to a different timer if required. This timer is only enabled when the gprof profiling package (CYGPKG_PROFILE_GPROF) is included and enabled in the eCos configuration, otherwise it remains available for application use.

Clock Control

The platform HAL must provide the input clock frequency (CYGARC_HAL_CORTEXM_STM32_INPUT_CLOCK) in its CDL file. This is then combined with the following options defined in this package to define the default system clocks:

This defines the source of the input to the PLL that generates the main system clock. There are two possible sources: the HSE selects the high speed external oscillator, and the HSI selects the high speed internal oscillator. This option defaults to the HSE.
This indicates whether the HSE clock should be started at all. If the system clock is running solely from the HSI clock, there may be no need for an HSE clock, and no crystal connected to it. In that scenario, this option can be disabled. This is usually set by the platform HAL.
This option specifies how much the clock from the input source defined by CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_SOURCE is divided down by, before being used as an input for the PLL. On non-connectivity parts, you can only divide by 2 or 1. On other F1 parts, if using HSI as the clock source, then that is automatically divided by 2. If using HSE as the clock source, then this value corresponds to the PREDIV1 field of register RCC_CFGR2. On F2 and F4 parts, this value corresponds to the PLLM field of RCC_PLLCFGR.
This defines the factor by which the PLL will multiply the selected input clock, after being divided by CYGHWR_HAL_CORTEXM_STM32_CLOCK_PLL_PREDIV. It ranges from 2 to 16 on F1 parts, and 2 to 432 on F2 and F4 parts, and defaults to 9, which is intended to give a 72MHz system clock on those boards with an 8MHz input. On the F1 it corresponds to the PLLMUL field of RCC_CFGR. On the F2/F4 it corresponds to the PLLN field of RCC_PLLCFGR.
This setting is only applicable to the F2 and F4 family of processors. This defines the divider applied to the PLL output for use as the SYSCLK. It can only have values 2, 4, 6 or 8 and defaults to 4. This setting corresponds to the PLLP field of RCC_PLLCFGR.
This defines the divider applied to the prescaler for all peripheral clocks. The HCLK fed to the AHB bus and other peripherals is taken directly from this output. Other peripheral clocks are derived by dividing it further. This can take values between 1 and 512 in powers of 2, the default value is 1.
This defines the prescaler divider for the peripheral clock passed to peripherals on the APB1 bus. It can take values between 1 and 16 in powers of 2, the default value is 2.
This defines the prescaler divider for the peripheral clock passed to peripherals on the APB2 bus. It can take values between 1 and 16 in powers of 2, the default value is 1.
This setting only applies to the F2 and F4 family of processors. It defines the divider used to divide down the PLL output clock (VCO clock) for use by the USB OTG FS, SDIO and RNG peripherals. USB OTG FS requires a 48MHz clock and other peripherals require a clock no greater than 48MHz. The allowable values range from 4 to 15 and the default is 10.

The actual values of these clocks, in Hz, is stored in global variables hal_stm32_sysclk, hal_stm32_hclk, hal_stm32_pclk1, hal_stm32_pclk2 and for the F2/F4/F7 processor families only, hal_stm32_qclk. The clock supplied to the SysTick timer, HCLK/8, is also assigned to hal_cortexm_systick_clock. These variables are used, rather than configuration options, in anticipation of future support for power management by varying the system clock rate.

Note that when changing or configuring any of these clock settings, you should consult the relevant processor datasheet as there may be both upper and lower constraints on the frequencies of some clock signals, including intermediate clocks. There are also some clocks where, while there is no strict constraint, clock stability is improved if values are chosen wisely. Finally, be aware that increasing clock speeds using this package may have an effect on platform specific properties, such as memory timings which may have to be adjusted accordingly.