This repository contains a collection of bare-metal STM32F411 experiments implemented using CMSIS (no HAL or LL drivers). It's my progression of learning Bare Metal MCU programming
Each subdirectory is a self-contained lab focused on one peripheral or system concept and it's practical use
Target MCU: STM32F411 (Cortex-M4) aka The Black Pill
- Understand STM32 at register level
- Learn how peripherals interact (DMA ↔ Timer ↔ GPIO ↔ NVIC)
- Avoid dependency on vendor abstraction layers
- How to use best practices in c++ for maximum efficiency
This is not production firmware — it is a silicon exploration lab.
- 01 - Interrupt Based Binary Counter
- 02 - DMA Based Copying Array
- 03 - PWM Based Breathing Effect
- 04 - USART Based Data Transmission
- 05 - DMA Based USART Circular Buffered Reply
- 06 - I2C Based Commuincation
- 07 - SPI Based MISO Implementation
- 08 - RCC HSE 100MHz Configuration
- 09 - I2C Driver Read-Write Polling Based
- 10 - VL53L0X Driver I2C
- 11 - Non Blocking Interrupt Driven USART Driver
- 12 - FSM Based Non Blocking I2C Driver
Each project directory consists of:
-
main.cpp
Main project source code -
schematic.svg[It may or may not be present based on project itself]
Schematic diagram to show wiring & overall working -
Makefile
A make file responsible for compiling, linking and flashing with one command -
README.md
Explanation of:- what the project demonstrates
- peripheral configuration summary
- register-level flow
Projects are designed to be read independently.
All projects use the same base toolchain:
- Compiler:
arm-none-eabi-gcc - Assembler:
arm-none-eabi-as - Linker script:
/platform/STM32F411CEU6_FLASH.ld - Startup code:
/platform/startup_stm32f411xe.s
Flashing via:
OpenOCD
Build system: simple Makefile per project
-
Install Tools
-> For Debian based OSsudo apt install gcc-arm-none-eabi binutils-arm-none-eabi libnewlib-arm-none-eabi git make openocd
-> For Red Hat based OS
sudo dnf install arm-none-eabi-gcc-cs arm-none-eabi-binutils-cs arm-none-eabi-newlib git make openocd
-> For Arch based OS
sudo pacman -S arm-none-eabi-gcc arm-none-eabi-binutils arm-none-eabi-newlib git make openocd
-
Verify Installation
arm-none-eabi-g++ --version
-
Pull this repository to local system
git pull https://github.com/Muhammad-Hassan-Tariq/Bare-Metal-stm32f411-projects.git
-
Build & Flash
- Change directory to any project listed
sudo make openocd_flash
- OS: Arch Linux
- Editor: Neovim + clangd LSP
- Build: GNU Make
- Debug: GDB + ST-Link V2
- Language: C++ (with C-style register access)
Why C++ for embedded?
- Type safety without performance overhead
- constexpr for compile-time optimization
- Templates for zero-cost abstractions
- Better than C for large firmware projects
