Register-level GPIO, SPI, I2C, and USART drivers for the STM32 NUCLEO-F411RE, written from scratch against the reference manual with no vendor HAL.
Every peripheral driver in this repository is built by reading the STM32F411 reference manual and configuring the hardware registers directly. There is no STM32 HAL, no CMSIS driver layer, and no third-party libraries: the peripheral register map, bit-field definitions, and NVIC access are all declared in a single MCU header (drivers/Inc/nucleof41xx.h) and driven by hand.
The project demonstrates bare-metal firmware fundamentals: memory-mapped register access, peripheral clock gating, interrupt configuration through the Cortex-M NVIC and EXTI, blocking and interrupt-driven I/O, and a reproducible cross-compiled build. Each driver exposes both polling APIs and interrupt-driven (*_IT) variants with application callbacks.
- Board: STM32 NUCLEO-F411RE
- MCU: STM32F411RE, ARM Cortex-M4F with hardware single-precision FPU
- Compiler flags target the core directly:
-mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard
All drivers live in drivers/src/ with matching headers in drivers/Inc/.
- GPIO (
nucleof41xx_gpio_driver.c): pin mode, output type, speed, and pull configuration; alternate-function mapping; pin and port read/write; toggle; EXTI interrupt configuration with NVIC enable, priority, and IRQ handling. - SPI (
nucleof41xx_spi_driver.c): master configuration, full-duplex send and receive, clock polarity and phase control, software slave management (SSI/SSOE), blocking and interrupt-driven transfers, and overrun handling with an application event callback. - I2C (
nucleof41xx_i2c_driver.c): master send and receive with 7-bit addressing, start/stop generation, address-phase read/write, ACK/NACK management, repeated start, plus interrupt-driven transfers and event/error IRQ handling. Basic slave send/receive is also present. - USART (
nucleof41xx_usart_driver.c): configurable baud rate, word length, parity, and stop bits; blocking and interrupt-driven transmit and receive; flag status and control helpers. - RCC (
nucleof41xx_rcc_driver.c): clock helper routines (for example PLL output clock and APB prescaler resolution) used by the peripheral drivers to compute timing from the active clock tree.
Board support code in bsp/ builds on these drivers: a DS1307 real-time-clock module over I2C (ds1307.c) and an HD44780-style character LCD (lcd.c).
The project cross-compiles from the command line with CMake and arm-none-eabi-gcc; no IDE is required. This is the exact flow that runs in CI.
# one-time toolchain install (Debian/Ubuntu)
sudo apt-get install -y gcc-arm-none-eabi cmake
# configure and build
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=cmake/arm-none-eabi-gcc.cmake -DCMAKE_BUILD_TYPE=Release
cmake --build buildThe build produces build/firmware.elf, build/firmware.bin, and build/firmware.hex, and prints a section size and memory-usage report. The toolchain file cmake/arm-none-eabi-gcc.cmake selects the ARM cross-compiler and links against STM32F411RETX_FLASH.ld with nano.specs/nosys.specs.
Each file in Src/ is a standalone example with its own main(), so exactly one is built at a time. The build defaults to Src/main.c; select a different example with -DAPP:
cmake -S . -B build -DCMAKE_TOOLCHAIN_FILE=cmake/arm-none-eabi-gcc.cmake -DAPP=Src/003spi_tx_arduino.cFlash the resulting binary to the board with the ST-Link command-line tools:
st-flash write build/firmware.bin 0x08000000The application can also be imported into STM32CubeIDE and flashed or debugged over the on-board ST-Link via USB.
.github/workflows/ci.yml runs on every push and pull request:
- Firmware build: installs the ARM GCC toolchain and CMake, configures and builds the firmware exactly as above, and uploads the
.elf,.bin, and.hexas artifacts. A green badge means the firmware genuinely compiles. - Static analysis: runs
cppcheckoverdrivers/andSrc/. This job is currently advisory and does not fail the build.
drivers/Inc/ peripheral driver headers + nucleof41xx.h MCU register map
drivers/src/ peripheral driver sources (GPIO, SPI, I2C, USART, RCC)
bsp/ board support: ds1307 RTC over I2C, HD44780 LCD
Src/ example applications, one main() per file
Startup/ startup_stm32f411retx.s (reset handler, vector table)
cmake/ arm-none-eabi-gcc toolchain file
*.ld linker scripts (STM32F411RETX_FLASH.ld / _RAM.ld)