STM32F4 Platform Guide

Overview

The STM32F4 platform provides support for STM32F4 series microcontrollers from STMicroelectronics. This platform targets high-performance ARM Cortex-M4 MCUs with DSP and FPU capabilities, suitable for a wide range of embedded applications.

Supported Variants:

  • STM32F407 (default)

  • STM32F429

  • STM32F446

Key Features:

  • ARM Cortex-M4 core with FPU

  • Up to 180 MHz operation

  • Up to 2 MB Flash, 256 KB SRAM

  • Rich peripheral set

  • DMA support

  • FreeRTOS integration

Platform Capabilities

Supported Peripherals

The STM32F4 platform supports the following peripherals:

Peripheral

Max Instances

Capabilities

UART/USART

6

Async/Sync TX/RX, DMA, hardware flow control

GPIO

16 pins per port

Input/Output, alternate functions, interrupts

SPI

6

Master/Slave, DMA, NSS management

I2C

3

Master/Slave, DMA, 10-bit addressing

Timer

14

General-purpose, advanced, basic timers

ADC

3

12-bit resolution, DMA, multi-channel

DAC

2

12-bit resolution, DMA

CAN

2

CAN 2.0A/B, up to 1 Mbps

USB

2

USB OTG FS/HS

SDIO

1

SD/MMC card interface

RTC

1

Calendar, alarm, tamper detection

Watchdog

2

Independent and window watchdog

Platform Limitations

  • Clock Configuration: Requires proper clock tree configuration

  • Pin Multiplexing: Limited pins require careful planning

  • DMA Channels: Limited DMA channels may require prioritization

  • Power Consumption: Higher power consumption than low-power variants

  • Temperature Range: Standard range (-40°C to +85°C)

Build Instructions

Prerequisites

  • CMake 3.15 or higher

  • ARM GCC toolchain (arm-none-eabi-gcc)

  • Python 3.7+ (for build scripts)

  • OpenOCD or ST-Link utilities (for flashing)

Toolchain Installation

Windows:

# Download ARM GCC from ARM website
# Add to PATH
$env:PATH += ";C:\Program Files (x86)\GNU Arm Embedded Toolchain\bin"

Linux:

# Ubuntu/Debian
sudo apt-get install gcc-arm-none-eabi

# Arch Linux
sudo pacman -S arm-none-eabi-gcc

macOS:

# Using Homebrew
brew install --cask gcc-arm-embedded

Basic Build

# Configure for STM32F4 platform
CMake -B build -DPLATFORM=STM32 -DSTM32_CHIP=STM32F407 \
      -DCMAKE_TOOLCHAIN_FILE=CMake/toolchains/arm-none-eabi.CMake

# Build
CMake --build build

# Generate binary
arm-none-eabi-objcopy -O binary build/app.elf build/app.bin

Using Build Scripts

# Build for STM32F4
python scripts/nexus.py build --platform STM32 --chip stm32f407

# Build with specific configuration
python scripts/nexus.py build --platform STM32 --chip stm32f407 \
       --config Release

Kconfig Options

Platform Selection

CONFIG_PLATFORM_STM32=y
CONFIG_PLATFORM_NAME="STM32"

Chip Selection

# STM32F4 family
CONFIG_STM32F4=y

# Specific variant
CONFIG_STM32F407=y
# CONFIG_STM32F429 is not set
# CONFIG_STM32F446 is not set

CONFIG_STM32_CHIP_NAME="STM32F407xx"

Platform Settings

# Platform identification
CONFIG_STM32_PLATFORM_NAME="STM32 Platform"
CONFIG_STM32_PLATFORM_VERSION="1.0.0"

# Logging
CONFIG_STM32_ENABLE_LOGGING=y
CONFIG_STM32_LOG_LEVEL=3

# Statistics
CONFIG_STM32_ENABLE_STATISTICS=y

# Memory alignment
CONFIG_STM32_BUFFER_ALIGNMENT=4

Resource Managers

# DMA channels
CONFIG_STM32_DMA_CHANNELS=8

# ISR slots
CONFIG_STM32_ISR_SLOTS=64

Peripheral Configuration

UART Configuration:

