Memory Layout
Memory layout of a C/C++ project is controlled by the linker in your toolchain. Memory layout in this documentation means the location of functions and data in flash memory and RAM on a Silicon Labs EFR32/EFM32. When using GCC, the GNU Linker is using GNU linker scripts (.ld) to control the memory layout and when using IAR Embedded Workbench IAR ILINK is using linker configuration files (.icf) to control the memory layout of the application.
Gecko SDK provides the Simplicity Studio Project Configurator which, can be used to generate these toolchain-dependent linker files. These linker files will be created based on the project description, target device, and components used in a project. Using the generated linker files, the sections of the applications will be placed in a deterministic way, which will allow the application to be used with Silicon Labs devices.
Toolchains
GCC and IAR are the supported toolchains. The GCC generated linker script,
linkerfile.ld
is placed in the
autogen
folder. The IAR-generated linker configuration file,
linkerfile.icf
is also placed in the
autogen
folder. The generated project files will refer to these files.
Note that the linker files are auto generated based on the components included in the project and will be overwritten whenever the application is re-generated.
Graphical View of Standard Memory Layout
This is a graphical view of a typical memory layout of an application built using the Silicon Labs Gecko SDK. This shows the relative placement of various sections. Note that some of the sections in the image are optional and do not have to be present in all applications.
Graphical view of typical memory layout Typical Memory Layout
In the graphical view, the main flash begins at address
0x0000 0000
because flash memory is typically memory mapped at that location on EFR32 devices. However, some devices may have the main flash located at a different address. See the reference manual of your selected device for the exact memory location of flash and RAM.
Section Details
Different memory sections are described starting with the lowest memory address.
Bootloader
An application using the Gecko SDK can optionally choose to use a bootloader. When using a bootloader, an area of flash will be reserved for the bootloader and will be unavailable for the application code. Some devices will have dedicated bootloader flash areas, while other devices will have to use parts of the main flash for bootloader code. All series-1 devices have dedicated bootloader flash memory regions except EFR32xG1 and EFM32xG1. On EFR32xG1 and EFM32xG1, the first parts of main flash are used for the bootloader. All series-0 and series-2 devices use the first parts of main flash for the bootloader.
To allocate flash memory for the bootloader with the Gecko SDK, add the
bootloader_interface
component to the application. The presence of this component in the project will trigger the reservation of a fixed size bootloader. On all series-1 devices and the EFR32xG21 device the bootloader size is 16 kB while on EFR32xG22 the bootloader size is 24 kB.
For a different size bootloader, manual modifications of the auto-generated linker files is needed. See the Gecko Bootloader user guide UG266 for more Gecko Bootloader-specific documentation.
Code
Application code is next in the memory layout. This is where functions and read only data are placed.
Bootloader Storage
The application Bootloader has the option to use parts of main flash on the device as storage space for the firmware update images. To safely reserve space in the memory map, the application can include the
flash_storage
component. This component will provide source code and a configuration file that the application can use to tune the amount of storage needed.
When including the
flash_storage
component, the default flash reservation is half of the main flash size minus 16 kB. To modify the size, change the
SL_BOOTLOADER_STORAGE_SIZE
option, which is located in the
sl_storage_config.h
configuration file. The size of the bootloader storage area is highly application-dependent and should be a fixed size once a product with a bootloader is deployed.
Note that the configured bootloader storage size used when building the application and the bootloader storage size used when building the bootloader must match. The user will have to manually ensure that the bootloader storage size and location is correctly configured between the bootloader project and the application project.
NVM3
Gecko SDK provides a way to store persistent key-value objects into the main flash. This data is persistent between resets and firmware updates and can be used for general storage and in wireless applications for token storage. When you add NVM3 as a component to a project, parts of main flash are reserved for a single NVM3 instance. The NVM3 storage will be placed at the end of main flash and the size of the NVM3 region is configurable by the application. The default size of the NVM3 instance is 40 kB on series-2 devices, 36 kB on series-1 devices and 36 kB on series-0 devices.
The configuration for the NVM3 instance is placed in the file
nvm3_default_config.h
, which is copied into the project when a project is generated. The NVM3 size configuration is called
NVM3_DEFAULT_NVM_SIZE
. For more documentation on NVM3 and other NVM3 related configurations, see application note AN1135: Using Third Generation Non-Volatile Memory (NVM3) Data Storage.
Stack
The stack and heap are used by the application to allocate dynamic memory. The stack is normally used to allocate local memory to function variables and call frames, which means that applications with deep call stacks will typically need to allocate a larger stack than applications with shallow call stacks. With Gecko SDK, customer applications can configure the size of the stack.
An application will have to configure the stack size based on the estimated maximum stack usage. This number can be difficult to determine exactly and might change between SDK releases and application versions, so a normal strategy would be to over-allocate the stack space to have some head room for application changes. Always change the stack configuration from the default value to suit the application needs.
The size of the stack is configured in the
sl_memory_config.h
configuration file using the
SL_STACK_SIZE
option. This configuration file is copied to the application when it's first generated. Modifying this configuration option will modify the stack size accordingly.
When using the Gecko SDK, the stack memory region is placed at the beginning of RAM. The stack is placed here so that it grows down towards address 0x20000000, which is the beginning of RAM so that stack overflow situations can be detected in hardware without corrupting any data. If at any point, the application uses more stack than is allocated, the device will trigger a fault and the developer can detect this error condition during development.
Heap
Whenever an application uses
malloc()
in any part of the software, a portion of RAM needs to be allocated to the central heap. The size of the allocated heap is application dependent. Small applications might not need any heap at all while other applications might use a lot of heap.
The size of the heap is configured in the
sl_memory_config.h
in the same way as the stack size is configured. The configuration options for heap size is called
SL_HEAP_SIZE
.
The heap region is placed after the rest of the RAM-based content and the heap is growing towards the end of RAM. Maintaining the heap internal content is handled by the C library that the application is using. This can for instance be newlib-nano when using GCC or DLIB when using IAR.
For GCC support with newlib-nano, the
_sbrk()
function is implemented in the Gecko SDK. This function is used by
malloc()
internally and returns the correct error code when the heap overflows, which makes it possible for the caller of
malloc()
to see if heap allocation succeeded or failed.
Support for Ember Style Memory Layout
The memory layout described here for Silicon Labs device is not always compatible with previous versions of the SDK. The Ember bootloader for the early EFR32 devices relied on a specific memory layout where the SIMEE section was placed in the middle of the main memory if the main flash was used for firmware update storage. To build a project using the Ember style memory layout, the application needs to pull in a
legacy_bootloader_interface
component. Using this Ember style memory layout will also place an Application Address Table (AAT) at the start of the application flash, which was required by the Ember bootloader.