nRF5 SDK for Mesh v3.2.0  08c60f6
Integrating Mesh into nRF5 SDK examples

The nRF5 SDK for Mesh is compatible with Nordic's nRF5 SDK. This allows you to either include resources from nRF5 SDK in an existing mesh project or include nRF5 SDK for Mesh functionalities in an nRF5 SDK example.

See Building the mesh stack and examples for information on how to download and install the nRF5 SDK. Check Coexistence examples to see how the nRF5 SDK features can be simultaneously used with nRF5 SDK for Mesh.

Note
  • nRF5 SDK integration is only tested with nRF5 SDK version 15.2.
  • nRF5 SDK version 15.2 does not support nRF51.

Table of contents

  • Dynamic memory
  • Concurrent SoftDevice and mesh activity
  • Including nRF5 SDK in an nRF5 SDK for Mesh example
  • Including nRF5 SDK for Mesh functionality in an nRF5 SDK example
    • Optional changes
    • nRF5 SDK NVM storage modules
    • Estimated sizes
      • Definitions
      • Base sizes
      • Results

Dynamic memory @anchor coexistence_memory

While using nRF5 SDK features along with nRF5 Mesh SDK features (as shown in coexistent examples) you may encounter situation where the application considerations may require changes to how dynamic memory is allocated and the amount of dynamic memory available for allocation. The mesh stack uses the Mesh memory manager interface for dynamic memory allocation. The default backend, mesh_mem_stdlib.c, uses the standard library malloc(), which requires a sufficiently large heap size to be defined. This behavior can be changed by replacing the backend with another memory manager.

If you are using Segger Embedded Studio for building the application set the Heap Size to 8192 bytes in the Project Options> Code> Runtime Memory Area settings.


Concurrent SoftDevice and mesh activity @anchor coexistence_softdevice_mesh_activity

The largest performance issues when running the SoftDevice and the Mesh concurrently usually comes from radio time contention. While the SoftDevice usually operates in short, scheduled bursts, the Mesh attempts to use the radio for as much time as possible. As long as the SoftDevice has no radio activity, the Mesh will be scanning and advertising continuously. The SoftDevice activity will reduce the amount of time the Mesh gets on-air, and in order to maintain a consistently good Mesh performance, the SoftDevice radio parameters must be set as conservatively as possible, without breaking the user experience.

When advertising with the SoftDevice, try using the highest advertising interval your usage scenario can tolerate. If possible, turn off the SoftDevice advertiser when it is not needed, and activate it only when you expect to receive a connection request. If you only need to send non-connectable, non-scannable advertisements (for example, for third party beacon protocols), use the Mesh Advertiser API, as it is optimized for minimal context switching when used together with the Mesh.

When the SoftDevice operates in a connection:

  • Try negotiating for the largest possible connection interval your application can tolerate. If high throughput over the connection is required, it is better to send more data in each connection event than to reduce the connection interval, as the majority of the overhead comes from context switching.
  • If the Mesh device is acting as a peripheral (slave) in its SoftDevice connection, you can also increase the "slave latency", which should let the SoftDevice skip connection events without increasing the latency of any outgoing data transfers over the link.
  • Just like with the advertisements, it is recommended to only keep the connection alive when it is needed. Idle SoftDevice connections impact Mesh performance almost as much as connections with a lot of traffic, particularly if the slave latency is low.

SoftDevice-based scanning has the biggest impact on the Mesh performance of all the SoftDevice activity. The Mesh is not able to receive packets while the SoftDevice is scanning, so every SoftDevice scan window replaces Mesh scanning. SoftDevice scanning should only be used when trying to establish connections or when active scanning is required. If general passive BLE scanning is required (for listening for beacons or other third party activity), hook into the Mesh scanner by setting an RX callback with the nrf_mesh_rx_cb_set function. If your application requires active scanning or needs to initiate a connection, the scan parameters should be set as conservatively as possible. Long scan intervals with short scan windows will give the Mesh as much time as possible for its own radio activity. Similarly, it might be beneficial to perform continuous scanning for a short period of time when establishing connections, instead of performing long running, duty cycled scanning, as the context switching would cause a lot of unnecessary overhead. Finally, setting a timeout for SoftDevice connection initiation calls to avoid idle scanning for long periods of time is highly recommended.

