C++ peripheral drivers for the STM32F401, built directly on CMSIS headers, no STM32Cube, no C HAL, no libopencm3. Targets C++20 with -fno-exceptions -fno-rtti.
- Each peripheral is a class. Construction configures the hardware and enables the peripheral clock automatically.
- Copy is deleted; move is implemented, ownership of a peripheral can be transferred but not shared.
- Register fields are modeled as scoped enums, so every config value is type-checked at compile time.
None/ sentinel values on enums let you skip fields you don't care about without extra overloads.
GPIO led(GPIOC, 10, GPIO::Mode::Output);
GPIO btn(GPIOC, 12, GPIO::Mode::Input,
GPIO::OutputType::None, GPIO::Speed::None, GPIO::Pull::PullUp);
led.set();
led.toggle();
bool state = btn.get();EXTI interrupt with edge-triggered callback:
btn.setInterruptCallback(GPIO::Edge::Fall, [](void* ctx) {
static_cast<GPIO*>(ctx)->toggle();
}, &led);Shared EXTI lines (EXTI9_5, EXTI15_10) are managed internally , enabling/disabling the NVIC line only when no other pin on that range is active.
UART uart(USART2, {GPIOA, 2}, {GPIOA, 3}); // tx, rx , AF7 defaulted via PinConfig
uart.setStdout(); // routes printf → this UART via _write syscall
uart.send(buf, len, /*timeout_ms=*/100);Baud rate is derived at runtime from SystemCoreClock and the APB prescaler , no magic constants.
Supports: word length, stop bits, parity, oversampling (×8/×16), hardware flow control (RTS/CTS).
| File | Purpose |
|---|---|
common.hpp |
Callback struct, freestanding move() |
gpio.hpp/cpp |
GPIO + EXTI driver |
uart.hpp/cpp |
UART driver |
pinConfig.hpp |
PinConfig , bundles port/pin/AF for passing to UART |
- CMSIS core headers (
core_cm4.h) - STM32F4xx device headers (
stm32f401xe.hviastm32f4xx.h) SystemCoreClockmust be set before constructing a UART (done in startup)