CONFIG_STM32_UART_ENABLE=y
CONFIG_STM32_UART_MAX_INSTANCES=6
CONFIG_INSTANCE_STM32_UART_1=y
CONFIG_UART1_BAUDRATE=115200
CONFIG_UART1_DATA_BITS=8
CONFIG_UART1_STOP_BITS=1
CONFIG_UART1_PARITY_NONE=y
CONFIG_UART1_MODE_DMA=y
CONFIG_UART1_TX_BUFFER_SIZE=256
CONFIG_UART1_RX_BUFFER_SIZE=256
CONFIG_UART1_DMA_TX_CHANNEL=4
CONFIG_UART1_DMA_RX_CHANNEL=5
CONFIG_UART1_TX_PIN=9
CONFIG_UART1_RX_PIN=10
CONFIG_UART1_TX_PORT="GPIOA"
CONFIG_UART1_RX_PORT="GPIOA"

GPIO Configuration:

CONFIG_STM32_GPIO_ENABLE=y

SPI Configuration:

CONFIG_STM32_SPI_ENABLE=y

I2C Configuration:

CONFIG_STM32_I2C_ENABLE=y

OSAL Configuration

# FreeRTOS backend
CONFIG_OSAL_FREERTOS=y
CONFIG_OSAL_BACKEND_NAME="FreeRTOS"
CONFIG_OSAL_TICK_RATE_HZ=1000
CONFIG_OSAL_HEAP_SIZE=32768
CONFIG_OSAL_MAIN_STACK_SIZE=2048
CONFIG_OSAL_MAX_PRIORITIES=32

Linker Configuration

# Memory layout for STM32F407
CONFIG_LINKER_RAM_START=0x20000000
CONFIG_LINKER_RAM_SIZE=0x00020000    # 128 KB
CONFIG_LINKER_FLASH_START=0x08000000
CONFIG_LINKER_FLASH_SIZE=0x00100000  # 1 MB

Hardware Setup

Development Boards

Recommended Boards:

  • STM32F4DISCOVERY (STM32F407VGT6)

  • NUCLEO-F446RE

  • Custom boards with STM32F4 series

Pin Configuration

UART1 Pins (Default):

TX: PA9  (USART1_TX)
RX: PA10 (USART1_RX)

SPI1 Pins:

SCK:  PA5  (SPI1_SCK)
MISO: PA6  (SPI1_MISO)
MOSI: PA7  (SPI1_MOSI)
NSS:  PA4  (SPI1_NSS)

I2C1 Pins:

SCL: PB6 (I2C1_SCL)
SDA: PB7 (I2C1_SDA)

Power Supply

  • VDD: 1.8V to 3.6V

  • VDDA: Analog supply (same as VDD or separate)

  • VBAT: Battery backup for RTC (optional)

Recommended Power Setup:

  • Use 3.3V regulated supply

  • Add decoupling capacitors (100nF) near each VDD pin

  • Add bulk capacitor (10µF) near power input

Clock Configuration

External Crystal:

  • HSE: 8 MHz (typical for discovery boards)

  • LSE: 32.768 kHz (for RTC)

PLL Configuration for 168 MHz:

/* HSE = 8 MHz */
/* PLL_M = 8, PLL_N = 336, PLL_P = 2, PLL_Q = 7 */
/* SYSCLK = 168 MHz */
/* AHB = 168 MHz, APB1 = 42 MHz, APB2 = 84 MHz */

Example Projects

Basic UART Example

#include "hal/nx_uart.h"
#include "hal/nx_factory.h"
#include "osal/nx_osal.h"

int main(void) {
    /* Initialize OSAL */
    nx_osal_init();

    /* Get UART instance */
    nx_uart_t* uart = nx_factory_uart(1);  /* UART1 */
    if (!uart) {
        return -1;
    }

    /* Initialize UART */
    nx_lifecycle_t* lc = uart->get_lifecycle(uart);
    if (lc->init(lc) != NX_OK) {
        return -1;
    }

    /* Send data */
    nx_tx_async_t* tx = uart->get_tx_async(uart);
    const uint8_t data[] = "Hello, STM32F4!";
    size_t len = sizeof(data) - 1;
    tx->transmit(tx, data, len);

    /* Start RTOS scheduler */
    nx_osal_start();

    /* Should never reach here */
    return 0;
}