As the Mesh does not actively block SoftDevice radio activity, reducing Mesh activity on the device that runs SoftDevice activity concurrently does not directly affect the SoftDevice performance. However, other Mesh devices nearby will interfere with SoftDevice activity in the advertisement channels, which could make connection initiation take longer.

Generally, the Mesh has to perform all its radio operations between the SoftDevice activity, so if a device is sending a lot of Mesh packets while performing SoftDevice radio operations, it will spend most of its Mesh time on this, instead of receiving incoming data. To combat this, reduce the Mesh packet sending by scaling the number of outgoing packets according to the radio time available. If possible, suspend Mesh packet relaying during time-consuming SoftDevice operations by calling the mesh_opt_core_adv_set on the CORE_TX_ROLE_RELAY role.


Including nRF5 SDK in an nRF5 SDK for Mesh example @anchor coexistence_nrf5_sdk_in_mesh

Depending on your toolchain:

  • When using Segger Embedded Studio, add code files and include paths to the corresponding SES project file.
  • When building the nRF5 SDK for Mesh stack using CMake, add code files and include paths to the corresponding CMakeLists.txt file. The SDK_ROOT root symbol is used to refer to the nRF5 SDK installation folder (see for example CMakeLists.txt in the Light Switch server example).

The mesh example projects already include an sdk_config.h file in their include/ directory. These files are copies of the default SDK configuration files, and all changes required by the mesh example are contained in the include/app_config.h file in the example's directory.

Note
Some SDK features must be explicitly enabled in the SDK configuration file before they can be used. See the SDK documentation page SDK configuration header file for details.

Including nRF5 SDK for Mesh functionality in an nRF5 SDK example @anchor coexistence_mesh_in_nrf5_sdk

  1. Include the following source files from nRF5 SDK for Mesh in the nRF5 SDK example's project file:
    • All C files in mesh/core/src
    • All C files in mesh/bearer/src
    • All C files in mesh/prov/src except nrf_mesh_prov_bearer_gatt.c
    • All C files in mesh/access/src
    • All C files in mesh/dfu/src
    • All C files in mesh/stack/src
    • models/foundation/config/src/config_server.c
    • models/foundation/config/src/composition_data.c
    • models/foundation/config/src/packed_index_list.c
    • models/foundation/health/src/health_server.c
    • Any other mesh models that are used in your application
    • external/micro-ecc/uECC.c
    • examples/common/src/assertion_handler_weak.c
    • examples/common/src/mesh_provisionee.c
      Note
      If various mesh features are not needed (for example, DFU), the corresponding files may simply be omitted from the project file. However, add examples/nrf_mesh_weak.c in their place to provide stubs for the missing API functions.
  2. Add the following folders to the project include path of the nRF5 SDK example:
    • mesh/core/api
    • mesh/core/include
    • mesh/bearer/api
    • mesh/bearer/include
    • mesh/prov/api
    • mesh/prov/include
    • mesh/access/api
    • mesh/access/include
    • mesh/dfu/api
    • mesh/dfu/include
    • mesh/stack/api
    • models/foundation/config/include
    • models/foundation/health/include
    • Path to include folder of any other mesh models that are used in your application
    • external/micro-ecc
    • examples/common/include
    • Path to any other resources in the mesh examples that are used in your application
  3. Add the following preprocessor symbols to the project file of the nRF5 SDK example:
    • NRF52_SERIES
    • NRF_MESH_LOG_ENABLE=NRF_LOG_USES_RTT (because logging in the mesh stack relies on RTT)
    • CONFIG_APP_IN_CORE

Optional changes @anchor coexistence_mesh_in_nrf5_sdk_optional

