
Download STM32CubeIDE, a free IDE from STMicroelectronics for Windows, Linux, and macOS, requiring license acceptance and account signup before downloading 729 megabytes.
Install CubeIDE by extracting the package, selecting an installation location, and installing ST-Link and SEGGER J-Link drivers, then set up the workspace and allow firewall access.
Download and organize the essential documents for bare-metal development on STM32F4, including the reference manual RM383, the datasheet, and the Nucleo user guide.
Begin a bare-metal stm32 project in stm32cubeide and locate the user LED on the nucleo board, which is pa5—port a pin 5—and prepare to configure it to turn on.
Define peripheral and GPIO base addresses from the stm32 memory map, enable clocks via RCC on the AHB1 bus, and prepare GPIOA registers to control LED pin 5.
Identify and define STM32 peripheral registers from the reference manual, enabling port A via RCC AHB1ENR, and configure PA5 as output with MODER and ODR.
Configure GPIOA clock, set PA5 as output, and drive PA5 high to light the LED; then toggle PA5 with a delay loop using bitwise OR to preserve other register bits.
Convert hardware registers into a structured memory map by defining GPIO_TypeDef and RCC typedefs, then access registers through base address typecasts and the arrow operator to blink the led.
Explore the gpio module: pins form ports (pa1, pd7), support general purpose and alternate functions, and use direction and data registers, buses ahb/apb, and clock sources rc, crystal, and pll.
Develop a GPIO output driver for STM32F4 using chip headers, enable GPIOA clock, configure PA5 as output, and toggle the LED to verify bare-metal operation.
Learn to control stm32 gpio outputs using the bit set/reset register (bsrr) to set and reset pins with bs and br bits, as demonstrated for pa5.
Develop a gpio input driver for STM32 by enabling Port C clock, configuring PC13 as input, reading the IDR, and responding to an active-low push button to control the LED.
Explore uart and usart basics, including serial versus parallel data, and synchronous and asynchronous modes. Learn baud rate, start bits, stop bits, parity, word length, and rx/tx configuration.
Develop a uart2 transmitter driver for stm32 bare-metal, enabling gpio pa2 as af07, configuring apb1 clocks, setting baud rate, and enabling the uart transmitter.
Write and test the uart2_write function by waiting for TXE, then writing to USART2->DR. Verify with realterm receiving characters and prepare to use printf for sentences in the next lesson.
Retarget printf on STM32 bare-metal by reimplementing __io_putchar to route characters to uart_write, enabling printf outputs like 'hello from STM32F4' and preparing uart.c and uart.h for reuse.
We modularize the UART code by creating uart.c and uart.h, moving init, write, and baud rate logic from main.c into dedicated modules and test on the STM32.
Develop uart2 receive driver by duplicating previous uart project, configure pa3 as rx with correct moder and af, enable rx, and implement uart2_read that returns USART2->DR after RXNE.
Test the uart2_rx driver by initializing uart2_tx_rx, reading received characters into a key variable, and validating LED on/off via GPIOA pin 5 with real-time monitoring.
Explore how sensors translate physical quantities into digital values for microcontrollers using an ADC, and how resolution and Vref determine step size and steps.
Discover adc independent modes on stm32f4, including single channel and multi-channel conversions (single and continuous), plus the injected mode, with a single adc supporting up to 16 channels.
Develop a single conversion adc driver for STM32, enabling adc1 on APB2, configuring PA1 as analog, and starting conversions with SWSTART to read from the adc data register.
Enable continuous conversion by setting the CR2_CONT bit in ADC1->CR2 and define CR2_CONT to run conversions continuously, with values viewable in realTerm.
The SysTick timer, a core ARM Cortex peripheral, provides a 24-bit down counter for timing delays and real-time operating system ticks using registers like STCVR, STCSR, and STRVR.
Develop a precise millisecond delay using the SysTick timer on Cortex M4, configuring the load value, clock source, and count flag to blink an LED and print serial messages.
STM32 timers and counters, including input capture, output compare, and one-pulse modes; learn key registers (cnt, arr, psc) and how prescalers shape timer clocks.
Configure prescaler, auto-reload, and capture/compare registers; enable timers and monitor the UIF flag; configure channel modes for input capture or output compare.
Develop and test a general-purpose timer driver for STM32F4, enabling timer2 on APB1, configuring prescaler and auto reload for 1 Hz interrupts, and using the UIF flag to toggle LED.
Develop a timer output-compare driver to toggle PA5 led using timer2 channel 1 in toggle mode, configuring PA5 as AF TIM2_CH1 and enabling the timer and channel.
Develop a timer input capture driver to measure input frequency by capturing the PA5 toggle with TIM3 channel 1 on PA6, configuring prescaler and edge settings.
Learn how interrupts work on Cortex-M STM32, including ISR handling, NVIC management, vector table lookup, EXTI lines, and priority concepts.
Develop a gpio interrupt driver for stm32 by configuring exti on pc13 with falling edge, enabling clocks, syscfg, and nvic, and testing the input interrupt.
Implement and test the gpio interrupt driver by creating the exti interrupt handler, verifying line 13 using the pending register, and invoking a callback to toggle an led.
Develop a uart receiver interrupt driver by enabling the rxneie interrupt in cr1, configuring the USART2 NVIC, and implementing USART2_IRQHandler to read the data register and invoke a callback.
Develop an adc interrupt driver for stm32 by enabling end-of-conversion interrupts in CR1 and nvic, implementing the adc_irq_handler, and testing with pa1.
Develop a systick interrupt driver by configuring the systick timer in interrupt mode, loading 16 million cycles, and toggling an led at 1 hz via a callback.
Develop an interrupted timer driver by enabling TIM2 UIE in DIER, configuring the NVIC, and implementing TIM2_IRQHandler to clear UIF and run a 1 Hz timer callback.
Explore the dma module in stm32 microcontrollers, covering streams, channels, and memory and peripheral ports. Configure priorities, addresses, data width, circular mode, and burst to optimize transfers.
Develop a dma driver for the uart to transfer data via dma, enabling usart2 tx with dma1 stream6 channel4, memory-to-peripheral transfer, and dma interrupt options.
Configure the uart transmitter dma driver from scratch by enabling dma clock, selecting channel four, setting memory-to-peripheral transfers, and enabling interrupts in bare-metal stm32.
Test the bare-metal uart transmitter via DMA1 stream 6 from a memory buffer to USART2_DR, enabling uart tx and a transfer-complete interrupt.
Explore the I2C protocol, its two-wire interface with SCL and SDA, master–slave roles, start and stop conditions, address and data frames, pull-up resistors, and clock speed and duty cycle options.
Implement an I2C1 driver by initializing clocks, configuring PB8/PB9 as alternate function open-drain with pull-ups, and setting CCR and TRISE for standard-mode 100 kHz.
Implement an I2C byte read function for an STM32, guiding the slave address, memory address, and data storage, with checks for busy state, start and restart conditions, and RXNE handling.
Implement an I2C burst read function to read multiple bytes from a slave by writing the memory address, issuing a restart, and reading with ACK handling.
Implement the I2C burst write function on STM32, sending slave address, memory address, and data bytes to I2C slave using a for loop and TXE/BTF flags, then stop.
Configure the ADXL345 accelerometer over i2c, connect scl to pb8 and sda to pb9, set data format to ±4g, and enable measurement after verifying device id.
Test the adxl345 I2C driver by initializing I2C and accelerometer, reading X0–X1, Y0–Y1, Z0–Z1, and converting to g with the 4G scale factor on STM32.
Discover the SPI protocol: a synchronous full-duplex master-slave interface using MOSI, MISO, SCK and SS, with CPOL/CPHA modes and NSS options, including TI mode.
Develop an spi driver to configure the adxl345 accelerometer on stm32, using spi1 with pa5, pa6, pa7 and pa9, enabling apb2 clock and af05.
Configure the SPI1 module by enabling the APB2 clock, setting baud rate, CPOL/CPHA, master mode, eight-bit data, software slave management, and finally enabling the SPI peripheral.
Implement the SPI transmit function by polling the TXE flag, writing to the data register, waiting for BSY to clear, and clearing the overrun flag via data and status reads.
Implement spi receive function by sending dummy data, waiting for rxne flag, reading data from spi1 data register into a buffer, and managing pa9 slave select with cs_enable and cs_disable.
Configure the adxl345 accelerometer via spi: implement adxl_write and adxl_read using multibyte support, initialize spi, manage cs lines, and read six axis data bytes (x0/x1, y0/y1, z0/z1) over spi.
Test the ADXL345 driver by building the SPI project, wiring PA9 CS, PA6 SDO, PA7 SDA, PA5 SCL, and observing live accelerometer values.
Are you tired of Copying and Pasting code you don't understand?
With a programming based approach, this course is designed to give you a solid foundation in bare-metal firmware development for ARM-based microcontrollers . The goal of this course is to teach you how to navigate the microcontroller reference manual and datasheet to extract the right information to professionally build peripheral drivers and firmware. To achieve this goal, no libraries are used in this course, purely bare-metal embedded-c and register manipulations.
Still keeping it simple, this course comes in different ARM Cortex-M development boards so that students can put the techniques to practice using an ARM Cortex-M development board of their choice. This version of the course uses the STMicroelectronics STM32F4-NUCLEO which has an ARM Cortex-M4 microcontoller.
So with that understood, let me tell you…
Exactly What You’re Getting
This is dramatically different from any course you have ever taken because it’s more of a professional hands-on “field guide” to stm32 bare metal firmware development.
The reason why is because there’s no fluff or filler. It immediately gets down to the actual subject, showing you exactly what to do, how to do it, and why.
Plus, it’s easy.
And you’ll immediately “get” the entire mythology I personally use to build firmware for consumer devices in my professional life.
It's About MORE Than Just Getting the Code to Work
See, this course will change your professional life forever. Here is what one student had to say about the course :
"I would suggest this course for all the beginners. The concepts have been covered in the right sequence.And also the best part of this lecture series is getting to know how to explore the reference manual and datasheets."
Here is what another student had to say :
"Extremly helpful to get to understand the uC programming deeper! For me it is much easier from now to develop code because I undertstand the base behind, so I'm more confident and more experienced to develop and debug the code. Really, this course is very useful to link the hardware knowledge with the coding skills. This fills the gap between them. Thanks for it! :)"
A third student :
"I am a professional semiconductor chipset application engineer with 30 years in global embedded product design in system applications. I can say this teacher is very straight forward by sharing his many years knowledge to the students with his true heart. Yes. I love his teaching pace and style!"
Taken by 8000+ Students with 1000+ Reviews
If at least one of the following applies to you then keep reading if not then simply skip this course:
" Escape From "
Copying/Pasting code you don’t understand
Using third party libraries and header files like HAL, LL and StdPeriph
Experiencing bugs you don’t understand
Being afraid of technical documentations like the reference manual and datasheet of the chip
Imposter syndrome
" Arrive At "
Building every single line of code from scratch by writing to the microcontroller’s memory space directly.
Using No third party libraries or header files
Understanding and writing every single line of code yourself- no Copy/Paste
Using the debugger effectively to analyze and resolve any bugs
Developing proficiency in your embedded development skills and confidently take the next steps
So like I said, there’s more than just getting each piece of code to work.
Here’s an overview of what you’re getting...
Analyzing the chip documentations:
Before developing the firmware for any chip you have to learn how to read the documentation provided by the chip manufacturer.
Defining Peripheral address
All components on the microcontroller have an address range. To write to a component or read from a component you need to locate its address range in the documentation and properly define the addresses in your code.
Creating registers from the address:
The addresses in the address range of a component represent the registers of that component. To access these registers you have effectively typecast the addresses.
Understanding CMSIS:
Cortex-Microcontroller Interface Standard (CMSIS)CMSIS is a standard developed by Arm for all Cortex-Microcontrollers. This is the standard used in professional firmware development
But it gets better because you’re also getting…
Deep Lessons on Developing Peripheral Drivers
You will learn how to develop bare-metal drivers for the following peripherals :
Analog-to-Digital Converter (ADC)
Serial Peripheral Interface (SPI)
Inter-Integrated Circuit (I2C)
Direct Memory Access (DMA)
Nested Vector Interrupt Controller (NVIC)
General Purpose Timers (TIM)
System Tick Timer (SysTick)
General Purpose Input/Output (GPIO)
Specially Designed For People Who Hate Copy/Paste
Listen. If you don’t like “Copy/Paste” you’re not alone. I can’t stand it either. I’d literally rather have a piece of code that I wrote from scratch that doesn’t work than someone else’s working code I copied and pasted.
And that’s why I’ve spent months designing and recording this course in which I show you how to locate every single register used and the meaning of every hexadecimal value written into the register.
Also it comes with a money back guarantee so you have nothing to loose.