This library is used for enabling and disabling the SoftDevice and for propagating SoftDevice events to the application.
This library has the following functionalities.
The API exposed by this module can be found in <InstallFolder>\components\softdevice\common
in the files nrf_sdh.h
, nrf_sdh_soc.h
, nrf_sdh_ant.h
, and nrf_sdh_ble.h
.
For API documentation of this module, see SoftDevice Handler.
The SoftDevice Handler library consists of four main modules.
This is the core of the SoftDevice Handler library. It handles requests for enabling or disabling the SoftDevice, and notifies about SoftDevice state changes (such as: about to be enabled, enabled, about to be disabled, disabled). This component also fetches stack events and dispatches them to the correct nrf_sdh_* library, where stands for soc, ant, or ble. To view and modify the configuration options of this module, refer to SoftDevice handler configuration.
This part of the library receives SoC events from the SoftDevice Handler library. Applications and other libraries can register with nrf_sdh_soc to receive these events by using the macro NRF_SDH_SOC_OBSERVER. To view and modify the configuration options of this module, refer to SoftDevice SoC event handler configuration.
This part of the library receives ANT events from the SoftDevice Handler library. Applications and other libraries can register with nrf_sdh_ant to receive these events by using the macro NRF_SDH_ANT_OBSERVER. To view and modify the configuration options of this module, refer to SoftDevice ANT event handler configuration.
This part of the library receives BLE events from the SoftDevice Handler library. Applications and other libraries can register with nrf_sdh_ble to receive these events by using the macro NRF_SDH_BLE_OBSERVER. To view and modify the configuration options of this module, refer to SoftDevice BLE event handler configuration.
The three nrf_sdh_* components have a similar role of sending a particular kind of stack events to their registered observers.
nrf_sdh_soc
: SoC eventsnrf_sdh_ant
: ANT eventsnrf_sdh_ble
: BLE events See Example of registering a BLE observer for a code example of how to register an observer.These three modules register with the core nrf_sdh
module using macros defined in the SoftDevice Handler library, in a similar way as their observers register to them. The nrf_sdh
core component then sends the specific stack events (SoC, ANT, or BLE) to the respective modules.
Apart from propagating stack events to the submodules, nrf_sdh
sends two other types of messages.
SoftDevice state requests.
Two types of requests are sent.
In certain situations, an observer might also want to delay or prevent enabling of the SoftDevice. For example, when a library is accessing the NVMC registers to write to flash, enabling the SoftDevice will result in an assert the next time when the library attempts to access these registers, because they are protected when the SoftDevice is enabled.
Each part of an application that wants to receive events from the different components of the SoftDevice Handler library must register itself by using the macros specified in the Library components section. The registering happens at compile time, even though the events themselves are sent out to the observers at runtime. A registered part of an application becomes an observer.
An observer is essentially a piece of code that listens for events. It consists of a handler function and its associated parameter - a context. Every handler function has a certain priority.
The priority of a handler is a number that specifies the order in which it receives events with respect to other handlers (of the same type of events - BLE, ANT, or SoC). Priority zero is the highest. It is possible to have several observers registered with the same priority, but then the order in which they receive events depends on the order in which the linker encounters the handlers during the linking process. Therefore, to be certain that a particular observer is the first one to receive an event, you must assign higher priority to it.
Example: Module A registers itself an observer of BLE events with (a handler) priority 1. Then, module B registers itself as an observer of BLE events with a handler of priority 0. When an event is pulled from the stack by the SoftDevice Handler library, it is dispatched to nrf_sdh_ble
, and from there, it is first sent to all observers that have a handler with priority zero, and then to all observers with a handler with priority 1. In consequence, module B receives the event before module A.
These priorities may be crucial when the modules depend on each other. In the example above, module A might depend on module B to be up to date when module A is processing an event from the stack. For that to happen, module B must receive the event first.
Priorities can be configured by passing a parameter to the macro.
It is not recommended to modify the priority of any library that is included in this SDK. This may lead to unexpected problems.
However, when you create a new custom library and want to register it as an observer, you will have to assign a priority to it. In such case, a best practice is to assign to it a priority level that is lower than that for all other libraries. In this way, the rest of the application will have received the event and updated its state by the time the event reaches your library.
The default priority levels are already used by the existing libraries, so you must allocate an additional priority level and assign it to your library. To increase the number of priority levels, open the sdk_config
file and look for the NRF_SDH_*_PRIO_LEVELS configuration parameter (* represents the type of events - SoC, BLE, or ANT). The value of this parameter is the number of available priority levels and the lowest priority is that number minus one. Change the value to a higher number and then assign the newly created priority level to your custom library.
It might also happen that you will need your piece of code to run before that of other libraries. In such case, check what priority is used in that library, by opening its header or .c file. Do not modify the priority of this library, but try to adjust the priority of yours. If this solution does not fit your requirements, you can increase the total number of priority levels.
The following code snippet demonstrates how to enable the SoftDevice and the BLE stack.
The following code snippet demonstrates how to register a piece of code as an observer of BLE events.
The following code snippet demonstrates how to register a piece of code as an observer of SoftDevice state change events.
Using the SoftDevice state requests, a part of an application can prevent the SoftDevice from being disabled or enabled. For example, if the flash library has scheduled some flash operations, disabling the SoftDevice will make them fail. In such case, the flash library can use a dedicated macro to register itself with nrf_sdh
as a request observer. When another part of the application issues the nrf_sdh_disable_request() call, the flash library event handler for the SoftDevice Handler library will respond to this request.
The handler can then return FALSE
and abort the state change.
If it does so, it must afterwards call nrf_sdh_continue()
when the SoftDevice can be disabled safely, for example after the flash operation has been completed. This call restarts the state change procedure, which involves resending state requests to all observers. If they all return TRUE
, then the SoftDevice begins to change its state and the state events are sent.
The following code snippet demonstrates how to register a state request observer.
In the MSC below, a library requests to disable the SoftDevice. A request observer defers the state change to complete pending operations, and then it restarts the procedure. Finally, the SoftDevice changes its state and the library (a state observer) is notified of this.
This module uses conditional compilation. It expects certain preprocessor macros to be defined as follows.