Additionally, you might need to apply one or more of the following changes:

  • Examples using the simple_hal module in the mesh stack may need to be updated to use the Nordic nRF5 SDK bsp module if integrated with the nRF5 SDK. It is possible to use both, but in this case GPIOTE_IRQHandler must be removed from one of them, and only one of the modules may register callback functions.
  • If the original Nordic nRF5 SDK example uses the SoftDevice, make sure that the mesh stack is initialized and enabled after the SoftDevice is enabled. In that case, SoftDevice events must be forwarded to the mesh stack. Add the following code to your application:
    #include "nrf_sdh_soc.h"
    #define MESH_SOC_OBSERVER_PRIO 0
    static void mesh_soc_evt_handler(uint32_t evt_id, void * p_context)
    {
    nrf_mesh_on_sd_evt(evt_id);
    }
    NRF_SDH_SOC_OBSERVER(m_mesh_soc_observer, MESH_SOC_OBSERVER_PRIO, mesh_soc_evt_handler, NULL);
  • If you have multiple SOC observers, ensure that the SOC observer events are forwarded to the mesh stack only from one of the observers at a time.
  • Flash storage of network configuration is enabled by default in the mesh stack as well as in some of the Nordic nRF5 SDK applications. The flash areas used for this purpose may overlap and cause errors. To allow safe coexistence of the flash storage module Flash manager in the mesh stack and the flash storage module fstorage in the Nordic nRF5 SDK, add the following code block to nrf_mesh_config_app.h:
    #include "fds.h"
    #include "fds_internal_defs.h"
    #define FLASH_MANAGER_RECOVERY_PAGE_OFFSET_PAGES FDS_PHY_PAGES
  • If you are adding you own mesh functionality rather than working from an existing mesh example, you also need to add the file nrf_mesh_config_app.h. Copy it from the examples/templates folder in mesh stack repository into your project folder, and remove #error message at the top of the file. Make other appropriate changes to the file content, like adjusting ACCESS_ELEMENT_COUNT and ACCESS_MODEL_COUNT to the required number of elements and models.

Flash placement project files @anchor coexistence_mesh_in_nrf5_sdk_flash_placement_xml

The Segger Embedded Studio projects all have a flash_placement.xml file next to them, which acts as input to the linker. In the flash_placement.xml file, the nRF5 SDK configures a set of ProgramSection listings, which are used to place certain variables. In addition to all the ProgramSections required by the nRF5 SDK components, the mesh requires two additional sections, nrf_mesh_flash and nrf_mesh_ram.

The additional mesh-related sections must be added to the flash_placement.xml file:

  1. Add the following line to the memory segment marked <MemorySegment name="FLASH" ...>:
    <ProgramSection alignment="4" keep="Yes" load="Yes" name=".nrf_mesh_flash" inputsections="*(SORT(.nrf_mesh_flash.*))" address_symbol="__start_nrf_mesh_flash" end_symbol="__stop_nrf_mesh_flash"/>
  2. Add the following line to the memory segment marked <MemorySegment name="RAM" ...>:
    <ProgramSection alignment="4" keep="Yes" load="No" name=".nrf_mesh_ram" inputsections="*(SORT(.nrf_mesh_ram.*))" address_symbol="__start_nrf_mesh_ram" end_symbol="__stop_nrf_mesh_ram"/>
Note
This change has already been made for the Coexistence examples. You can use the flash_placement.xml files in these examples as a reference when editing flash placement files of any of the existing nRF5 SDK examples.

nRF5 SDK NVM storage modules @anchor coexistence_mesh_in_nrf5_sdk_nvm

Using nRF5 SDK modules such as fstorage, pstorage, or ble_flash for writing to flash may be problematic due to long timeslot events occupied by the mesh stack. Use the Flash manager module provided by the mesh stack instead.

Furthermore, when writing to flash, ensure not to write or erase areas utilized by the mesh stack modules and the bootloader (if present). By default, the mesh modules utilize the last x number of pages before the start of the bootloader, if present, or the last x number of pages of the available flash on the Nordic SoC. The value of x depends on the configuration of the mesh stack and can be calculated by:

x = 2 + ACCESS_FLASH_PAGE_COUNT + DSM_FLASH_PAGE_COUNT

