STM32 Based Embedded Car
STM32 Based Embedded Car
This project implements a custom preemptive real‑time kernel on the STM32F401 microcontroller, evolving from a minimal bootloader to robust task management.
It develops memory‑mapped drivers for GPIO, UART, ADC, and I²C, introduces interrupt‑driven context switching via SysTick and PendSV, and adds system calls for user‑mode isolation.
Finally, it integrates a PID-controlled PWM motor loop with encoder feedback under the RTOS, along with UART‑based data logging and Python visualization for interactive tuning .
Stage 1
In the first stage of the project, I established the STM32F401 development environment by installing and configuring GCC, GDB, and OpenOCD, all orchestrated through a make‑based toolchain. I wrote and flashed a minimal bootloader that initialized the flash memory, system clocks, and exception vectors, verifying seamless connectivity via SWD and a simple serial prompt. This initial step ensured reliable hardware bring‑up and laid the foundation for bare‑metal programming on the STM32. By demystifying the startup sequence, I gained a deep understanding of vector tables and low‑level chip initialization routines. This groundwork was critical for subsequent direct peripheral access and system software development.
Stage 2
Next, I developed a suite of memory‑mapped I/O drivers to abstract direct register manipulation for GPIO, UART, ADC, and I²C peripherals. The GPIO driver enabled configurable pin modes for digital inputs and outputs, facilitating LED toggling and button debouncing. Through the UART driver, I established bidirectional serial communication for logging and command interfaces, complete with interrupt‑driven FIFOs. The ADC driver allowed precise analog sampling for sensors like photoresistors, while the I²C master driver communicated with external LCD modules. These modules were thoroughly tested in both polling and interrupt modes, ensuring robust peripheral integration under varying system loads.
Stage 3
Building on these drivers, I introduced comprehensive interrupt handling to support real‑time responsiveness. I configured the SysTick timer to generate periodic system ticks, serving as the heartbeat for task scheduling. External interrupts were mapped to EXTI lines, enabling immediate reactions to external events such as button presses and encoder pulses. To facilitate multitasking, I implemented PendSV‑based context switching and designed custom supervisor calls (SVC) to manage privilege levels and enforce kernel‑user isolation. This phase culminated in a foundational threading model, where basic tasks could yield and resume execution under controlled conditions. Rigorous validation of interrupt priorities and NVIC configurations guaranteed predictable interrupt latency.
Stage 4
In the final stages, I engineered a preemptive real‑time kernel featuring both round‑robin and rate‑monotonic schedulers, complete with thread control blocks and the highest‑locker priority inversion protocol. Within this RTOS, dedicated threads manage PID‑based motor control: a PWM driver outputs precise duty cycles to the motor, while an encoder interrupt handler tracks position and velocity for closed‑loop feedback. Auxiliary threads handle UART logging and LCD updates for real‑time telemetry, and a Python‑based host script visualizes system performance for dynamic tuning. Throughout, I optimized stack usage and prioritized deterministic behavior to meet hard real‑time constraints. This cohesive integration demonstrates a fully autonomous motor control solution running atop a custom RTOS.