Search topics...
Boot & StartupMemory Sectionsfoundational

Why does the .data section need to be copied from Flash to RAM at startup? Why doesn't .bss need copying?

0 upvotes
Practice with AISoon
Study the fundamentals first — Boot & Startup topic page

The .data section contains initialized global and static variables — variables that have explicit initial values assigned in C code (e.g., int counter = 42; or static float gain = 1.5f;). These initial values must persist across power cycles, so they are stored in Flash by the linker at a load address (LMA). However, the C standard requires these variables to be writable at runtime (the program can modify counter after startup), and Flash memory cannot be written by normal store instructions — it requires a special erase-then-program sequence. Therefore, the startup code must copy the initial values from their Flash location to their runtime address (VMA) in RAM, where the CPU can read and write them normally. The linker script defines both addresses: the LMA (where the data lives in Flash) and the VMA (where the data lives during execution), and exports symbols (_sidata, _sdata, _edata) so the startup code knows the source, destination, and size of the copy.

The .bss section contains uninitialized global and static variables (e.g., int buffer[256]; or static uint32_t tick_count;). The C standard mandates that these start at zero. Since every byte is guaranteed to be zero, there is no unique initialization data to store in Flash — storing thousands of zeros in Flash would waste space for no benefit. Instead, the startup code simply writes zeros to the entire .bss region in RAM using a memset-style loop, guided by the _sbss and _ebss symbols from the linker script. This is both faster (a simple zero-fill loop) and smaller (no Flash storage needed) than a copy. On a large MCU with 128 KB of RAM where .bss might be 64 KB, the Flash savings are substantial.

A subtle but important detail: the order of initialization matters. The .data copy must complete before .bss zeroing if the two regions are adjacent in RAM, because the copy length calculation uses the linker symbols which assume a clean memory layout. In practice, most startup files handle .data first, then .bss. If either step is skipped or the linker symbols are wrong, global variables will contain garbage — a bug that manifests as "works in debug but not release" or "works after reset but not after power cycle," since the debugger may initialize RAM during download.

Source: Boot & Startup Q&A