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.