FreeRTOS Task Example

#include "osal/nx_osal.h"
#include "hal/nx_gpio.h"

void led_task(void* param) {
    nx_gpio_t* gpio = nx_factory_gpio(0);
    nx_lifecycle_t* lc = gpio->get_lifecycle(gpio);
    lc->init(lc);

    /* Configure LED pin */
    nx_gpio_config_t config = {
        .pin = 13,  /* PD13 on STM32F4DISCOVERY */
        .mode = NX_GPIO_MODE_OUTPUT,
        .pull = NX_GPIO_PULL_NONE,
        .speed = NX_GPIO_SPEED_LOW
    };
    gpio->configure(gpio, &config);

    /* Blink LED */
    while (1) {
        gpio->write_pin(gpio, 13, 1);
        nx_osal_delay_ms(500);
        gpio->write_pin(gpio, 13, 0);
        nx_osal_delay_ms(500);
    }
}

int main(void) {
    nx_osal_init();

    /* Create task */
    nx_osal_task_create(led_task, "LED", 512, NULL, 1, NULL);

    /* Start scheduler */
    nx_osal_start();
    return 0;
}

DMA UART Example

#include "hal/nx_uart.h"

void uart_dma_example(void) {
    nx_uart_t* uart = nx_factory_uart(1);
    nx_lifecycle_t* lc = uart->get_lifecycle(uart);
    lc->init(lc);

    /* DMA is configured via Kconfig */
    /* CONFIG_UART1_MODE_DMA=y */

    /* Transmit with DMA */
    nx_tx_async_t* tx = uart->get_tx_async(uart);
    const uint8_t data[] = "DMA Transfer";
    size_t len = sizeof(data) - 1;
    tx->transmit(tx, data, len);

    /* DMA handles transfer in background */
}

Debugging Procedures

Using OpenOCD

Install OpenOCD:

# Linux
sudo apt-get install openocd

# macOS
brew install openocd

Start OpenOCD:

# For STM32F4DISCOVERY
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg

Connect GDB:

arm-none-eabi-gdb build/app.elf
(gdb) target remote localhost:3333
(gdb) monitor reset halt
(gdb) load
(gdb) continue

Using Visual Studio Code

Create .vscode/launch.json:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug STM32F4",
            "type": "cortex-debug",
            "request": "launch",
            "servertype": "openocd",
            "cwd": "${workspaceRoot}",
            "executable": "${workspaceRoot}/build/app.elf",
            "device": "STM32F407VG",
            "configFiles": [
                "interface/stlink.cfg",
                "target/stm32f4x.cfg"
            ]
        }
    ]
}

Serial Console

Connect to UART:

# Linux
screen /dev/ttyUSB0 115200

# Windows (using PuTTY)
# COM port, 115200 baud, 8N1

Troubleshooting

Common Issues

Build Fails with “arm-none-eabi-gcc not found”:

Solution: Install ARM GCC toolchain and add to PATH.

Flash Fails with “Error: init mode failed”:

Solution: Check ST-Link connection, try different USB port, update ST-Link firmware.

UART Not Working:

Solution: Verify pin configuration matches hardware, check baud rate, ensure clock is configured.

DMA Not Transferring:

Solution: Verify DMA channel configuration, check buffer alignment, ensure DMA clock is enabled.

Clock Configuration Issues

If system doesn’t start or runs at wrong speed:

  1. Verify HSE frequency matches hardware (usually 8 MHz)

  2. Check PLL configuration

  3. Ensure flash wait states are configured for clock speed

  4. Verify voltage regulator scale setting

Memory Issues

Stack Overflow:

Solution: Increase stack size in Kconfig (CONFIG_OSAL_MAIN_STACK_SIZE).

Heap Exhausted:

Solution: Increase heap size (CONFIG_OSAL_HEAP_SIZE) or use static allocation.

Linker Error “region RAM overflowed”:

Solution: Reduce memory usage or use external RAM.

Performance Optimization

  • Enable compiler optimizations (-O2 or -O3)

  • Use DMA for data transfers

  • Enable instruction and data caches

  • Use FPU for floating-point operations

  • Optimize interrupt priorities

See Also