Kinetis – relocating variables to upper SRAM

NXP Kinetis microcontrollers have an inconvenient architectural feature – split RAM. The memory is split into two areas of equal size. You can run into this issue when the size of all RAM variables (data+bss) approaches half size of available SRAM. It manifests itself with a linker error looking similar to this:
ld: region `m_data' overflowed by 132 bytes
I will use an MK22FN512 as an example, but this post applies equally to all Kinetis K-series MCUs.

Brief reminder about MCU memories and sections:

  • flash – holds the code (text section) and initial values for variables different than zero (data section)
  • RAM – holds all runtime variables (bss – data initialized to zeros, data – data initialized with values different than zeros)

Placement of all sections in the output binary is configured by the linker script. In Kinetis Design Studio projects the linker script is located in “Project Settings”->”Linker_files” subdirectory.

In my dummy MK22FN512 project linker script starts with:

The first three sections reside in flash, m_data is the lower SRAM (also called SRAM_L), m_data2 is the upper SRAM (SRAM_U). Length of both is 0x20000, which corresponds to total RAM (128KB) available in MK22FN512.

The problem

I made a very simple dummy project in Kinetis Design Studio with two 32KB arrays:

Two 32KB arrays should easily fit into 128KB of RAM. The code compiles cleanly, but fails to link:

The problem is that all variables go only into m_data section, which is only 64KB large (and there are some extra bytes used by the code besides the arrays).


The solution

The linker script needs a new section (because you can’t place variables directly into output sections):

This has to be placed right after .bss and before .heap.

Variables must be manually placed in the new section using the following attribute:


Now the project links cleanly:

Adding attributes to many small variables makes little sense, so most obvious candidates are big arrays, buffers etc. The aw and nobits attributes make the section treated as not occupying output binary space (ie. like .bss), so it will not be initialized like .data (otherwise after objcopy the .bin file can be 512MB large). Variables placed in this section will most likely not be zeroed out by the startup code (because technically it is not .bss), however it does not matter much if they are used for buffers.

Why?

Kinetis architecture is explained in AN4745. The Cortex-M4 core has three AHBLite buses. ICODE and DCODE busses can only access the lower addressing space (including SRAM_L), the system bus can only access higher addressing space (including SRAM_U).

Both parts of RAM behave mostly the same from C programmer’s point of view. The only difference is that code executed from SRAM_L runs at full speed, while from SRAM_U requires a wait state (so it runs at half-speed). Data access is identical and runs at full speed.

Rate this post