the MCU memory map
Imagine a long street where every house has a number, but the houses are very different: some are libraries (you can only read them), some are notepads (you can read and write), and some are not houses at all but control panels for machines outside. The MCU memory map is exactly this: a single numbered range of addresses (say 0x00000000 up to 0xFFFFFFFF on a 32-bit chip) where each region of numbers is wired to a different kind of thing.
On a typical Cortex-M microcontroller the map has a few key regions. Flash (program memory) usually starts near address 0x08000000 (or is also visible at 0x00000000): this is non-volatile, read-mostly storage where your compiled program and constant data permanently live — it survives power-off. RAM (SRAM) usually starts near 0x20000000: this is fast read/write memory for your variables, the stack, and the heap, but it is volatile (it forgets everything when power is lost). Then there is the peripheral region, often around 0x40000000: these addresses are NOT memory at all — reading or writing them actually talks to hardware. Writing to a peripheral address might turn on an LED; reading one might return the current temperature from a sensor. This is called memory-mapped I/O. Higher up, around 0xE0000000, sits the system region with the interrupt controller and core peripherals. You can see the whole map in the chip's reference manual.
It matters because, with no OS to abstract any of this, your code, your linker script, and your pointers all use these raw addresses directly. The crucial honest point: addresses in the peripheral region are NOT ordinary memory — a write there has a side effect on the world, and a read may change device state, so you must mark those accesses volatile and never let the compiler optimize them away. Treating a peripheral register like a normal variable is one of the classic embedded bugs.
Typical Cortex-M 32-bit address map: 0x00000000 flash alias / boot 0x08000000 flash (program + const data, read-mostly) 0x20000000 SRAM (.data, .bss, stack, heap; volatile/RAM) 0x40000000 peripherals (GPIO, UART, timers — memory-mapped I/O) 0xE0000000 system (NVIC, SysTick, debug) 0xFFFFFFFF top of 4 GiB address space
Flash for code, RAM for variables, and a peripheral region where addresses are wired to hardware, not storage.
The biggest trap: peripheral addresses are not RAM. A read there can have side effects and a write changes hardware, so they must be accessed through volatile pointers — and exact addresses come from the chip's reference manual, not a guess.