| nRF5 SDK v12.0.0 |

Choose documentation: | nRF5 SDK | S130 SoftDevice API | S132 SoftDevice API | S212 SoftDevice API | S332 SoftDevice API

All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
Experimental: Section variables

Section variables are variables that are placed in a named section by different independent pieces of code (for example, files or modules), so that they can be shared. The section variables module facilitates the handling of section variables by abstracting the required compiler-specific code.

The sharing of variables happens at compile time (or more precisely, at link time). One module (the registrar) creates a named section that can hold variables. Other modules (the registrants) can then register variables to place them into the section at link time. Each variable can be accessed by the registrar and the registrant that created it.

Main reasons for using section variables are:

- Decoupled code: Section variables are declared in the registrant code, without having to change the code of the registrar.
- Transparency: The registrant can access its section variables in the same way as any other variables.
- Access control: Variables can be declared as static by the registrants and still be shared with the registrar.
- Ease of use: The registrar can access all registered variables through macros that are provided by the section variables module.
- No duplication of variables: The variable that is accessed by the registrar is the variable that the registrant created, not a copy.
- Space efficiency: The required storage space is dynamically adjusted at link time, but frozen at run time.

A typical use case for section variables is the initialization of a module that allows multiple users to register with it and that manages a shared resource (for example, Experimental: Flash Storage). Each of the users provides a configuration structure that is kept by the module. Without the use of section variables, these configuration structures can be dynamically registered at run time or handled through a shared header file. With run-time registration, the module can never know the final number of registrants. With a shared header file, you must modify the code of the registrar (which might be a library that you do not want to change). With section variables, the number of registrants is known immediately when the code runs, and you need to modify only the registrant code.

Section variables are used in Experimental: Flash Storage and Experimental: Flash Data Storage to configure flash page usage, for example.

The following code examples show how to use section variables in an application. In a typical use case, there is one registrar module that creates the named section and uses the data in it and one or more registrant modules that register their data in the named section.

# Creating a named section

Creating a named section requires two steps:

1. In the code of the registrar module, create and name the section (section_name in this example), indicating the data type of the variables to be stored in it (data_type_t in this example):
   NRF_SECTION_VARS_CREATE_SECTION(section_name, data_type_t);
   Note that all variables in a named section must be of the same type.
2. If you are using GCC, tell the linker that there is a named section. To do so, add the following definition to the root level of the linker script that is used in the compilation (replace section_name with the name of your section):
   SECTIONS
   {
   .section_name :
   {
   PROVIDE(__start_section_name = .);
   KEEP(*(.section_name))
   PROVIDE(__stop_section_name = .);
   } > RAM
   } INSERT AFTER .data;

# Registering section variables

In the code of the registrant module, use the NRF_SECTION_VARS_REGISTER_VAR macro to register a section variable. The following code example shows how to register the variable var_name of type data_type_t in the section named section_name and assign it the value var_value:

NRF_SECTION_VARS_REGISTER_VAR( section_name, data_type_t var_name ) = { var_value };

If the registrant does not require to update the value of the section variable, define the variable as const. If this is the case for all section variables in a named section, the section is placed in flash:

NRF_SECTION_VARS_REGISTER_VAR( section_name, const data_type_t var_name ) = { var_value };

To simplify registrations, you can define macros that fill in the name of the named section. See the following example from Experimental: Flash Storage:

#define FS_REGISTER_CFG(cfg_var) NRF_SECTION_VARS_REGISTER_VAR(fs_data, cfg_var)

# Using section variables

The Section variables module provides several macros that the registrar can use to retrieve section variables and information about the named section and the variables it contains.

The following code example shows how to iterate through all registered section variables to initialize the registrar module for all registrants:

static void init_func(void)
{
int vars_cnt = NRF_SECTION_VARS_COUNT(data_type_t, section_name);
for (int i = 0; i < vars_cnt; i++)
{
data_type_t * p_var_name = NRF_SECTION_VARS_GET(i, data_type_t, section_name);
// Add initialization code here
}
}

Note that it is not possible to control the order of the variables in a named section across compiler versions and across compilations.