In this equation:

  • ACCESS_FLASH_PAGE_COUNT must be equal to or greater than:
      (1 + ((DATA_SIZE) / (FLASH_MANAGER_DATA_PER_PAGE - LARGEST_ENTRY_SIZE)))
    
    • DATA_SIZE is
      (ALIGN_VAL((sizeof(fm_header_t) + sizeof(access_model_state_data_t)), WORD_SIZE) * ACCESS_MODEL_COUNT) +
      (ALIGN_VAL((sizeof(fm_header_t) + sizeof(access_flash_subscription_list_t)), WORD_SIZE) * ACCESS_SUBSCRIPTION_LIST_COUNT) +
      (ALIGN_VAL((sizeof(fm_header_t) + sizeof(uint16_t)), WORD_SIZE) * ACCESS_ELEMENT_COUNT) +
    • ALIGN_VAL returns the total field size aligned to WORD boundaries.
    • FLASH_MANAGER_DATA_PER_PAGE is
      (PAGE_SIZE - sizeof(flash_manager_metadata_t))
    • LARGEST_ENTRY_SIZE is ACCESS_MODEL_STATE_FLASH_SIZE
  • DSM_FLASH_PAGE_COUNT shall be equal to or greater than
       (1 + ((DATA_SIZE) / (FLASH_MANAGER_DATA_PER_PAGE - LARGEST_ENTRY_SIZE)))
    
    • DATA_SIZE is
      (ALIGN_VAL((sizeof(fm_header_t) + sizeof(dsm_flash_entry_addr_unicast_t)), WORD_SIZE) +
      ALIGN_VAL((sizeof(fm_header_t) + sizeof(dsm_flash_entry_addr_nonvirtual_t)), WORD_SIZE) * DSM_NONVIRTUAL_ADDR_MAX +
      ALIGN_VAL((sizeof(fm_header_t) + sizeof(dsm_flash_entry_addr_virtual_t)), WORD_SIZE) * DSM_VIRTUAL_ADDR_MAX +
      ALIGN_VAL((sizeof(fm_header_t) + sizeof(dsm_flash_entry_subnet_t)), WORD_SIZE) * DSM_SUBNET_MAX +
      ALIGN_VAL((sizeof(fm_header_t) + sizeof(dsm_flash_entry_devkey_t)), WORD_SIZE) * DSM_DEVICE_MAX +
      ALIGN_VAL((sizeof(fm_header_t) + sizeof(dsm_flash_entry_appkey_t)), WORD_SIZE) * DSM_APP_MAX)
    • FLASH_MANAGER_DATA_PER_PAGE is
      (PAGE_SIZE - sizeof(flash_manager_metadata_t))
    • LARGEST_ENTRY_SIZE is
      (sizeof(fm_header_t) + sizeof(dsm_flash_entry_t))

Estimated sizes @anchor coexistence_mesh_in_nrf5_sdk_sizes

The following table lists estimated sizes based on the Light switch server example, built using Keil v5 with optimization level O3 for nRF52832.

Definitions @anchor coexistence_mesh_in_nrf5_sdk_sizes_definitions

Definition Value
ACCESS_MODEL_COUNT 3
ACCESS_SUBSCRIPTION_LIST_COUNT 1
ACCESS_ELEMENT_COUNT 1
DSM_NONVIRTUAL_ADDR_MAX 3
DSM_VIRTUAL_ADDR_MAX 1
DSM_SUBNET_MAX 1
DSM_DEVICE_MAX 1
DSM_APP_MAX 1

Base sizes @anchor coexistence_mesh_in_nrf5_sdk_sizes_base_sizes

Structure/union Size in bytes
fm_header_t 4
access_model_state_data_t 20
access_flash_subscription_list_t 4
dsm_local_unicast_address_t 4
dsm_flash_entry_addr_nonvirtual_t 2
dsm_flash_entry_addr_virtual_t 16
dsm_flash_entry_subnet_t 36
dsm_flash_entry_devkey_t 20
dsm_flash_entry_appkey_t 36
flash_manager_metadata_t 8
dsm_flash_entry_t 36

Results @anchor coexistence_mesh_in_nrf5_sdk_sizes_results

Count name Value
ACCESS_FLASH_PAGE_COUNT 1
DSM_FLASH_PAGE_COUNT 1
Total page count 4