Bare-Metal RTOS on STM32
A preemptive real-time kernel written from the reset vector up, with context-switch latency measured on a logic analyzer.
Startup and drivers
I wrote the linker script, vector table, and reset handler for the STM32F446.
The handler copies .data, zeroes .bss, and configures the clock tree.
Setting flash wait states before raising the clock frequency is one of the
ordering details that matters at startup.
The register-level drivers cover GPIO, UART with ring buffers, SysTick, I²C, and SPI. Logic-analyser captures let me compare bus activity with the expected transaction, including the start, address, ACK, and data phases of I²C.
Scheduling
The kernel uses task control blocks, per-task stacks, and PendSV context switching. SysTick drives time slicing, while a priority scheduler chooses the next task. A blocked task yields the CPU. Mutexes use priority inheritance to handle priority inversion.
Proof on wires
Each task toggles a distinct GPIO so I can inspect scheduling on the logic
analyser. DWT->CYCCNT measures context-switch cost in cycles. Fault registers
such as CFSR and HFSR help narrow down stack-frame and exception-return errors
in GDB.