Intro to ARM Cortex-M Processors
Understand what ARM is, why the Cortex-M family dominates the embedded world, and get a clear picture of everything you will build in this series.
What is an Embedded System?
An embedded system is a dedicated computer built directly into a larger product to perform one specific job. Unlike a desktop PC that runs many applications, an embedded system typically does one thing really well — controlling a motor, reading a sensor, transmitting data wirelessly, or driving a display.
The word “embedded” means the computer is hidden inside a product — you may not even realise it is there. Your washing machine has one. Your car ECU has dozens. Your smartwatch has one. They all share a common trait: a small, energy-efficient processor running specialised software, often called firmware.
- Real-time response — must react to events within a guaranteed time window
- Resource-constrained — limited RAM (often 64 KB to 1 MB), limited flash
- Low power — battery-powered products must run for months or years
- High reliability — automotive and medical devices cannot afford crashes
- No operating system, or a minimal RTOS — many run bare-metal C code
What is ARM? (And Why Does Everyone Use It?)
ARM (originally “Acorn RISC Machines”, now owned by SoftBank and listed independently) is a British semiconductor company that does something unusual: it does not manufacture chips. Instead, it designs processor cores and licenses the design to other companies. Those companies then integrate the ARM core into their own chips alongside peripherals like USB, UART, ADC, timers, and sell those chips (called microcontrollers or SoCs) to product manufacturers.
Designs the CPU core
Sells a license
ST, NXP, TI, Nordic
Add peripherals & sell chips
Buy chips, write firmware
Build products
Phones, watches,
cars, appliances
This business model has made ARM the most widely licensed processor architecture on Earth. Billions of ARM-core chips are shipped every year. When you write code for a Cortex-M3, your skills transfer directly to any microcontroller built on that same core — whether it is made by ST, NXP, Microchip, or Nordic Semiconductor.
The ARM Cortex Processor Family
ARM organises its Cortex processors into three product lines, each targeting a different market segment. Understanding this helps you choose the right processor for any project.
Run Linux, Android, iOS
High performance, complex
e.g., Raspberry Pi CPU
Hard real-time, safety-critical
Automotive ABS brakes,
hard disk controllers
Low power, deterministic
IoT, wearables, appliances
→ THIS COURSE
The Cortex-M Sub-family in Detail
Within the Cortex-M line, ARM offers multiple variants at different price and performance points:
| Core | Architecture | Key Feature | Typical Use |
|---|---|---|---|
| Cortex-M0 | ARMv6-M | Ultra-low gate count, cheapest | Simple sensors, passive RFID |
| Cortex-M0+ | ARMv6-M | Lower power than M0 | Energy harvesting IoT nodes |
| Cortex-M3 | ARMv7-M | Full Thumb-2 ISA, hardware divider, bit-banding | Industrial control, wearables THIS COURSE |
| Cortex-M4 | ARMv7E-M | M3 + DSP instructions + optional FPU | Motor control, audio, signal processing THIS COURSE |
| Cortex-M7 | ARMv7E-M | Dual-issue pipeline, cache, highest M-class performance | Automotive, high-end DSP |
| Cortex-M33 | ARMv8-M | TrustZone security, M4-class performance | Secure IoT devices |
| Cortex-M55 | ARMv8.1-M | Helium vector extensions (ML at the edge) | On-device machine learning |
The Cortex-M3 and M4 hit a sweet spot of capability, documentation, and tooling maturity. They are the most widely taught and most widely deployed in industry today. Skills learned on M3/M4 transfer directly to M7 and M33, which share the same ARMv7-M programmer’s model. If you master M3/M4, everything else is a short step up.
Cortex-M3 vs Cortex-M4 — Side by Side
Both cores share the same instruction set base (Thumb-2), the same programmer’s model, and the same NVIC interrupt architecture. The M4 adds dedicated digital signal processing capabilities on top of the M3 foundation.
- ARMv7-M instruction set
- 3-stage pipeline
- Hardware multiply and divide
- Bit-banding (atomic bit manipulation)
- Memory Protection Unit (MPU)
- No floating-point unit
- No DSP extension instructions
- Very power-efficient
- Example chip: STM32F103, STM32L151
- ARMv7E-M instruction set (superset of M3)
- 3-stage pipeline (same as M3)
- Hardware multiply and divide
- Bit-banding
- Memory Protection Unit (MPU)
- Optional single-precision FPU (FPv4-SP)
- DSP/SIMD instructions added
- Slightly higher power than M3
- Example chip: STM32F407, STM32F429
Write code for the Cortex-M3 and it will compile and run on the Cortex-M4 with zero changes (unless you deliberately use M4-only DSP intrinsics). The programmer’s model — registers, stack, exceptions, NVIC — is identical. This course teaches both at the same time.
Inside the Cortex-M: Core Architecture Overview
Before diving into code, it helps to visualise the major blocks inside a Cortex-M microcontroller. The processor core itself is just one part of the chip; the chip vendor adds many peripherals around it.
Registers • ALU • Fetch/Decode/Execute Pipeline
Thumb-2 ISA • NVIC • SysTick • Debug Logic
Memory
Ports
/ SPI / I2C
/ PWM
/ DAC
/ Ethernet
/ RCC
Throughout this course you will learn to program every layer in this diagram — from writing to a GPIO register to configuring the NVIC to handle an interrupt from a timer peripheral.
Where ARM Cortex-M Lives in the Real World
ARM Cortex-M processors are used in virtually every category of electronic product you interact with daily. The combination of low power consumption, low cost, deterministic real-time behaviour, and a rich peripheral set makes them the default choice for embedded design teams worldwide.
A typical wrist-worn fitness tracker uses a low-power Cortex-M3 microcontroller (e.g., the STMicro STM32L1 series). The ultra-low-power profile of the Cortex-M3 — with a stop mode that draws only a few microamps — is exactly what allows the device to run for five or more days on a single small battery while continuously sampling an accelerometer.
- Microcontroller family: STM32L1 series (Cortex-M3 core)
- Why M3? Sub-milliamp active current, rich low-power sleep modes, small chip footprint
- Peripherals used: SPI (accelerometer), I2C (heart-rate sensor), BLE UART, RTC, DMA
A GPS multi-sport watch demands more processing power for route display, heart-rate analysis, and Bluetooth audio. A Cortex-M7-based microcontroller (backward-compatible with M4 code) manages these tasks while still maintaining the low-power sleep states needed between GPS fixes.
- Microcontroller family: Atmel SMART SAM S/E (Cortex-M7 core)
- Why M7? Dual-issue pipeline, instruction cache, fast DSP for sensor fusion
- Peripherals used: UART (GPS module), SPI display driver, USB, BLE co-processor, ADC
What You Will Learn in This Series
This lecture series takes you from zero to writing professional-quality bare-metal firmware for ARM Cortex-M3 and M4 microcontrollers. Here is the full curriculum roadmap:
| # | Topic Module | What You Will Do | Level |
|---|---|---|---|
| 1 | Architecture & Core Internals | Understand the register bank, pipeline, bus matrix, memory map | Beginner |
| 2 | Programmer’s Model | Work with general-purpose registers, SP, LR, PC, PSR; operating modes | Beginner |
| 3 | Memory Architecture | Understand the 4 GB address space, memory regions, bit-banding, MPU | Intermediate |
| 4 | Exception & Interrupt Handling | Configure the NVIC, write ISRs, understand priority grouping and preemption | Intermediate |
| 5 | Peripheral Programming | Drive GPIOs, configure clocks via RCC, implement button debounce, blink LEDs | Beginner |
| 6 | Timers & PWM | Use SysTick and general-purpose timers to generate delays and PWM signals | Intermediate |
| 7 | Communication Protocols | Implement USART, SPI, and I2C in bare-metal C using register-level programming | Intermediate |
| 8 | Debugging with KEIL / OpenOCD | Use JTAG/SWD to step through code, inspect registers, set watchpoints | Advanced |
| 9 | Lab Sessions & Assignments | Write real firmware from scratch — not HAL, not Arduino, pure registers | Advanced |
The Hands-On Philosophy: Writing Real Code
Many students learn embedded systems by calling library functions (HAL, Arduino, STM32Cube) without ever understanding what those functions do internally. This course takes the opposite approach: you will write directly to hardware registers, in plain C, with no magic abstractions in the way.
Why does this matter? Because when a library call silently fails at 3 AM before a product deadline, the engineer who understands what every register bit does is the one who fixes it. Register-level knowledge makes you fundamentally better — even when you later use libraries by choice.
Bare-metal programming means writing firmware that runs directly on the hardware with no operating system underneath. Your C code is the first thing that runs after reset. You configure every clock, every peripheral, every interrupt yourself — by writing values to memory-mapped registers documented in the chip’s Reference Manual.
A First Taste: Blinking an LED with Registers
To make this concrete immediately, here is what bare-metal LED blinking looks like on an STM32 Cortex-M4 microcontroller. Do not worry if you do not understand every line yet — we will build up to this step by step across the lectures. The point is to show you what the code actually looks like at the register level.
On an STM32F4 board, user LED LD2 is typically connected to Port A, Pin 5 (PA5). To blink it, we need to:
- Enable the clock to GPIO Port A via the RCC (Reset and Clock Control) register
- Configure PA5 as a push-pull output via the GPIO Mode register
- Toggle the output using the GPIO Output Data Register in a loop
#include <stdint.h>
/* ── Register addresses (from STM32F4 Reference Manual RM0090) ── */
#define RCC_AHB1ENR (*((volatile uint32_t *)0x40023830U))
#define GPIOA_MODER (*((volatile uint32_t *)0x40020000U))
#define GPIOA_ODR (*((volatile uint32_t *)0x40020014U))
/* Bit positions */
#define RCC_GPIOAEN (1U << 0) /* bit 0 of RCC_AHB1ENR enables GPIOA clock */
#define GPIOA_PIN5 (1U << 5) /* PA5 = bit 5 of ODR */
static void delay(volatile uint32_t count)
{
while (count--);
}
int main(void)
{
/* Step 1: Enable the GPIOA peripheral clock */
RCC_AHB1ENR |= RCC_GPIOAEN;
/* Step 2: Configure PA5 as general-purpose output (MODER bits 11:10 = 01) */
GPIOA_MODER &= ~(3U << (5 * 2)); /* clear the two mode bits for pin 5 */
GPIOA_MODER |= (1U << (5 * 2)); /* set to 01 = output mode */
/* Step 3: Toggle PA5 forever */
while (1) {
GPIOA_ODR |= GPIOA_PIN5; /* LED ON */
delay(500000);
GPIOA_ODR &= ~GPIOA_PIN5; /* LED OFF */
delay(500000);
}
return 0;
}
- Memory-mapped I/O: Peripheral registers are just addresses in memory — reading and writing them controls hardware.
- Bit manipulation: Using |= to set bits without disturbing others, &= ~ to clear bits, and ^= to toggle.
- Volatile: The volatile keyword prevents the compiler from optimising away register reads/writes.
- Clock enable first: Most Cortex-M chips gate peripheral clocks by default. Forgetting to enable the clock is the #1 beginner bug.
- Reference Manual: Every address above (like 0x40023830) comes directly from the manufacturer’s Reference Manual — not guessed.
Development Tools for This Course
You will use the following tools throughout this series. All of them have free tiers or are fully open-source:
| Tool | Purpose | Notes |
|---|---|---|
| KEIL MDK / uVision | IDE, compiler (ARM Compiler 6), debugger | Free for devices up to 32 KB code; industry standard |
| ARM GCC Toolchain | Open-source compiler and linker | arm-none-eabi-gcc — fully free, widely used in Linux development |
| OpenOCD | Open On-Chip Debugger — flash and debug via SWD/JTAG | Free, works with STM32 Nucleo’s built-in ST-LINK |
| STM32 Nucleo Board | Development board with ST-LINK debugger built in | ~$15 USD; has Cortex-M3 (Nucleo-F103) or M4 (Nucleo-F401/F411) variants |
| Logic Analyser | Capture and decode UART, SPI, I2C signals in real time | Low-cost 8-channel USB logic analysers work fine for learning |
What You Need to Know Before Starting
- C programming fundamentals — pointers, arrays, structs, bitwise operators, function pointers. If you can write a linked list in C, you are ready.
- Basic binary and hexadecimal — you must be comfortable converting between hex, binary, and decimal, and performing simple AND/OR/XOR operations mentally.
- High school electronics (helpful but not required) — understanding voltage, current, and Ohm’s law helps when wiring LEDs and buttons.
You do not need prior experience with embedded systems, RTOS, assembly, or any specific IDE. We start from zero on all of that.
Quick Refresher: Bitwise Operations in C
Bitwise operations are the bread and butter of embedded programming. You will use them in every lecture. Here is a compact reference:
#include <stdint.h>
int main(void)
{
uint32_t reg = 0x00000000; /* imagine this is a hardware register */
/* ── Set bit N (force it to 1 without touching other bits) ── */
reg |= (1U << 5); /* sets bit 5; reg = 0x00000020 */
/* ── Clear bit N (force it to 0 without touching other bits) ── */
reg &= ~(1U << 5); /* clears bit 5; reg = 0x00000000 */
/* ── Toggle bit N ── */
reg ^= (1U << 5); /* flips bit 5; reg = 0x00000020 */
/* ── Read (test) bit N ── */
if (reg & (1U << 5)) {
/* bit 5 is set */
}
/* ── Set a multi-bit field (e.g. bits 11:10 to value 0b10) ── */
reg &= ~(0x3U << 10); /* clear the 2-bit field first */
reg |= (0x2U << 10); /* then write the desired value */
/* ── Read a multi-bit field ── */
uint32_t field = (reg >> 10) & 0x3U; /* extract bits 11:10 */
return 0;
}
In C, the literal 1 is a signed int, typically 32 bits. Shifting a signed integer left by 31 or more bits is undefined behaviour. Always use the unsigned form 1U or cast to uint32_t before shifting. This is a real source of subtle bugs in production firmware.
Processor vs Microcontroller: Know the Difference
This distinction trips up almost every beginner. A processor and a microcontroller are related but different things:
(Processor Core)
- CPU registers
- ALU + barrel shifter
- Instruction decoder
- NVIC interrupt controller
- SysTick timer
- Debug port (SWD)
- No memory of its own
- No peripherals of its own
(STMicro / NXP / etc.)
- Flash memory (e.g. 512 KB)
- SRAM (e.g. 128 KB)
- GPIO ports (A, B, C, D…)
- USART, SPI, I2C, CAN, USB
- Timers (basic, general, advanced)
- ADC / DAC
- Clock tree & PLL
- DMA controller
(e.g. STM32F407)
Key Reference Documents You Will Use
Embedded development is a documentation-heavy discipline. Two types of documents will become your daily companions:
| Document | Published By | What It Contains | When to Use It |
|---|---|---|---|
| Cortex-M3/M4 Technical Reference Manual (TRM) | ARM Holdings | CPU architecture, instruction set, register descriptions, exception model, NVIC | When writing interrupt handlers, understanding pipeline behaviour, reading CPSR/xPSR |
| ARMv7-M Architecture Reference Manual | ARM Holdings | Complete instruction set encoding, memory model rules, memory ordering | Deep dives into assembly, memory barriers, atomic operations |
| STM32F4xx Reference Manual (RM0090) | STMicroelectronics | Every peripheral on the chip: register map, bit fields, reset values, configuration sequences | Any time you configure a peripheral — GPIO, USART, SPI, Timer, ADC, etc. |
| STM32F4xx Datasheet | STMicroelectronics | Pin configuration, electrical characteristics, package information, memory and peripheral base addresses | Hardware design, checking max sink/source current on GPIO, finding base addresses |
| Nucleo Board User Manual (UM1724) | STMicroelectronics | Board schematic, connector pinout, solder bridges, ST-LINK programming interface | Identifying which microcontroller pin is connected to which board header or LED/button |
Reference Manuals for complex microcontrollers run to 1,000+ pages. You are not expected to read them cover-to-cover. The skill is knowing how to navigate them:
- Use the Table of Contents to find the peripheral chapter (e.g., “Chapter 8: General-purpose I/Os”).
- Read the functional description section for a conceptual overview (typically 1–2 pages).
- Look at the register map table at the end of each section to find offset addresses.
- Read only the specific register descriptions for the bits you need to configure.
- Follow the configuration sequence listed in the section — order often matters.
Frequently Asked Questions
Lecture 2 covers the Cortex-M register bank in detail — the 13 general-purpose registers, stack pointer, link register, program counter, and the Program Status Register. Understanding these is the foundation for everything that follows.

2 Comments