Ground Embedded KO Subscribe

Notes / Computer Architecture

Memory map: everything in an MCU has an address

Code is in Flash, variables are in SRAM, and peripheral registers sit at fixed addresses too. How to read the memory map in a datasheet.

GROUND EMBEDDED · NOTEComputer Architecture 05Memory mapMCU

A 32-bit Cortex-M has a 4 GB address space from 0x0000_0000 to 0xFFFF_FFFF. Real memory occupies only part of it, but each region has an assigned use.

Address Region STM32 example
0x0800_0000 Code (Flash) Program and const data
0x2000_0000 SRAM Global variables, stack, heap
0x4000_0000 Peripherals GPIO, timer and UART registers
0xE000_0000 Core peripherals NVIC, SysTick, debug

Reading the datasheet

Find "GPIOA 0x4002_0000 to 0x4002_03FF" in the memory-map table of the reference manual, find "ODR offset 0x14" in the register table of that chapter, and the address of GPIOA_ODR is 0x4002_0014. GPIOA->ODR in the CMSIS headers does this calculation for you.

Using it for debugging

When a hard fault occurs, a faulting address of 0x2000_xxxx is RAM and 0x4xxx_xxxx is a peripheral access. Accessing the registers of a peripheral whose clock is off causes a bus error, and the address alone lets you guess the cause.

In a picture: the address space on one line

0x0000_0000CodeFlash, vector table0x2000_0000SRAMvariables, stack0x4000_0000PeripheralsGPIO, UART, timers0xE000_0000CoreNVIC, SysTick
The 4 GB address space of a Cortex-M. Code, variables and peripherals all live in the same addressing scheme, so one pointer reaches everything.

These large divisions are the same on every Cortex-M. What goes at which address inside them is decided by the chip maker and written in the "Memory map" table of the datasheet.

How a register address is formed

peripheral base address + register offset = register address
GPIOA 0x4800_0000       + ODR 0x14        = 0x4800_0014

The vendor header file expresses this calculation as a struct.

typedef struct {
    volatile uint32_t MODER;    // +0x00
    volatile uint32_t OTYPER;   // +0x04
    volatile uint32_t OSPEEDR;  // +0x08
    volatile uint32_t PUPDR;    // +0x0C
    volatile uint32_t IDR;      // +0x10
    volatile uint32_t ODR;      // +0x14
} GPIO_TypeDef;

#define GPIOA ((GPIO_TypeDef *)0x48000000u)

Write GPIOA->ODR and the compiler adds 0x14 to the base address and accesses it. The order and size of the struct members have to match the offsets in the reference manual exactly.

Where the program is placed

Section Contents Where it goes
.text Code Flash
.rodata const data, strings Flash
.data Global variables with an initial value RAM (initial values kept in Flash)
.bss Global variables that start at 0 RAM
Stack, heap Space used at run time RAM

.data takes up both Flash and RAM. At power-up the startup code copies the initial values kept in Flash to RAM, fills .bss with 0 and then calls main. That process is why global variables have their values from the very start.

RoadmapSee where this note sits in Computer Architecture→

Reading the map file

The .map file produced by the build lists the address and size of every function and variable.

  • When Flash or RAM runs short: sort by size and find what is taking the space.
  • When a hard fault occurs: find which function the faulting address is in.
  • When a variable gets corrupted: suspect the array placed just before it.

Bit-banding and aliases

Some Cortex-M3/M4 parts have a region where each bit of RAM and of the peripherals is accessed at its own address. One write changes a single bit, so there is no problem of an interrupt cutting in during a read-modify-write. Not every chip has it, so check the datasheet.

Problems that come up in practice

  • Accessing a reserved region: reading an address that is not in the map causes a bus fault.
  • A peripheral whose clock is off: the address is right, yet reads return 0 and writes do not take effect.
  • It stops working after changing the chip: even in the same family, peripheral base addresses can differ. Switch to the header file for that chip.
  • Bootloader and application addresses overlap: the Flash start address in the linker script and the vector-table location have to be moved together.
FREE PDFGet the 3 free ebooksIf you want to keep reading this topic as one book: BLDC motor control, serial communication and sensors at book length. PDFs are in Korean.Get them free →