diff --git a/doc/nrf-bm/libraries/nrf_sdh.rst b/doc/nrf-bm/libraries/nrf_sdh.rst new file mode 100644 index 0000000000..3aa273be64 --- /dev/null +++ b/doc/nrf-bm/libraries/nrf_sdh.rst @@ -0,0 +1,6 @@ +.. _lib_nrf_sdh: + +SoftDevice handler +################## + +The SoftDevice handler is a library that handles SoftDevice initialization tasks, and pulls and dispatches the SoftDevice events to registered components. diff --git a/doc/nrf-bm/release_notes/release_notes_changelog.rst b/doc/nrf-bm/release_notes/release_notes_changelog.rst index a7dc3187e1..86e2dbf61e 100644 --- a/doc/nrf-bm/release_notes/release_notes_changelog.rst +++ b/doc/nrf-bm/release_notes/release_notes_changelog.rst @@ -27,7 +27,26 @@ No changes since the latest nRF Connect SDK Bare Metal release. SoftDevice Handler ================== -No changes since the latest nRF Connect SDK Bare Metal release. +* Added: + + * The :option:`NRF_SDH_SOC_RAND_SEED` Kconfig option to control whether to automatically respond to SoftDevice random seed requests. + * Priority levels for SoftDevice event observers: HIGHEST, HIGH, USER, USER_LOW, LOWEST. + * The :c:func:`nrf_sdh_ble_evt_tostr` function to stringify a BLE event. + * The :c:func:`nrf_sdh_soc_evt_tostr` function to stringify a SoC event. + +* Changed: + + * The return type of the :c:type:`nrf_sdh_state_evt_handler_t` event handler to ``int``. + +* Removed: + + * The ``NRF_SDH_BLE`` Kconfig option. + * The ``NRF_SDH_STATE_REQ_OBSERVER`` macro and relative data types. + Register a state event observer and return non-zero to ``NRF_SDH_STATE_EVT_ENABLE_PREPARE`` + or ``NRF_SDH_STATE_EVT_DISABLE_PREPARE`` to abort state changes instead. + * The ``nrf_sdh_ble_app_ram_start_get`` function. + * The ``nrf_sdh_request_continue`` function. + * The ``nrf_sdh_is_enabled`` function. Boards ====== diff --git a/include/ble_adv.h b/include/ble_adv.h index addb0b00bd..6d19a2c971 100644 --- a/include/ble_adv.h +++ b/include/ble_adv.h @@ -27,18 +27,12 @@ extern "C" { #endif -/** - * @brief Advertising module BLE event observer priority. - */ -#define BLE_ADV_BLE_OBSERVER_PRIO 0 - /** * @brief Declare an instance of a BLE advertising library. */ #define BLE_ADV_DEF(instance) \ static struct ble_adv instance; \ - NRF_SDH_BLE_OBSERVER(ble_adv_##instance, ble_adv_on_ble_evt, &instance, \ - BLE_ADV_BLE_OBSERVER_PRIO) + NRF_SDH_BLE_OBSERVER(ble_adv_##instance, ble_adv_on_ble_evt, &instance, HIGH) /** * @brief Advertising modes. diff --git a/include/ble_gq.h b/include/ble_gq.h index 3cf8252e8a..82b2873a5d 100644 --- a/include/ble_gq.h +++ b/include/ble_gq.h @@ -75,7 +75,7 @@ extern "C" { .data_pool = &CONCAT(_name, _heap), \ }; \ NRF_SDH_BLE_OBSERVER(CONCAT(_name, _obs), ble_gq_on_ble_evt, (void *)&_name, \ - CONFIG_BLE_GQ_OBSERVER_PRIO) + HIGH) /** * @brief Helper macro for initializing connection handle array. Used in @ref BLE_GQ_CUSTOM_DEF. diff --git a/include/ble_qwr.h b/include/ble_qwr.h index 78067d9372..f42fc5bab4 100644 --- a/include/ble_qwr.h +++ b/include/ble_qwr.h @@ -41,7 +41,7 @@ extern "C" { NRF_SDH_BLE_OBSERVER(_name ## _obs, \ ble_qwr_on_ble_evt, \ &_name, \ - CONFIG_BLE_QWR_BLE_OBSERVER_PRIO) + HIGH) /* Error code used by the module to reject prepare write requests on non-registered attributes. */ #define BLE_QWR_REJ_REQUEST_ERR_CODE BLE_GATT_STATUS_ATTERR_APP_BEGIN + 0 diff --git a/include/bluetooth/services/ble_bas.h b/include/bluetooth/services/ble_bas.h index 99cdb7e8e5..184b01b8b5 100644 --- a/include/bluetooth/services/ble_bas.h +++ b/include/bluetooth/services/ble_bas.h @@ -29,7 +29,7 @@ extern "C" { #define BLE_BAS_DEF(_name) \ static struct ble_bas _name; \ extern void ble_bas_on_ble_evt(const ble_evt_t *ble_evt, void *ctx); \ - NRF_SDH_BLE_OBSERVER(_name##_obs, ble_bas_on_ble_evt, &_name, 0) + NRF_SDH_BLE_OBSERVER(_name##_obs, ble_bas_on_ble_evt, &_name, HIGH) /** * @brief Battery service event types. diff --git a/include/bluetooth/services/ble_cgms.h b/include/bluetooth/services/ble_cgms.h index d12c242128..41502ea4b8 100644 --- a/include/bluetooth/services/ble_cgms.h +++ b/include/bluetooth/services/ble_cgms.h @@ -17,14 +17,6 @@ * of the sensor. Session Run Time and Session Start Time can be used to convey timing * information between the sensor and the collector. The Specific Ops Control Point * is used to stop and start monitoring sessions, among other things. - * - * @note The application must register this module as BLE event observer using the - * NRF_SDH_BLE_OBSERVER macro. Example: - * @code - * struct ble_cgms instance; - * NRF_SDH_BLE_OBSERVER(anything, BLE_CGMS_BLE_OBSERVER_PRIO, - * ble_cgms_on_ble_evt, &instance); - * @endcode */ #ifndef BLE_CGMS_H__ @@ -51,7 +43,7 @@ extern "C" { static struct ble_cgms _name; \ NRF_SDH_BLE_OBSERVER(_name ## _obs, \ ble_cgms_on_ble_evt, &_name, \ - CONFIG_BLE_CGMS_BLE_OBSERVER_PRIO) + HIGH) #define OPCODE_LENGTH 1 #define HANDLE_LENGTH 2 diff --git a/include/bluetooth/services/ble_hids.h b/include/bluetooth/services/ble_hids.h index 273c619803..d00192ee0f 100644 --- a/include/bluetooth/services/ble_hids.h +++ b/include/bluetooth/services/ble_hids.h @@ -41,7 +41,7 @@ extern "C" { sizeof(uint32_t) * BYTES_TO_WORDS(BLE_HIDS_LINK_CTX_SIZE), \ }, \ }; \ - NRF_SDH_BLE_OBSERVER(_name##_obs, ble_hids_on_ble_evt, &_name, 0) + NRF_SDH_BLE_OBSERVER(_name##_obs, ble_hids_on_ble_evt, &_name, HIGH) /** * @brief HID boot keyboard input report maximum size, in bytes. diff --git a/include/bluetooth/services/ble_hrs.h b/include/bluetooth/services/ble_hrs.h index 07f82a8ff7..2e968a9802 100644 --- a/include/bluetooth/services/ble_hrs.h +++ b/include/bluetooth/services/ble_hrs.h @@ -30,7 +30,7 @@ extern "C" { #define BLE_HRS_DEF(_name) \ static struct ble_hrs _name; \ extern void ble_hrs_on_ble_evt(const ble_evt_t *ble_evt, void *ctx); \ - NRF_SDH_BLE_OBSERVER(_name##_obs, ble_hrs_on_ble_evt, &_name, 0) + NRF_SDH_BLE_OBSERVER(_name##_obs, ble_hrs_on_ble_evt, &_name, HIGH) /** * @defgroup BLE_HRS_BODY_SENSOR_LOCATION HRS Body sensor location diff --git a/include/bluetooth/services/ble_lbs.h b/include/bluetooth/services/ble_lbs.h index 06865a09c8..05cef390c0 100644 --- a/include/bluetooth/services/ble_lbs.h +++ b/include/bluetooth/services/ble_lbs.h @@ -20,8 +20,6 @@ extern "C" { #endif -#define BLE_LBS_BLE_OBSERVER_PRIO 2 - #define BLE_UUID_LBS_BASE { 0x23, 0xD1, 0xBC, 0xEA, 0x5F, 0x78, 0x23, 0x15, \ 0xDE, 0xEF, 0x12, 0x12, 0x00, 0x00, 0x00, 0x00 } #define BLE_UUID_LBS_SERVICE 0x1523 @@ -39,7 +37,7 @@ struct ble_lbs; #define BLE_LBS_DEF(_name) \ static struct ble_lbs _name; \ extern void ble_lbs_on_ble_evt(const ble_evt_t *ble_evt, void *lbs_instance); \ - NRF_SDH_BLE_OBSERVER(_name ## _obs, ble_lbs_on_ble_evt, &_name, BLE_LBS_BLE_OBSERVER_PRIO) + NRF_SDH_BLE_OBSERVER(_name ## _obs, ble_lbs_on_ble_evt, &_name, HIGH) enum ble_lbs_evt_type { BLE_LBS_EVT_LED_WRITE, diff --git a/include/bluetooth/services/ble_nus.h b/include/bluetooth/services/ble_nus.h index 21c252b873..c7e30b2c03 100644 --- a/include/bluetooth/services/ble_nus.h +++ b/include/bluetooth/services/ble_nus.h @@ -48,7 +48,7 @@ void ble_nus_on_ble_evt(ble_evt_t const *ble_evt, void *context); NRF_SDH_BLE_OBSERVER(_name ## _obs, \ ble_nus_on_ble_evt, \ &_name, \ - 0) + HIGH) #define OPCODE_LENGTH 1 #define HANDLE_LENGTH 2 diff --git a/include/nrf_sdh.h b/include/nrf_sdh.h index 9a73809971..49031a9764 100644 --- a/include/nrf_sdh.h +++ b/include/nrf_sdh.h @@ -15,6 +15,8 @@ #define NRF_SDH_H__ #include +#include +#include #include #ifdef __cplusplus @@ -22,66 +24,56 @@ extern "C" { #endif /** - * @brief SoftDevice Handler state requests. + * @defgroup softdevice_observer_prio SoftDevice event observer priority levels + * + * A SoftDevice observer has a defined priority, which determines the order with + * which the observer receives relevant events compared to other observers. + * + * Five priority levels are defined, highest, high, user, user low, lowest. + * These can be selected using the tokens HIGHEST, HIGH, USER, USER_LOW, and LOWEST respectively. + * + * In general, an observer priority must be defined in such a way that an observer + * has a lower priority than that of other observers (libraries, etc.) it depends on. + * + * @{ */ -enum nrf_sdh_state_req { - /** - * @brief Request to disable the SoftDevice. - */ - NRF_SDH_STATE_REQ_DISABLE, - /** - * @brief Request to enable the SoftDevice. - */ - NRF_SDH_STATE_REQ_ENABLE, -}; + + +/* Helper macros to check for equality */ + +#define H_NRF_SDH_OBSERVER_PRIO_HIGHEST_HIGHEST 1 +#define H_NRF_SDH_OBSERVER_PRIO_HIGH_HIGH 1 +#define H_NRF_SDH_OBSERVER_PRIO_USER_USER 1 +#define H_NRF_SDH_OBSERVER_PRIO_USER_LOW_USER_LOW 1 +#define H_NRF_SDH_OBSERVER_PRIO_LOWEST_LOWEST 1 /** - * @brief SoftDevice Handler state request handler. - * - * @retval true If ready for the SoftDevice to change state. - * @retval false If not ready for the SoftDevice to change state. - * If false is returned, the state change is aborted. + * @brief Utility macro to check for observer priority validity. + * @internal */ -typedef bool (*nrf_sdh_state_req_handler_t)(enum nrf_sdh_state_req request, void *context); +#define PRIO_LEVEL_IS_VALID(level) \ + COND_CODE_1(H_NRF_SDH_OBSERVER_PRIO_HIGHEST_##level, (), \ + (COND_CODE_1(H_NRF_SDH_OBSERVER_PRIO_HIGH_##level, (), \ + (COND_CODE_1(H_NRF_SDH_OBSERVER_PRIO_USER_##level, (), \ + (COND_CODE_1(H_NRF_SDH_OBSERVER_PRIO_USER_LOW_##level, (), \ + (COND_CODE_1(H_NRF_SDH_OBSERVER_PRIO_LOWEST_##level, (), \ + (BUILD_ASSERT(0, "Invalid priority level"))))))))))) /** - * @brief SoftDevice Handler state request observer. + * @brief Utility macro to convert a priority token to its numerical value + * @internal */ -struct nrf_sdh_state_req_observer { - /** - * @brief State request handler. - */ - nrf_sdh_state_req_handler_t handler; - /** - * @brief A context parameter for the handler function. - */ - void *context; -}; +#define PRIO_LEVEL_ORD(level) \ + COND_CODE_1(H_NRF_SDH_OBSERVER_PRIO_HIGHEST_##level, (0), \ + (COND_CODE_1(H_NRF_SDH_OBSERVER_PRIO_HIGH_##level, (1), \ + (COND_CODE_1(H_NRF_SDH_OBSERVER_PRIO_USER_##level, (2), \ + (COND_CODE_1(H_NRF_SDH_OBSERVER_PRIO_USER_LOW_##level, (3), \ + (COND_CODE_1(H_NRF_SDH_OBSERVER_PRIO_LOWEST_##level, (4), \ + (BUILD_ASSERT(0, "Invalid priority level"))))))))))) /** - * @brief Register a SoftDevice state request observer. - * - * An observer of SoftDevice state requests receives requests to change the state of the - * SoftDevice from enabled to disabled and vice versa. These requests may or may not be - * acknowledged by the observer, depending on the value returned by its request handler function. - * Thus, a request observer has the capability to defer the change of state of the SoftDevice. - * If it does so, it has the responsibility to call @ref nrf_sdh_request_continue when it is ready - * to let the SoftDevice change its state. If such capability is not necessary and you only need - * to be informed about changes of SoftDevice state, use @ref NRF_SDH_STATE_EVT_OBSERVER instead. - * - * @param _observer Name of the observer. - * @param _handler State request handler. - * @param _ctx A context passed to the state request handler. - * @param _prio Priority of the observer's event handler. - * The lower the number, the higher the priority. + * @} */ -#define NRF_SDH_STATE_REQ_OBSERVER(_observer, _handler, _ctx, _prio) \ - static bool _handler(enum nrf_sdh_state_req, void *); \ - const TYPE_SECTION_ITERABLE(struct nrf_sdh_state_req_observer, _observer, \ - nrf_sdh_state_req_observers, _prio) = { \ - .handler = _handler, \ - .context = _ctx, \ - }; /** * @brief SoftDevice Handler state events. @@ -89,6 +81,8 @@ struct nrf_sdh_state_req_observer { enum nrf_sdh_state_evt { /** * @brief SoftDevice is going to be enabled. + * + * The state change can be halted by returning non-zero when receiving this event. */ NRF_SDH_STATE_EVT_ENABLE_PREPARE, /** @@ -101,6 +95,8 @@ enum nrf_sdh_state_evt { NRF_SDH_STATE_EVT_BLE_ENABLED, /** * @brief SoftDevice is going to be disabled. + * + * The state change can be halted by returning non-zero when receiving this event. */ NRF_SDH_STATE_EVT_DISABLE_PREPARE, /** @@ -111,8 +107,11 @@ enum nrf_sdh_state_evt { /** * @brief SoftDevice Handler state event handler. + * + * @retval 0 If ready for the SoftDevice to change state. + * @retval 1 If not ready for the SoftDevice to change state (state change is halted). */ -typedef void (*nrf_sdh_state_evt_handler_t)(enum nrf_sdh_state_evt state, void *context); +typedef int (*nrf_sdh_state_evt_handler_t)(enum nrf_sdh_state_evt state, void *context); /** * @brief SoftDevice Handler state observer. @@ -131,24 +130,25 @@ struct nrf_sdh_state_evt_observer { /** * @brief Register a SoftDevice state observer. * - * A SoftDevice state observer receives events when the SoftDevice state has changed or is - * about to change. These events are only meant to inform the state observer, which, contrary - * to a state request observer, does not have the capability to defer the change of state. - * If such capability is required, use @ref NRF_SDH_STATE_REQ_OBSERVER instead. + * A SoftDevice state observer receives events when the SoftDevice state has changed + * or is about to change. An observer may return non-zero when receiving + * @ref NRF_SDH_STATE_EVT_ENABLE_PREPARE or @ref NRF_SDH_STATE_EVT_DISABLE_PREPARE + * to halt the state change. * * @param _observer Name of the observer. * @param _handler State request handler. * @param _ctx A context passed to the state request handler. * @param _prio Priority of the observer's event handler. - * The lower the number, the higher the priority. + * Allowed input: `HIGHEST`, `HIGH`, `USER`, `USER_LOW`, `LOWEST`. */ #define NRF_SDH_STATE_EVT_OBSERVER(_observer, _handler, _ctx, _prio) \ - static void _handler(enum nrf_sdh_state_evt, void *); \ + PRIO_LEVEL_IS_VALID(_prio); \ + static int _handler(enum nrf_sdh_state_evt, void *); \ const TYPE_SECTION_ITERABLE(struct nrf_sdh_state_evt_observer, _observer, \ - nrf_sdh_state_evt_observers, _prio) = { \ + nrf_sdh_state_evt_observers, PRIO_LEVEL_ORD(_prio)) = { \ .handler = _handler, \ .context = _ctx, \ - }; + } /** * @brief SoftDevice stack event handler. @@ -180,66 +180,43 @@ struct nrf_sdh_stack_evt_observer { * @param _handler Stack event handler. * @param _ctx A context passed to the state request handler. * @param _prio Priority of the observer's event handler. - * The lower the number, the higher the priority. + * Allowed input: `HIGHEST`, `HIGH`, `USER`, `USER_LOW`, `LOWEST`. */ #define NRF_SDH_STACK_EVT_OBSERVER(_observer, _handler, _ctx, _prio) \ + PRIO_LEVEL_IS_VALID(_prio); \ static void _handler(void *); \ const TYPE_SECTION_ITERABLE(struct nrf_sdh_stack_evt_observer, _observer, \ - nrf_sdh_stack_evt_observers, _prio) = { \ + nrf_sdh_stack_evt_observers, PRIO_LEVEL_ORD(_prio)) = { \ .handler = _handler, \ .context = _ctx, \ - }; + } /** * @brief Enable the SoftDevice. * - * This function issues a @ref NRF_SDH_STATE_REQ_ENABLE request to all observers that - * were registered using the @ref NRF_SDH_STATE_REQ_OBSERVER macro. The observers may or - * may not acknowledge the request. If all observers acknowledge the request, the - * SoftDevice is enabled. Otherwise, the process is stopped and the observers - * that did not acknowledge have the responsibility to restart it by calling - * @ref nrf_sdh_request_continue when they are ready for the SoftDevice to change state. + * Enable the SoftDevice and send state events to registered observers. + * An observer may halt the SoftDevice state change by returning non-zero when receiving + * @ref NRF_SDH_STATE_EVT_ENABLE_PREPARE. * * @retval 0 On success. * @retval -EALREADY The SoftDevice is already enabled. + * @retval -EBUSY An observer was busy, retry later. */ int nrf_sdh_enable_request(void); /** * @brief Disable the SoftDevice. * - * This function issues a @ref NRF_SDH_STATE_REQ_DISABLE request to all observers that - * were registered using the @ref NRF_SDH_STATE_REQ_OBSERVER macro. The observers may or - * may not acknowledge the request. If all observers acknowledge the request, the - * SoftDevice is disabled. Otherwise, the process is stopped and the observers - * that did not acknowledge have the responsibility to restart it by calling - * @ref nrf_sdh_request_continue when they are ready for the SoftDevice to change state. + * Disable the SoftDevice and send state events to registered observers. + * An observer may halt the SoftDevice state change by returning non-zero when receiving + * @ref NRF_SDH_STATE_EVT_DISABLE_PREPARE. * * @retval 0 On success. * @retval -EALREADY The SoftDevice is already disabled. + * @retval -EBUSY An observer was busy, retry later. */ int nrf_sdh_disable_request(void); -/** - * @brief Function for restarting the SoftDevice Enable/Disable process. - * - * Modules which did not acknowledge a @ref NRF_SDH_STATE_REQ_ENABLE or - * @ref NRF_SDH_STATE_REQ_DISABLE request must call this function to restart the - * SoftDevice state change process. - * - * @retval 0 On success. - * @retval -EINVAL No state change request was pending. - */ -int nrf_sdh_request_continue(void); - -/** - * @brief Retrieve the SoftDevice state. - * - * @retval true If the SoftDevice is enabled. - * @retval false If the SoftDevice is disabled. - */ -bool nrf_sdh_is_enabled(void); - /** * @brief Stop processing SoftDevice events. * diff --git a/include/nrf_sdh_ble.h b/include/nrf_sdh_ble.h index 6a54a0b453..720ea71a49 100644 --- a/include/nrf_sdh_ble.h +++ b/include/nrf_sdh_ble.h @@ -16,6 +16,7 @@ #define NRF_SDH_BLE_H__ #include +#include #include #include @@ -54,33 +55,35 @@ struct nrf_sdh_ble_evt_observer { * @param _handler State request handler. * @param _ctx A context passed to the state request handler. * @param _prio Priority of the observer's event handler. - * The lower the number, the higher the priority. + * Allowed input: `HIGHEST`, `HIGH`, `USER`, `USER_LOW`, `LOWEST`. */ #define NRF_SDH_BLE_OBSERVER(_observer, _handler, _ctx, _prio) \ + PRIO_LEVEL_IS_VALID(_prio); \ static const TYPE_SECTION_ITERABLE(struct nrf_sdh_ble_evt_observer, _observer, \ - nrf_sdh_ble_evt_observers, _prio) = { \ + nrf_sdh_ble_evt_observers, PRIO_LEVEL_ORD(_prio)) = { \ .handler = _handler, \ .context = _ctx, \ - }; + } /** - * @brief Retrieve the starting address of the application's RAM. + * @brief Enable the SoftDevice Bluetooth stack. * - * @param[out] app_ram_start The starting address of the application's RAM. + * @param[in] conn_tag Connection configuration tag. * * @retval 0 On success. - * @retval -EFAULT @p app_ram_start is @c NULL. */ -int nrf_sdh_ble_app_ram_start_get(uint32_t *app_ram_start); +int nrf_sdh_ble_enable(uint8_t conn_cfg_tag); /** - * @brief Enable the SoftDevice Bluetooth stack. + * @brief Stringify a SoftDevice BLE event. * - * @param[in] conn_tag Connection configuration tag. + * If :option:`CONFIG_NRF_SDH_STR_TABLES` is enabled, returns the event name. + * Otherwise, returns the supplied integer as a string. * - * @retval 0 On success. + * @param evt A @ref BLE_GAP_EVTS, @ref BLE_GATTS_EVTS, or @ref BLE_GATTC_EVTS enumeration value. + * @returns A statically allocated string containing the event name or numerical value. */ -int nrf_sdh_ble_enable(uint8_t conn_cfg_tag); +const char *nrf_sdh_ble_evt_tostr(uint32_t evt); /** * @brief Get the assigned index for a connection handle. diff --git a/include/nrf_sdh_soc.h b/include/nrf_sdh_soc.h index 875b460a12..51a4581d3e 100644 --- a/include/nrf_sdh_soc.h +++ b/include/nrf_sdh_soc.h @@ -16,6 +16,7 @@ #define NRF_SDH_SOC_H__ #include +#include #include #ifdef __cplusplus @@ -48,14 +49,26 @@ struct nrf_sdh_soc_evt_observer { * @param _handler State request handler. * @param _ctx A context passed to the state request handler. * @param _prio Priority of the observer's event handler. - * The lower the number, the higher the priority. + * Allowed input: `HIGHEST`, `HIGH`, `USER`, `USER_LOW`, `LOWEST`. */ #define NRF_SDH_SOC_OBSERVER(_observer, _handler, _ctx, _prio) \ + PRIO_LEVEL_IS_VALID(_prio); \ const TYPE_SECTION_ITERABLE(struct nrf_sdh_soc_evt_observer, _observer, \ - nrf_sdh_soc_evt_observers, _prio) = { \ + nrf_sdh_soc_evt_observers, PRIO_LEVEL_ORD(_prio)) = { \ .handler = _handler, \ .context = _ctx, \ - }; + } + +/** + * @brief Stringify a SoftDevice SoC event. + * + * If :option:`CONFIG_NRF_SDH_STR_TABLES` is enabled, returns the event name. + * Otherwise, returns the supplied integer as a string. + * + * @param evt An @ref NRF_SOC_SVCS enumeration value. + * @return A statically allocated string containing the event name or numerical value. + */ +const char *nrf_sdh_soc_evt_tostr(uint32_t evt); #ifdef __cplusplus } diff --git a/lib/ble_conn_params/att_mtu.c b/lib/ble_conn_params/att_mtu.c index 5f43261ec2..611fa74756 100644 --- a/lib/ble_conn_params/att_mtu.c +++ b/lib/ble_conn_params/att_mtu.c @@ -159,7 +159,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) mtu_exchange_request(conn_handle, idx); } } -NRF_SDH_BLE_OBSERVER(ble_observer, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(ble_observer, on_ble_evt, NULL, HIGH); int ble_conn_params_att_mtu_set(uint16_t conn_handle, uint16_t att_mtu) { diff --git a/lib/ble_conn_params/conn_param.c b/lib/ble_conn_params/conn_param.c index 6c1a0a4ba9..fe71ab8066 100644 --- a/lib/ble_conn_params/conn_param.c +++ b/lib/ble_conn_params/conn_param.c @@ -167,28 +167,30 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) break; } } -NRF_SDH_BLE_OBSERVER(ble_observer, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(ble_observer, on_ble_evt, NULL, HIGH); -static void on_state_evt(enum nrf_sdh_state_evt evt, void *ctx) +static int on_state_evt(enum nrf_sdh_state_evt evt, void *ctx) { int err; if (evt != NRF_SDH_STATE_EVT_BLE_ENABLED) { - return; + return 0; } err = sd_ble_gap_ppcp_set(&ppcp); if (err) { LOG_ERR("Failed to set preferred conn params, nrf_error %#x", err); - return; + return 0; } LOG_DBG("conn. interval min %u max %u, peripheral latency %u, sup. timeout %u", ppcp.min_conn_interval, ppcp.max_conn_interval, ppcp.slave_latency, ppcp.conn_sup_timeout); + + return 0; } -NRF_SDH_STATE_EVT_OBSERVER(ble_conn_params_sdh_state_observer, on_state_evt, NULL, 0); +NRF_SDH_STATE_EVT_OBSERVER(ble_conn_params_sdh_state_observer, on_state_evt, NULL, HIGH); int ble_conn_params_override(uint16_t conn_handle, const ble_gap_conn_params_t *conn_params) { diff --git a/lib/ble_conn_params/data_length.c b/lib/ble_conn_params/data_length.c index 1dc915b291..644dda968e 100644 --- a/lib/ble_conn_params/data_length.c +++ b/lib/ble_conn_params/data_length.c @@ -185,7 +185,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) data_length_update(conn_handle, idx); } } -NRF_SDH_BLE_OBSERVER(ble_observer, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(ble_observer, on_ble_evt, NULL, HIGH); int ble_conn_params_data_length_set(uint16_t conn_handle, struct ble_conn_params_data_length dl) { diff --git a/lib/ble_conn_params/phy_mode.c b/lib/ble_conn_params/phy_mode.c index d5493cd7a0..c20201a392 100644 --- a/lib/ble_conn_params/phy_mode.c +++ b/lib/ble_conn_params/phy_mode.c @@ -156,7 +156,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) radio_phy_mode_update(conn_handle, idx); } } -NRF_SDH_BLE_OBSERVER(ble_observer, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(ble_observer, on_ble_evt, NULL, HIGH); int ble_conn_params_phy_radio_mode_set(uint16_t conn_handle, ble_gap_phys_t phy_pref) { diff --git a/lib/ble_conn_state/Kconfig b/lib/ble_conn_state/Kconfig index 80b949960f..2cd7bc1d68 100644 --- a/lib/ble_conn_state/Kconfig +++ b/lib/ble_conn_state/Kconfig @@ -5,7 +5,7 @@ # menuconfig BLE_CONN_STATE bool "Connection state" - depends on NRF_SDH_BLE + depends on SOFTDEVICE help A library to defer event processing to main(). @@ -18,10 +18,6 @@ config BLE_CONN_STATE_USER_FLAG_COUNT help The number of available user flags. -config BLE_CONN_STATE_BLE_OBSERVER_PRIO - int "BLE observer priority" - default 0 - module=BLE_CONN_STATE module-str=BLE Connection state source "${ZEPHYR_BASE}/subsys/logging/Kconfig.template.log_config" diff --git a/lib/ble_conn_state/ble_conn_state.c b/lib/ble_conn_state/ble_conn_state.c index 1eb8977383..9c3c73432b 100644 --- a/lib/ble_conn_state/ble_conn_state.c +++ b/lib/ble_conn_state/ble_conn_state.c @@ -423,4 +423,4 @@ static void ble_evt_handler(ble_evt_t const *ble_evt, void *ctx) } NRF_SDH_BLE_OBSERVER(ble_evt_observer, ble_evt_handler, NULL, - CONFIG_BLE_CONN_STATE_BLE_OBSERVER_PRIO); + HIGHEST); diff --git a/lib/ble_gq/Kconfig b/lib/ble_gq/Kconfig index 4584a12248..4f7d64a96d 100644 --- a/lib/ble_gq/Kconfig +++ b/lib/ble_gq/Kconfig @@ -30,10 +30,6 @@ config BLE_GQ_HEAP_SIZE Default value used for GATT queue instances defined using BLE_GQ_DEF. Sets the heap size for storing additional data that can be of variable size. -config BLE_GQ_OBSERVER_PRIO - int "SoftDevice event observer priority" - default 0 - module=BLE_GQ module-str=BLE GATT Queue source "$(ZEPHYR_BASE)/subsys/logging/Kconfig.template.log_config" diff --git a/lib/ble_qwr/Kconfig b/lib/ble_qwr/Kconfig index c65997e7a9..8c943ff30d 100644 --- a/lib/ble_qwr/Kconfig +++ b/lib/ble_qwr/Kconfig @@ -14,10 +14,6 @@ config BLE_QWR_MAX_ATTR help Maximum queued writes attributes -config BLE_QWR_BLE_OBSERVER_PRIO - int "BLE observer priority" - default 2 - module=BLE_QWR module-str=BLE QWR source "$(ZEPHYR_BASE)/subsys/logging/Kconfig.template.log_config" diff --git a/lib/bm_storage/sd/bm_storage_sd.c b/lib/bm_storage/sd/bm_storage_sd.c index 2c4b8e7d52..aff32bb35d 100644 --- a/lib/bm_storage/sd/bm_storage_sd.c +++ b/lib/bm_storage/sd/bm_storage_sd.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -64,15 +65,13 @@ struct bm_storage_sd_state { static struct bm_storage_sd_state state; static void on_soc_evt(uint32_t evt, void *ctx); -static bool on_state_req_change(enum nrf_sdh_state_req req, void *ctx); -static void on_state_evt_change(enum nrf_sdh_state_evt evt, void *ctx); +static int on_state_evt_change(enum nrf_sdh_state_evt evt, void *ctx); RING_BUF_DECLARE(sd_fifo, CONFIG_BM_STORAGE_BACKEND_SD_QUEUE_SIZE * sizeof(struct bm_storage_sd_op)); -NRF_SDH_SOC_OBSERVER(sdh_soc, on_soc_evt, NULL, 0); -NRF_SDH_STATE_REQ_OBSERVER(sdh_state_req, on_state_req_change, NULL, 0); -NRF_SDH_STATE_EVT_OBSERVER(sdh_state_evt, on_state_evt_change, NULL, 0); +NRF_SDH_SOC_OBSERVER(sdh_soc, on_soc_evt, NULL, HIGH); +NRF_SDH_STATE_EVT_OBSERVER(sdh_state_evt, on_state_evt_change, NULL, HIGH); static inline bool is_aligned32(uint32_t addr) { @@ -228,7 +227,7 @@ uint32_t bm_storage_backend_init(struct bm_storage *storage) return NRF_ERROR_BUSY; } - state.sd_enabled = nrf_sdh_is_enabled(); + sd_softdevice_is_enabled((uint8_t *)&state.sd_enabled); state.type = BM_STORAGE_SD_STATE_IDLE; @@ -341,27 +340,31 @@ static void on_soc_evt(uint32_t evt, void *ctx) if (!state.paused) { queue_process(); - } else { - nrf_sdh_request_continue(); } } -static void on_state_evt_change(enum nrf_sdh_state_evt evt, void *ctx) +static int on_state_evt_change(enum nrf_sdh_state_evt evt, void *ctx) { - if ((evt == NRF_SDH_STATE_EVT_ENABLED) || (evt == NRF_SDH_STATE_EVT_DISABLED)) { + switch (evt) { + case NRF_SDH_STATE_EVT_ENABLE_PREPARE: + case NRF_SDH_STATE_EVT_DISABLE_PREPARE: + /* Only allow changing state when idle */ + state.paused = true; + return (state.type != BM_STORAGE_SD_STATE_IDLE); + + case NRF_SDH_STATE_EVT_ENABLED: + case NRF_SDH_STATE_EVT_DISABLED: + /* Continue executing any operation still in the queue */ state.paused = false; state.sd_enabled = (evt == NRF_SDH_STATE_EVT_ENABLED); - - /* Execute any operation still in the queue. */ queue_process(); - } -} + return 0; -static bool on_state_req_change(enum nrf_sdh_state_req req, void *ctx) -{ - state.paused = true; - - return (state.type == BM_STORAGE_SD_STATE_IDLE); + case NRF_SDH_STATE_EVT_BLE_ENABLED: + default: + /* Not interesting */ + return 0; + } } const struct bm_storage_info bm_storage_info = { diff --git a/lib/peer_manager/Kconfig b/lib/peer_manager/Kconfig index 8ddfef776d..901627adc7 100644 --- a/lib/peer_manager/Kconfig +++ b/lib/peer_manager/Kconfig @@ -21,12 +21,6 @@ config PM_BM_ZMS_SECTOR_SIZE int "Sector size" default 1024 -config PM_BLE_OBSERVER_PRIO - int "Priority with which BLE events are dispatched to the Peer Manager module." - default 1 - help - Priority with which BLE events are dispatched to the Peer Manager module. - config PM_MAX_REGISTRANTS int "Number of event handlers that can be registered." default 3 diff --git a/lib/peer_manager/peer_manager.c b/lib/peer_manager/peer_manager.c index b36acb6762..aabde7c7ea 100644 --- a/lib/peer_manager/peer_manager.c +++ b/lib/peer_manager/peer_manager.c @@ -311,7 +311,7 @@ static void ble_evt_handler(ble_evt_t const *p_ble_evt, void *p_context) gcm_ble_evt_handler(p_ble_evt); } -NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, ble_evt_handler, NULL, CONFIG_PM_BLE_OBSERVER_PRIO); +NRF_SDH_BLE_OBSERVER(m_ble_evt_observer, ble_evt_handler, NULL, HIGH); /** @brief Function for resetting the internal state of this module. */ static void internal_state_reset(void) diff --git a/samples/bluetooth/ble_cgms/src/main.c b/samples/bluetooth/ble_cgms/src/main.c index 0255bd25f2..45b0c814cc 100644 --- a/samples/bluetooth/ble_cgms/src/main.c +++ b/samples/bluetooth/ble_cgms/src/main.c @@ -509,7 +509,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) } } -NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, USER_LOW); /** * @brief Function for handling advertising events. diff --git a/samples/bluetooth/ble_hids_keyboard/src/main.c b/samples/bluetooth/ble_hids_keyboard/src/main.c index 52bd2135f6..6a72207dd2 100644 --- a/samples/bluetooth/ble_hids_keyboard/src/main.c +++ b/samples/bluetooth/ble_hids_keyboard/src/main.c @@ -242,7 +242,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) break; } } -NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, USER_LOW); static void ble_adv_evt_handler(struct ble_adv *ble_adv, const struct ble_adv_evt *evt) { diff --git a/samples/bluetooth/ble_hids_mouse/src/main.c b/samples/bluetooth/ble_hids_mouse/src/main.c index eac51e6af2..4e672e2b77 100644 --- a/samples/bluetooth/ble_hids_mouse/src/main.c +++ b/samples/bluetooth/ble_hids_mouse/src/main.c @@ -166,7 +166,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) break; } } -NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, USER_LOW); static void ble_adv_evt_handler(struct ble_adv *ble_adv, const struct ble_adv_evt *evt) { diff --git a/samples/bluetooth/ble_hrs/src/main.c b/samples/bluetooth/ble_hrs/src/main.c index b98abadc76..839b9ebd51 100644 --- a/samples/bluetooth/ble_hrs/src/main.c +++ b/samples/bluetooth/ble_hrs/src/main.c @@ -252,7 +252,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) break; } } -NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, USER_LOW); void on_conn_params_evt(const struct ble_conn_params_evt *evt) { diff --git a/samples/bluetooth/ble_lbs/src/main.c b/samples/bluetooth/ble_lbs/src/main.c index 02051c68fc..e8862490c0 100644 --- a/samples/bluetooth/ble_lbs/src/main.c +++ b/samples/bluetooth/ble_lbs/src/main.c @@ -72,7 +72,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) break; } } -NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, USER_LOW); static void ble_adv_evt_handler(struct ble_adv *adv, const struct ble_adv_evt *adv_evt) { diff --git a/samples/bluetooth/ble_nus/src/main.c b/samples/bluetooth/ble_nus/src/main.c index 70aa00f9c0..bd1762c885 100644 --- a/samples/bluetooth/ble_nus/src/main.c +++ b/samples/bluetooth/ble_nus/src/main.c @@ -237,7 +237,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) break; } } -NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, USER_LOW); /** * @brief Connection parameters event handler diff --git a/samples/bluetooth/ble_pwr_profiling/src/main.c b/samples/bluetooth/ble_pwr_profiling/src/main.c index 6ade3c224d..b8f85ec4dc 100644 --- a/samples/bluetooth/ble_pwr_profiling/src/main.c +++ b/samples/bluetooth/ble_pwr_profiling/src/main.c @@ -356,7 +356,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) break; } } -NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, USER_LOW); static void on_conn_params_evt(const struct ble_conn_params_evt *evt) { diff --git a/samples/bluetooth/hello_softdevice/src/main.c b/samples/bluetooth/hello_softdevice/src/main.c index 8e2279b59d..eeb329dd1c 100644 --- a/samples/bluetooth/hello_softdevice/src/main.c +++ b/samples/bluetooth/hello_softdevice/src/main.c @@ -18,19 +18,21 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) { LOG_INF("BLE event %d", evt->header.evt_id); } -NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, USER_LOW); static void on_soc_evt(uint32_t evt, void *ctx) { LOG_INF("SoC event"); } -NRF_SDH_SOC_OBSERVER(sdh_soc, on_soc_evt, NULL, 0); +NRF_SDH_SOC_OBSERVER(sdh_soc, on_soc_evt, NULL, USER_LOW); -static void on_state_change(enum nrf_sdh_state_evt state, void *ctx) +static int on_state_change(enum nrf_sdh_state_evt state, void *ctx) { - LOG_INF("SoftDevice state has changed to %d", state); + LOG_INF("SoftDevice state %d", state); + + return 0; } -NRF_SDH_STATE_EVT_OBSERVER(sdh_state, on_state_change, NULL, 0); +NRF_SDH_STATE_EVT_OBSERVER(sdh_state, on_state_change, NULL, USER_LOW); int main(void) { diff --git a/samples/boot/mcuboot_recovery_entry/prj.conf b/samples/boot/mcuboot_recovery_entry/prj.conf index 67ad8f7922..4357ffffae 100644 --- a/samples/boot/mcuboot_recovery_entry/prj.conf +++ b/samples/boot/mcuboot_recovery_entry/prj.conf @@ -13,7 +13,6 @@ CONFIG_BLE_ADV_NAME="nRF_BM_Entry" CONFIG_BLE_ADV_EXTENDED_ADVERTISING=n CONFIG_BLE_ADV_DIRECTED_ADVERTISING=n CONFIG_SOFTDEVICE=y -CONFIG_NRF_SDH_BLE=y CONFIG_NRF_SDH=y CONFIG_NRF_SECURITY=y CONFIG_MBEDTLS_PSA_CRYPTO_C=y diff --git a/samples/boot/mcuboot_recovery_entry/src/main.c b/samples/boot/mcuboot_recovery_entry/src/main.c index 378f9c65f1..279ee91ec8 100644 --- a/samples/boot/mcuboot_recovery_entry/src/main.c +++ b/samples/boot/mcuboot_recovery_entry/src/main.c @@ -117,7 +117,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) }; } -NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, USER_LOW); static void ble_adv_evt_handler(struct ble_adv *adv, const struct ble_adv_evt *adv_evt) { diff --git a/samples/mcumgr/ble_mcumgr/prj.conf b/samples/mcumgr/ble_mcumgr/prj.conf index 6cc933cb07..b311866cdd 100644 --- a/samples/mcumgr/ble_mcumgr/prj.conf +++ b/samples/mcumgr/ble_mcumgr/prj.conf @@ -38,7 +38,6 @@ CONFIG_MCUMGR_GRP_OS_RESET_HOOK=y CONFIG_MCUMGR_GRP_OS_ECHO=y CONFIG_MCUMGR_GRP_OS_MCUMGR_PARAMS=y CONFIG_MCUMGR_GRP_OS_BOOTLOADER_INFO=y -CONFIG_NRF_SDH_BLE=y CONFIG_NRF_SDH=y CONFIG_NRF_SECURITY=y CONFIG_MBEDTLS_PSA_CRYPTO_C=y diff --git a/samples/mcumgr/ble_mcumgr/src/main.c b/samples/mcumgr/ble_mcumgr/src/main.c index e4d8347849..c46ce0f89a 100644 --- a/samples/mcumgr/ble_mcumgr/src/main.c +++ b/samples/mcumgr/ble_mcumgr/src/main.c @@ -125,7 +125,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) }; } -NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, 0); +NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, NULL, USER_LOW); /** * @brief BLE advertising event handler diff --git a/subsys/bluetooth/services/ble_cgms/Kconfig b/subsys/bluetooth/services/ble_cgms/Kconfig index 8dabff42c4..d687dafdc8 100644 --- a/subsys/bluetooth/services/ble_cgms/Kconfig +++ b/subsys/bluetooth/services/ble_cgms/Kconfig @@ -9,10 +9,6 @@ menuconfig BLE_CGMS if BLE_CGMS -config BLE_CGMS_BLE_OBSERVER_PRIO - int "SoftDevice event observer priority" - default 0 - config BLE_CGMS_DB_RECORDS_MAX int "Number of records that can be stored in the database" default 100 diff --git a/subsys/bluetooth/services/ble_mcumgr/mcumgr.c b/subsys/bluetooth/services/ble_mcumgr/mcumgr.c index 2c0a3d2d52..edd6b7eb41 100644 --- a/subsys/bluetooth/services/ble_mcumgr/mcumgr.c +++ b/subsys/bluetooth/services/ble_mcumgr/mcumgr.c @@ -372,7 +372,7 @@ static void on_ble_evt(const ble_evt_t *evt, void *ctx) }; } -NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, &ble_mcumgr, 0); +NRF_SDH_BLE_OBSERVER(sdh_ble, on_ble_evt, &ble_mcumgr, HIGH); int ble_mcumgr_init(void) { diff --git a/subsys/softdevice_handler/CMakeLists.txt b/subsys/softdevice_handler/CMakeLists.txt index 5fc6b858a4..5d7e2d36a7 100644 --- a/subsys/softdevice_handler/CMakeLists.txt +++ b/subsys/softdevice_handler/CMakeLists.txt @@ -8,9 +8,12 @@ zephyr_linker_sources(SECTIONS sdh.ld) zephyr_library_sources( nrf_sdh.c nrf_sdh_soc.c + nrf_sdh_ble.c irq_connect.c ) +zephyr_library_sources_ifdef(CONFIG_NRF_SDH_SOC_RAND_SEED rand_seed.c) + if(CONFIG_SOFTDEVICE_S115) zephyr_library_sources(irq_forward.s) # Suppress the swap_helper.S file so that z_arm_svc can be defined manually @@ -22,7 +25,3 @@ if(CONFIG_SOFTDEVICE_S115) ) target_link_options(app PUBLIC "-Wl,--defsym=z_arm_svc=SVC_Handler") endif() - -if(CONFIG_NRF_SDH_BLE) - zephyr_library_sources(nrf_sdh_ble.c) -endif() diff --git a/subsys/softdevice_handler/Kconfig b/subsys/softdevice_handler/Kconfig index 7963774245..a34f31f7cd 100644 --- a/subsys/softdevice_handler/Kconfig +++ b/subsys/softdevice_handler/Kconfig @@ -6,16 +6,9 @@ menuconfig NRF_SDH bool "Softdevice handler" depends on SOFTDEVICE - depends on NRF_SECURITY - depends on MBEDTLS_PSA_CRYPTO_C - depends on PSA_WANT_GENERATE_RANDOM if NRF_SDH -config NRF_SDH_BLE - bool "BLE events" - default y - choice prompt "Dispatch model" default NRF_SDH_DISPATCH_MODEL_SCHED @@ -46,6 +39,8 @@ config NRF_SDH_DISPATCH_MODEL default 1 if NRF_SDH_DISPATCH_MODEL_SCHED default 2 if NRF_SDH_DISPATCH_MODEL_POLL +menu "Clock configuration" + config NRF_SDH_CLOCK_LF_SRC int "LF Clock" default 1 @@ -62,7 +57,9 @@ config NRF_SDH_CLOCK_LF_ACCURACY int "Accuracy" default 0 -if NRF_SDH_BLE +endmenu + +menu "Default BLE configuration" config NRF_SDH_BLE_CONN_TAG int "Connection tag" @@ -111,14 +108,23 @@ config NRF_SDH_BLE_VS_UUID_COUNT config NRF_SDH_BLE_SERVICE_CHANGED bool "Include the Service Changed characteristic in the Attribute Table" -endif # NRF_SDH_BLE +endmenu + +config NRF_SDH_SOC_RAND_SEED + bool "Automatically respond to SoftDevice random seeds requests" + depends on NRF_SECURITY + depends on MBEDTLS_PSA_CRYPTO_C + default y + help + Automatically seed SoftDevice upon NRF_EVT_RAND_SEED_REQUEST events, + using CRACEN to generate the random seed. config NRF_SDH_STR_TABLES - bool "Build string tables for SoftDevice handler events" + bool "Build string tables for SoftDevice events" default y help - Make prints nicer by printing the stringified version of certain enumerations. - Disable to save non-volatile memory. + Compile a table of stringified SoftDevice events for nrf_sdh_ble_evt_tostr() and + nrf_sdh_soc_evt_tostr(). Disable to save non-volatile memory. module=NRF_SDH module-str= SoftDevice handler log level diff --git a/subsys/softdevice_handler/nrf_sdh.c b/subsys/softdevice_handler/nrf_sdh.c index 7060b79a8d..e56455e2eb 100644 --- a/subsys/softdevice_handler/nrf_sdh.c +++ b/subsys/softdevice_handler/nrf_sdh.c @@ -19,21 +19,9 @@ LOG_MODULE_REGISTER(nrf_sdh, CONFIG_NRF_SDH_LOG_LEVEL); #warning Please select NRF_CLOCK_LF_ACCURACY_500_PPM when using NRF_CLOCK_LF_SRC_RC #endif -static atomic_t sdh_enabled; /* Whether the SoftDevice is enabled. */ -static atomic_t sdh_suspended; /* Whether this module is suspended. */ -static atomic_t sdh_transition; /* Whether enable/disable process was started. */ +/* Whether this module is pulling SoftDevice events or not. */ +static atomic_t sdh_is_suspended; -static char *req_tostr(enum nrf_sdh_state_req r) -{ - switch (r) { - case NRF_SDH_STATE_REQ_ENABLE: - return "enable"; - case NRF_SDH_STATE_REQ_DISABLE: - return "disable"; - default: - return "unknown"; - }; -} static char *state_tostr(enum nrf_sdh_state_evt s) { switch (s) { @@ -50,38 +38,37 @@ static char *state_tostr(enum nrf_sdh_state_evt s) }; } -static int sdh_state_req_observer_notify(enum nrf_sdh_state_req req) +/* Used in nrf_sdh_ble.c */ +int sdh_state_evt_observer_notify(enum nrf_sdh_state_evt state) { - if (IS_ENABLED(CONFIG_NRF_SDH_STR_TABLES)) { - LOG_INF("State change request: %s", req_tostr(req)); - } else { - LOG_INF("State change request: %#x", req); - } - - TYPE_SECTION_FOREACH(struct nrf_sdh_state_req_observer, nrf_sdh_state_req_observers, obs) { - if (obs->handler(req, obs->context)) { - LOG_DBG("Notify observer %p => ready", obs); - } else { - /* Do not let SoftDevice change state now */ - LOG_DBG("Notify observer %p => busy", obs); - return -EBUSY; - } - } + int busy; + bool busy_is_allowed; - return 0; -} - -static void sdh_state_evt_observer_notify(enum nrf_sdh_state_evt state) -{ if (IS_ENABLED(CONFIG_NRF_SDH_STR_TABLES)) { LOG_DBG("State change: %s", state_tostr(state)); } else { LOG_DBG("State change: %#x", state); } + busy_is_allowed = (state == NRF_SDH_STATE_EVT_ENABLE_PREPARE) || + (state == NRF_SDH_STATE_EVT_DISABLE_PREPARE); + TYPE_SECTION_FOREACH(struct nrf_sdh_state_evt_observer, nrf_sdh_state_evt_observers, obs) { - obs->handler(state, obs->context); + busy = obs->handler(state, obs->context); + if (!busy) { + continue; + } + if (!busy_is_allowed) { + __ASSERT(busy_is_allowed, + "Returning non-zero from these events is ignored"); + continue; + } + /* Do not let SoftDevice change state now */ + LOG_DBG("Notify observer %p => busy", obs); + return -EBUSY; } + + return 0; } __weak void softdevice_fault_handler(uint32_t id, uint32_t pc, uint32_t info) @@ -110,6 +97,7 @@ __weak void softdevice_fault_handler(uint32_t id, uint32_t pc, uint32_t info) int nrf_sdh_enable_request(void) { int err; + uint8_t sd_is_enabled; const nrf_clock_lf_cfg_t clock_lf_cfg = { .source = CONFIG_NRF_SDH_CLOCK_LF_SRC, .rc_ctiv = CONFIG_NRF_SDH_CLOCK_LF_RC_CTIV, @@ -117,39 +105,29 @@ int nrf_sdh_enable_request(void) .accuracy = CONFIG_NRF_SDH_CLOCK_LF_ACCURACY }; - if (sdh_enabled) { + (void)sd_softdevice_is_enabled(&sd_is_enabled); + if (sd_is_enabled) { return -EALREADY; } - atomic_set(&sdh_transition, true); - - err = sdh_state_req_observer_notify(NRF_SDH_STATE_REQ_ENABLE); + err = sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_ENABLE_PREPARE); if (err) { - /** TODO: should this be Success instead? */ - /* Leave sdh_transition to 1, so process can be continued */ - __ASSERT(err == -EBUSY, "Unknown return value %d from sdh req observer", err); return -EBUSY; } - atomic_set(&sdh_transition, false); - - /* Notify observers about starting SoftDevice enable process. */ - sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_ENABLE_PREPARE); - err = sd_softdevice_enable(&clock_lf_cfg, softdevice_fault_handler); if (err) { LOG_ERR("Failed to enable SoftDevice, nrf_error %#x", err); return -EINVAL; } - atomic_set(&sdh_enabled, true); - atomic_set(&sdh_suspended, false); + atomic_set(&sdh_is_suspended, false); /* Enable event interrupt, the priority has already been set by the stack. */ NVIC_EnableIRQ((IRQn_Type)SD_EVT_IRQn); /* Notify observers about a finished SoftDevice enable process. */ - sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_ENABLED); + (void)sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_ENABLED); return 0; } @@ -157,75 +135,65 @@ int nrf_sdh_enable_request(void) int nrf_sdh_disable_request(void) { int err; + uint8_t sd_is_enabled; - if (!sdh_enabled) { + (void)sd_softdevice_is_enabled(&sd_is_enabled); + if (!sd_is_enabled) { return -EALREADY; } - atomic_set(&sdh_transition, true); - - /* Notify observers about SoftDevice disable request. */ - err = sdh_state_req_observer_notify(NRF_SDH_STATE_REQ_DISABLE); + /* Notify observers about starting SoftDevice disable process. */ + err = sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_DISABLE_PREPARE); if (err) { - /** TODO: should this be Success instead? */ - /* Leave sdh_transition to 1, so process can be continued */ - __ASSERT(err == -EBUSY, "Unknown return value %d from sdh req observer", err); return -EBUSY; } - atomic_set(&sdh_transition, false); - - /* Notify observers about starting SoftDevice disable process. */ - sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_DISABLE_PREPARE); - err = sd_softdevice_disable(); if (err) { LOG_ERR("Failed to disable SoftDevice, nrf_error %#x", err); return -EINVAL; } - atomic_set(&sdh_enabled, false); - NVIC_DisableIRQ((IRQn_Type)SD_EVT_IRQn); /* Notify observers about a finished SoftDevice enable process. */ - sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_DISABLED); + (void)sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_DISABLED); return 0; } -int nrf_sdh_request_continue(void) +void nrf_sdh_suspend(void) { - if (!sdh_transition) { - return -EINVAL; - } - - if (sdh_enabled) { - return nrf_sdh_disable_request(); - } else { - return nrf_sdh_enable_request(); - } -} + uint8_t sd_is_enabled; -bool nrf_sdh_is_enabled(void) -{ - return sdh_enabled; -} + (void)sd_softdevice_is_enabled(&sd_is_enabled); -void nrf_sdh_suspend(void) -{ - if (!sdh_enabled || sdh_suspended) { + if (!sd_is_enabled) { + LOG_WRN("Tried to suspend, but SoftDevice is disabled"); + return; + } + if (sdh_is_suspended) { + LOG_WRN("Tried to suspend, but already is suspended"); return; } NVIC_DisableIRQ((IRQn_Type)SD_EVT_IRQn); - atomic_set(&sdh_suspended, true); + atomic_set(&sdh_is_suspended, true); } void nrf_sdh_resume(void) { - if ((!sdh_suspended) || (!sdh_enabled)) { + uint8_t sd_is_enabled; + + (void)sd_softdevice_is_enabled(&sd_is_enabled); + + if (!sd_is_enabled) { + LOG_WRN("Tried to resume, but SoftDevice is disabled"); + return; + } + if (!sdh_is_suspended) { + LOG_WRN("Tried to resume, but not suspended"); return; } @@ -233,12 +201,12 @@ void nrf_sdh_resume(void) NVIC_SetPendingIRQ((IRQn_Type)SD_EVT_IRQn); NVIC_EnableIRQ((IRQn_Type)SD_EVT_IRQn); - atomic_set(&sdh_suspended, false); + atomic_set(&sdh_is_suspended, false); } bool nrf_sdh_is_suspended(void) { - return (!sdh_enabled) || (sdh_suspended); + return sdh_is_suspended; } void nrf_sdh_evts_poll(void) diff --git a/subsys/softdevice_handler/nrf_sdh_ble.c b/subsys/softdevice_handler/nrf_sdh_ble.c index 28c4f380b3..36bdb33bd2 100644 --- a/subsys/softdevice_handler/nrf_sdh_ble.c +++ b/subsys/softdevice_handler/nrf_sdh_ble.c @@ -6,18 +6,26 @@ #include #include +#include +#include #include #include -#include #include #define APP_RAM_START DT_REG_ADDR(DT_CHOSEN(zephyr_sram)) LOG_MODULE_DECLARE(nrf_sdh, CONFIG_NRF_SDH_LOG_LEVEL); -const char *gap_evt_tostr(int evt) +extern int sdh_state_evt_observer_notify(enum nrf_sdh_state_evt state); + +const char *nrf_sdh_ble_evt_tostr(uint32_t evt) { + int err; + static char buf[sizeof("BLE event: 0xFFFFFFFF")]; + switch (evt) { +#if defined(CONFIG_NRF_SDH_STR_TABLES) + /* GAP */ case BLE_GAP_EVT_CONNECTED: return "BLE_GAP_EVT_CONNECTED"; case BLE_GAP_EVT_DISCONNECTED: @@ -70,20 +78,60 @@ const char *gap_evt_tostr(int evt) #endif case BLE_GAP_EVT_ADV_SET_TERMINATED: return "BLE_GAP_EVT_ADV_SET_TERMINATED"; - default: - return "unknown"; - } -} -int nrf_sdh_ble_app_ram_start_get(uint32_t *app_ram_start) -{ - if (!app_ram_start) { - return -EFAULT; + /* GATTS */ + case BLE_GATTS_EVT_WRITE: + return "BLE_GATTS_EVT_WRITE"; + case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST: + return "BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST"; + case BLE_GATTS_EVT_SYS_ATTR_MISSING: + return "BLE_GATTS_EVT_SYS_ATTR_MISSING"; + case BLE_GATTS_EVT_HVC: + return "BLE_GATTS_EVT_HVC"; + case BLE_GATTS_EVT_SC_CONFIRM: + return "BLE_GATTS_EVT_SC_CONFIRM"; + case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST: + return "BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST"; + case BLE_GATTS_EVT_TIMEOUT: + return "BLE_GATTS_EVT_TIMEOUT"; + case BLE_GATTS_EVT_HVN_TX_COMPLETE: + return "BLE_GATTS_EVT_HVN_TX_COMPLETE"; + + /* GATTC */ + case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP: + return "BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP"; + case BLE_GATTC_EVT_REL_DISC_RSP: + return "BLE_GATTC_EVT_REL_DISC_RSP"; + case BLE_GATTC_EVT_CHAR_DISC_RSP: + return "BLE_GATTC_EVT_CHAR_DISC_RSP"; + case BLE_GATTC_EVT_DESC_DISC_RSP: + return "BLE_GATTC_EVT_DESC_DISC_RSP"; + case BLE_GATTC_EVT_ATTR_INFO_DISC_RSP: + return "BLE_GATTC_EVT_ATTR_INFO_DISC_RSP"; + case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP: + return "BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP"; + case BLE_GATTC_EVT_READ_RSP: + return "BLE_GATTC_EVT_READ_RSP"; + case BLE_GATTC_EVT_CHAR_VALS_READ_RSP: + return "BLE_GATTC_EVT_CHAR_VALS_READ_RSP"; + case BLE_GATTC_EVT_WRITE_RSP: + return "BLE_GATTC_EVT_WRITE_RSP"; + case BLE_GATTC_EVT_HVX: + return "BLE_GATTC_EVT_HVX"; + case BLE_GATTC_EVT_EXCHANGE_MTU_RSP: + return "BLE_GATTC_EVT_EXCHANGE_MTU_RSP"; + case BLE_GATTC_EVT_TIMEOUT: + return "BLE_GATTC_EVT_TIMEOUT"; + case BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE: + return "BLE_GATTC_EVT_WRITE_CMD_TX_COMPLETE"; +#endif + default: + err = snprintf(buf, sizeof(buf), "BLE event: %#x", evt); + __ASSERT(err > 0, "Encode error"); + __ASSERT(err < sizeof(buf), "Buffer too small"); + (void)err; + return buf; } - - *app_ram_start = APP_RAM_START; - - return 0; } static int default_cfg_set(void) @@ -202,9 +250,7 @@ int nrf_sdh_ble_enable(uint8_t conn_cfg_tag) LOG_DBG("SoftDevice BLE enabled"); - TYPE_SECTION_FOREACH(struct nrf_sdh_state_evt_observer, nrf_sdh_state_evt_observers, obs) { - obs->handler(NRF_SDH_STATE_EVT_BLE_ENABLED, obs->context); - } + (void)sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_BLE_ENABLED); return 0; } @@ -297,11 +343,7 @@ static void ble_evt_poll(void *context) break; } - if (IS_ENABLED(CONFIG_NRF_SDH_STR_TABLES)) { - LOG_DBG("BLE event: %s", gap_evt_tostr(ble_evt->header.evt_id)); - } else { - LOG_DBG("BLE event: %#x", ble_evt->header.evt_id); - } + LOG_DBG("%s", nrf_sdh_ble_evt_tostr(ble_evt->header.evt_id)); if (ble_evt->header.evt_id == BLE_GAP_EVT_CONNECTED) { idx_assign(ble_evt->evt.gap_evt.conn_handle); @@ -320,8 +362,8 @@ static void ble_evt_poll(void *context) /* An SoC event may have triggered this round of polling, and BLE may not be enabled */ __ASSERT((err == NRF_ERROR_NOT_FOUND) || (err == BLE_ERROR_NOT_ENABLED), - "Failed to receive SoftDevice event, nrf_error %#x", err); + "Failed to receive SoftDevice BLE event, nrf_error %#x", err); } /* Listen to SoftDevice events */ -NRF_SDH_STACK_EVT_OBSERVER(ble_evt_obs, ble_evt_poll, NULL, 0); +NRF_SDH_STACK_EVT_OBSERVER(ble_evt_obs, ble_evt_poll, NULL, HIGH); diff --git a/subsys/softdevice_handler/nrf_sdh_soc.c b/subsys/softdevice_handler/nrf_sdh_soc.c index 6a03bc5f26..caeae00a00 100644 --- a/subsys/softdevice_handler/nrf_sdh_soc.c +++ b/subsys/softdevice_handler/nrf_sdh_soc.c @@ -6,64 +6,51 @@ #include #include +#include +#include #include #include -#include -#include -#include #include LOG_MODULE_DECLARE(nrf_sdh, CONFIG_NRF_SDH_LOG_LEVEL); -static const char *tostr(uint32_t evt) +const char *nrf_sdh_soc_evt_tostr(uint32_t evt) { + int err; + static char buf[sizeof("SoC event: 0xFFFFFFFF")]; + switch (evt) { +#if defined(CONFIG_NRF_SDH_STR_TABLES) case NRF_EVT_HFCLKSTARTED: - return "The HFCLK has started"; + return "NRF_EVT_HFCLKSTARTED"; case NRF_EVT_POWER_FAILURE_WARNING: - return "A power failure warning has occurred"; + return "NRF_EVT_POWER_FAILURE_WARNING"; case NRF_EVT_FLASH_OPERATION_SUCCESS: - return "Flash operation has completed successfully"; + return "NRF_EVT_FLASH_OPERATION_SUCCESS"; case NRF_EVT_FLASH_OPERATION_ERROR: - return "Flash operation has timed out with an error"; + return "NRF_EVT_FLASH_OPERATION_ERROR"; case NRF_EVT_RADIO_BLOCKED: - return "A radio timeslot was blocked"; + return "NRF_EVT_RADIO_BLOCKED"; case NRF_EVT_RADIO_CANCELED: - return "A radio timeslot was canceled by SoftDevice"; + return "NRF_EVT_RADIO_CANCELED"; case NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN: - return "A radio timeslot signal callback handler return was invalid"; + return "NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN"; case NRF_EVT_RADIO_SESSION_IDLE: - return "A radio timeslot session is idle"; + return "NRF_EVT_RADIO_SESSION_IDLE"; case NRF_EVT_RADIO_SESSION_CLOSED: - return "A radio timeslot session is closed"; + return "NRF_EVT_RADIO_SESSION_CLOSED"; case NRF_EVT_RAND_SEED_REQUEST: - return "SoftDevice RNG needs to be seeded"; + return "NRF_EVT_RAND_SEED_REQUEST"; +#endif default: - return "Unknown"; + err = snprintf(buf, sizeof(buf), "SoC event: %#x", evt); + __ASSERT(err > 0, "Encode error"); + __ASSERT(err < sizeof(buf), "Buffer too small"); + (void)err; + return buf; } } -static void softdevice_rng_seed(void) -{ - uint32_t err = NRF_ERROR_INVALID_DATA; - psa_status_t status; - uint8_t seed[SD_RAND_SEED_SIZE]; - - status = cracen_get_trng(seed, sizeof(seed)); - if (status == PSA_SUCCESS) { - err = sd_rand_seed_set(seed); - memset(seed, 0, sizeof(seed)); - if (err == NRF_SUCCESS) { - LOG_DBG("SoftDevice RNG seeded"); - return; - } - } else { - LOG_ERR("Generate random failed, psa status %d", status); - } - - LOG_ERR("Failed to seed SoftDevice RNG, nrf_error %#x", err); -} - static void soc_evt_poll(void *context) { uint32_t err; @@ -75,15 +62,7 @@ static void soc_evt_poll(void *context) break; } - if (IS_ENABLED(CONFIG_NRF_SDH_STR_TABLES)) { - LOG_DBG("SoC event: %s", tostr(evt_id)); - } else { - LOG_DBG("SoC event: 0x%x", evt_id); - } - - if (evt_id == NRF_EVT_RAND_SEED_REQUEST) { - softdevice_rng_seed(); - } + LOG_DBG("%s", nrf_sdh_soc_evt_tostr(evt_id)); /* Forward the event to SoC observers. */ TYPE_SECTION_FOREACH( @@ -93,8 +72,8 @@ static void soc_evt_poll(void *context) } __ASSERT(err == NRF_ERROR_NOT_FOUND, - "Failed to receive SoftDevice event, nrf_error %#x", err); + "Failed to receive SoftDevice SoC event, nrf_error %#x", err); } /* Listen to SoftDevice events */ -NRF_SDH_STACK_EVT_OBSERVER(soc_evt_obs, soc_evt_poll, NULL, 0); +NRF_SDH_STACK_EVT_OBSERVER(soc_evt_obs, soc_evt_poll, NULL, HIGHEST); diff --git a/subsys/softdevice_handler/rand_seed.c b/subsys/softdevice_handler/rand_seed.c new file mode 100644 index 0000000000..284327840c --- /dev/null +++ b/subsys/softdevice_handler/rand_seed.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2025 Nordic Semiconductor ASA + * + * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause + */ + +#include +#include +#include +#include +#include + +LOG_MODULE_DECLARE(nrf_sdh, CONFIG_NRF_SDH_LOG_LEVEL); + +static void on_rand_seed_evt(uint32_t evt, void *ctx) +{ + uint32_t nrf_err; + psa_status_t status; + uint8_t seed[SD_RAND_SEED_SIZE]; + + if (evt != NRF_EVT_RAND_SEED_REQUEST) { + /* Not our business */ + return; + } + + status = cracen_get_trng(seed, sizeof(seed)); + if (status != PSA_SUCCESS) { + LOG_ERR("Failed to generate true random number, psa_status %d", status); + return; + } + + nrf_err = sd_rand_seed_set(seed); + + /* Discard seed immediately */ + memset(seed, 0, sizeof(seed)); + + if (nrf_err != NRF_SUCCESS) { + LOG_ERR("Failed to seed SoftDevice RNG, nrf_error %#x", nrf_err); + return; + } + + LOG_DBG("SoftDevice RNG seeded"); +} + +NRF_SDH_SOC_OBSERVER(rand_seed, on_rand_seed_evt, NULL, HIGH); diff --git a/subsys/softdevice_handler/sdh.ld b/subsys/softdevice_handler/sdh.ld index 72e1f6de28..d3a0c9d10a 100644 --- a/subsys/softdevice_handler/sdh.ld +++ b/subsys/softdevice_handler/sdh.ld @@ -1,4 +1,3 @@ -ITERABLE_SECTION_ROM(nrf_sdh_state_req_observers, 4) ITERABLE_SECTION_ROM(nrf_sdh_state_evt_observers, 4) ITERABLE_SECTION_ROM(nrf_sdh_stack_evt_observers, 4) ITERABLE_SECTION_ROM(nrf_sdh_soc_evt_observers, 4) diff --git a/tests/subsys/bluetooth/services/ble_nus/src/unity_test.c b/tests/subsys/bluetooth/services/ble_nus/src/unity_test.c index 9f020ce470..a628fa5697 100644 --- a/tests/subsys/bluetooth/services/ble_nus/src/unity_test.c +++ b/tests/subsys/bluetooth/services/ble_nus/src/unity_test.c @@ -15,7 +15,8 @@ #include "cmock_ble.h" #include "cmock_nrf_sdh_ble.h" -BLE_NUS_DEF(ble_nus); +static struct ble_nus ble_nus; + uint16_t test_case_conn_handle = 0x1000; bool evt_handler_called; struct ble_nus_client_context *last_link_ctx;