diff --git a/applications/firmware_loader/ble_mcumgr/src/main.c b/applications/firmware_loader/ble_mcumgr/src/main.c index 234ed3b7ff..481ac736d3 100644 --- a/applications/firmware_loader/ble_mcumgr/src/main.c +++ b/applications/firmware_loader/ble_mcumgr/src/main.c @@ -127,7 +127,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/doc/nrf-bm/libraries/bluetooth/services/ble_cgms.rst b/doc/nrf-bm/libraries/bluetooth/services/ble_cgms.rst index eafad4201b..136c66d7c6 100644 --- a/doc/nrf-bm/libraries/bluetooth/services/ble_cgms.rst +++ b/doc/nrf-bm/libraries/bluetooth/services/ble_cgms.rst @@ -25,7 +25,6 @@ Set the :kconfig:option:`CONFIG_BLE_CGMS` Kconfig option to enable the service. The CGMS service can be configured by using the following Kconfig options: -* :kconfig:option:`CONFIG_BLE_CGMS_BLE_OBSERVER_PRIO` - Sets the observer priority of the CGMS instance. * :kconfig:option:`CONFIG_BLE_CGMS_DB_RECORDS_MAX` - Sets the maximum number of records that can be stored in the database. Initialization 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 fc2151ae65..0c0e8858b2 100644 --- a/doc/nrf-bm/release_notes/release_notes_changelog.rst +++ b/doc/nrf-bm/release_notes/release_notes_changelog.rst @@ -32,8 +32,28 @@ S145 SoftDevice SoftDevice Handler ================== -* Added the :kconfig:option:`NRF_SDH_CLOCK_HFINT_CALIBRATION_INTERVAL` Kconfig option to control the HFINT calibration interval. -* Added the :kconfig:option:`NRF_SDH_CLOCK_HFCLK_LATENCY` Kconfig option to inform the SoftDevice about the ramp-up time of the high-frequency crystal oscillator. +* Added: + + * The :kconfig:option:`NRF_SDH_CLOCK_HFINT_CALIBRATION_INTERVAL` Kconfig option to control the HFINT calibration interval. + * The :kconfig:option:`NRF_SDH_CLOCK_HFCLK_LATENCY` Kconfig option to inform the SoftDevice about the ramp-up time of the high-frequency crystal oscillator. + * The :kconfig:option:`CONFIG_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_to_str` function to stringify a BLE event. + * The :c:func:`nrf_sdh_soc_evt_to_str` function to stringify a SoC event. + * The :c:func:`nrf_sdh_observer_ready` function to ready an observer for a SoftDevice state change. + +* Changed: + + * The return type of the :c:type:`nrf_sdh_state_evt_handler_t` event handler to ``int``. + +* Removed: + + * The ``nrf_sdh_ble_app_ram_start_get`` function, use ``DT_REG_ADDR(DT_CHOSEN(zephyr_sram))`` instead. + * The ``NRF_SDH_STATE_REQ_OBSERVER`` macro and relative data types. + Register a state event observer and return non-zero to :c:enum:`NRF_SDH_STATE_EVT_ENABLE_PREPARE` + or :c:enum:`NRF_SDH_STATE_EVT_DISABLE_PREPARE` to abort state changes instead. + * The ``nrf_sdh_request_continue`` function. + * The ``nrf_sdh_is_enabled`` function, use the SoftDevice native function :c:func:`sd_softdevice_is_enabled` instead. Boards ====== diff --git a/include/bm/bluetooth/ble_adv.h b/include/bm/bluetooth/ble_adv.h index 899102079b..54e3936535 100644 --- a/include/bm/bluetooth/ble_adv.h +++ b/include/bm/bluetooth/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/bm/bluetooth/ble_gq.h b/include/bm/bluetooth/ble_gq.h index cb1828c17c..2007a1a5a1 100644 --- a/include/bm/bluetooth/ble_gq.h +++ b/include/bm/bluetooth/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/bm/bluetooth/ble_qwr.h b/include/bm/bluetooth/ble_qwr.h index c63bc61f79..cfead9bbe0 100644 --- a/include/bm/bluetooth/ble_qwr.h +++ b/include/bm/bluetooth/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/bm/bluetooth/services/ble_bas.h b/include/bm/bluetooth/services/ble_bas.h index 790278f7cb..9ff23c86b9 100644 --- a/include/bm/bluetooth/services/ble_bas.h +++ b/include/bm/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/bm/bluetooth/services/ble_cgms.h b/include/bm/bluetooth/services/ble_cgms.h index 0853532cdf..a7b017bd1d 100644 --- a/include/bm/bluetooth/services/ble_cgms.h +++ b/include/bm/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/bm/bluetooth/services/ble_hids.h b/include/bm/bluetooth/services/ble_hids.h index 4dca7b634f..70a978fd0d 100644 --- a/include/bm/bluetooth/services/ble_hids.h +++ b/include/bm/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/bm/bluetooth/services/ble_hrs.h b/include/bm/bluetooth/services/ble_hrs.h index 060bff31d0..123bd2fa98 100644 --- a/include/bm/bluetooth/services/ble_hrs.h +++ b/include/bm/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/bm/bluetooth/services/ble_lbs.h b/include/bm/bluetooth/services/ble_lbs.h index 2318477151..4decb8b7bb 100644 --- a/include/bm/bluetooth/services/ble_lbs.h +++ b/include/bm/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/bm/bluetooth/services/ble_nus.h b/include/bm/bluetooth/services/ble_nus.h index 80e3348151..6d6b481927 100644 --- a/include/bm/bluetooth/services/ble_nus.h +++ b/include/bm/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/bm/softdevice_handler/nrf_sdh.h b/include/bm/softdevice_handler/nrf_sdh.h index 9a73809971..e33fb3646c 100644 --- a/include/bm/softdevice_handler/nrf_sdh.h +++ b/include/bm/softdevice_handler/nrf_sdh.h @@ -15,6 +15,8 @@ #define NRF_SDH_H__ #include +#include +#include #include #ifdef __cplusplus @@ -22,66 +24,55 @@ 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 +80,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 +94,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 +106,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. @@ -126,29 +124,37 @@ struct nrf_sdh_state_evt_observer { * @brief A context parameter to the event handler. */ void *context; + /** + * @brief The observer's state during the latest SoftDevice state transistion. + */ + bool is_busy; }; /** * @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. + * + * Note that state events may be sent from various contexts, depending on the context + * of the initiator of the SoftDevice 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 *); \ - const TYPE_SECTION_ITERABLE(struct nrf_sdh_state_evt_observer, _observer, \ - nrf_sdh_state_evt_observers, _prio) = { \ + PRIO_LEVEL_IS_VALID(_prio); \ + static int _handler(enum nrf_sdh_state_evt, void *); \ + TYPE_SECTION_ITERABLE(struct nrf_sdh_state_evt_observer, _observer, \ + nrf_sdh_state_evt_observers, PRIO_LEVEL_ORD(_prio)) = { \ .handler = _handler, \ .context = _ctx, \ - }; + } /** * @brief SoftDevice stack event handler. @@ -180,65 +186,63 @@ 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. + * Request to enable the SoftDevice. An observer may stop the SoftDevice state change + * by returning non-zero when receiving the @ref NRF_SDH_STATE_EVT_ENABLE_PREPARE event. + * If an observer does so, it must call @ref nrf_sdh_observer_ready() when it becomes ready. * - * @retval 0 On success. - * @retval -EALREADY The SoftDevice is already enabled. + * @retval 0 If the SoftDevice has been enabled. + * @retval -EALREADY If the SoftDevice is already enabled. + * @retval -EINPROGRESS If a state change has already been requested. + * @retval -EBUSY The request was sent, but one or more observer were busy. + * Once all observers have become ready, the SoftDevice will change state + * and the @ref NRF_SDH_STATE_EVT_ENABLED event is sent. */ 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. + * Request to disable the SoftDevice. An observer may stop the SoftDevice state change + * by returning non-zero when receiving the @ref NRF_SDH_STATE_EVT_DISABLE_PREPARE event. + * If an observer does so, it must call @ref nrf_sdh_observer_ready() when it becomes ready. * - * @retval 0 On success. - * @retval -EALREADY The SoftDevice is already disabled. + * @retval 0 If the SoftDevice has been disabled. + * @retval -EALREADY If the SoftDevice is already disabled. + * @retval -EINPROGRESS If a state change has already been requested. + * @retval -EBUSY The request was sent, but one or more observer were busy. + * Once all observers have become ready, the SoftDevice will change state + * and the @ref NRF_SDH_STATE_EVT_DISABLED event is sent. */ int nrf_sdh_disable_request(void); /** - * @brief Function for restarting the SoftDevice Enable/Disable process. + * @brief Mark an observer ready for a SoftDevice state change. * - * 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. + * This function will dispatch an event to all remaining observers that were busy, if any. + * If the caller was the last observer to become ready, this function will change + * the SoftDevice state. * - * @retval 0 On success. - * @retval -EINVAL No state change request was pending. - */ -int nrf_sdh_request_continue(void); - -/** - * @brief Retrieve the SoftDevice state. + * @param observer The observer to mark as ready. * - * @retval true If the SoftDevice is enabled. - * @retval false If the SoftDevice is disabled. + * @retval 0 The observer is marked as ready. + * @retval -EFAULT If @p observer is @c NULL. + * @retval -EPERM If called when no request to change the SoftDevice state was made. */ -bool nrf_sdh_is_enabled(void); +int nrf_sdh_observer_ready(struct nrf_sdh_state_evt_observer *observer); /** * @brief Stop processing SoftDevice events. diff --git a/include/bm/softdevice_handler/nrf_sdh_ble.h b/include/bm/softdevice_handler/nrf_sdh_ble.h index 119f7cdab3..34bf22c494 100644 --- a/include/bm/softdevice_handler/nrf_sdh_ble.h +++ b/include/bm/softdevice_handler/nrf_sdh_ble.h @@ -17,6 +17,7 @@ #include #include +#include #include #ifdef __cplusplus @@ -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_to_str(uint32_t evt); /** * @brief Get the assigned index for a connection handle. diff --git a/include/bm/softdevice_handler/nrf_sdh_soc.h b/include/bm/softdevice_handler/nrf_sdh_soc.h index 875b460a12..ebe9884a84 100644 --- a/include/bm/softdevice_handler/nrf_sdh_soc.h +++ b/include/bm/softdevice_handler/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_to_str(uint32_t evt); #ifdef __cplusplus } diff --git a/lib/bluetooth/ble_conn_params/att_mtu.c b/lib/bluetooth/ble_conn_params/att_mtu.c index be20348712..7aa93733c7 100644 --- a/lib/bluetooth/ble_conn_params/att_mtu.c +++ b/lib/bluetooth/ble_conn_params/att_mtu.c @@ -160,7 +160,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); uint32_t ble_conn_params_att_mtu_set(uint16_t conn_handle, uint16_t att_mtu) { diff --git a/lib/bluetooth/ble_conn_params/conn_param.c b/lib/bluetooth/ble_conn_params/conn_param.c index 2e614eefda..bbb1fd75bb 100644 --- a/lib/bluetooth/ble_conn_params/conn_param.c +++ b/lib/bluetooth/ble_conn_params/conn_param.c @@ -169,28 +169,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) { uint32_t nrf_err; if (evt != NRF_SDH_STATE_EVT_BLE_ENABLED) { - return; + return 0; } nrf_err = sd_ble_gap_ppcp_set(&ppcp); if (nrf_err) { LOG_ERR("Failed to set preferred conn params, nrf_error %#x", nrf_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); uint32_t ble_conn_params_override(uint16_t conn_handle, const ble_gap_conn_params_t *conn_params) { diff --git a/lib/bluetooth/ble_conn_params/data_length.c b/lib/bluetooth/ble_conn_params/data_length.c index f91e896176..16b216e629 100644 --- a/lib/bluetooth/ble_conn_params/data_length.c +++ b/lib/bluetooth/ble_conn_params/data_length.c @@ -186,7 +186,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); uint32_t ble_conn_params_data_length_set(uint16_t conn_handle, struct ble_conn_params_data_length dl) diff --git a/lib/bluetooth/ble_conn_params/phy_mode.c b/lib/bluetooth/ble_conn_params/phy_mode.c index 8a1e6c3b39..b60ece7b66 100644 --- a/lib/bluetooth/ble_conn_params/phy_mode.c +++ b/lib/bluetooth/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); uint32_t ble_conn_params_phy_radio_mode_set(uint16_t conn_handle, ble_gap_phys_t phy_pref) { diff --git a/lib/bluetooth/ble_conn_state/Kconfig b/lib/bluetooth/ble_conn_state/Kconfig index 80b949960f..ca2489ecec 100644 --- a/lib/bluetooth/ble_conn_state/Kconfig +++ b/lib/bluetooth/ble_conn_state/Kconfig @@ -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/bluetooth/ble_conn_state/ble_conn_state.c b/lib/bluetooth/ble_conn_state/ble_conn_state.c index 0f00376f6c..38bc6ca4bf 100644 --- a/lib/bluetooth/ble_conn_state/ble_conn_state.c +++ b/lib/bluetooth/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/bluetooth/ble_gq/Kconfig b/lib/bluetooth/ble_gq/Kconfig index 4584a12248..4f7d64a96d 100644 --- a/lib/bluetooth/ble_gq/Kconfig +++ b/lib/bluetooth/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/bluetooth/ble_qwr/Kconfig b/lib/bluetooth/ble_qwr/Kconfig index c65997e7a9..8c943ff30d 100644 --- a/lib/bluetooth/ble_qwr/Kconfig +++ b/lib/bluetooth/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/bluetooth/peer_manager/Kconfig b/lib/bluetooth/peer_manager/Kconfig index a068928d32..dd09f517fa 100644 --- a/lib/bluetooth/peer_manager/Kconfig +++ b/lib/bluetooth/peer_manager/Kconfig @@ -21,12 +21,6 @@ config PM_BM_ZMS_SECTOR_SIZE int "BM_ZMS sector size" default 1024 -config PM_BLE_OBSERVER_PRIO - int "BLE events priority" - default 1 - help - Priority with which BLE events are dispatched to the Peer Manager module. - config PM_MAX_REGISTRANTS int "Maximum number of event handlers that can be registered" default 3 diff --git a/lib/bluetooth/peer_manager/peer_manager.c b/lib/bluetooth/peer_manager/peer_manager.c index 66ff4af500..7d460c68fa 100644 --- a/lib/bluetooth/peer_manager/peer_manager.c +++ b/lib/bluetooth/peer_manager/peer_manager.c @@ -310,7 +310,7 @@ static void ble_evt_handler(const ble_evt_t *ble_evt, void *context) gcm_ble_evt_handler(ble_evt); } -NRF_SDH_BLE_OBSERVER(ble_evt_observer, ble_evt_handler, NULL, CONFIG_PM_BLE_OBSERVER_PRIO); +NRF_SDH_BLE_OBSERVER(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 2e7060856c..44b3d2d2bc 100644 --- a/samples/bluetooth/ble_cgms/src/main.c +++ b/samples/bluetooth/ble_cgms/src/main.c @@ -508,7 +508,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 61b578d934..8864a83124 100644 --- a/samples/bluetooth/ble_hids_keyboard/src/main.c +++ b/samples/bluetooth/ble_hids_keyboard/src/main.c @@ -243,7 +243,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 750b75bc54..6bfaa166cf 100644 --- a/samples/bluetooth/ble_hids_mouse/src/main.c +++ b/samples/bluetooth/ble_hids_mouse/src/main.c @@ -168,7 +168,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 31c705dbaf..8fd5320b2c 100644 --- a/samples/bluetooth/ble_hrs/src/main.c +++ b/samples/bluetooth/ble_hrs/src/main.c @@ -255,7 +255,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 b37bf79701..70fcb7c232 100644 --- a/samples/bluetooth/ble_lbs/src/main.c +++ b/samples/bluetooth/ble_lbs/src/main.c @@ -73,7 +73,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 1c7e36317c..f2007f9835 100644 --- a/samples/bluetooth/ble_nus/src/main.c +++ b/samples/bluetooth/ble_nus/src/main.c @@ -239,7 +239,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 c76d4d35ea..df433f7ae3 100644 --- a/samples/bluetooth/ble_pwr_profiling/src/main.c +++ b/samples/bluetooth/ble_pwr_profiling/src/main.c @@ -359,7 +359,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 a2be32e03a..3b7e385244 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/src/main.c b/samples/boot/mcuboot_recovery_entry/src/main.c index 3520fbf3a9..f2cd04f96f 100644 --- a/samples/boot/mcuboot_recovery_entry/src/main.c +++ b/samples/boot/mcuboot_recovery_entry/src/main.c @@ -120,7 +120,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/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 75c5421432..69bcaa3dfe 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); uint32_t ble_mcumgr_init(void) { diff --git a/subsys/softdevice_handler/CMakeLists.txt b/subsys/softdevice_handler/CMakeLists.txt index 9aefee3546..13d75e9f20 100644 --- a/subsys/softdevice_handler/CMakeLists.txt +++ b/subsys/softdevice_handler/CMakeLists.txt @@ -5,12 +5,15 @@ # zephyr_library() zephyr_linker_sources(SECTIONS sdh.ld) +zephyr_linker_sources(DATA_SECTIONS sdh_ram.ld) zephyr_library_sources( nrf_sdh.c nrf_sdh_soc.c irq_connect.c ) +zephyr_library_sources_ifdef(CONFIG_NRF_SDH_SOC_RAND_SEED rand_seed.c) + if(CONFIG_SOFTDEVICE_S115 OR CONFIG_SOFTDEVICE_S145) zephyr_library_sources(irq_forward.s) # Suppress the swap_helper.S file so that z_arm_svc can be defined manually diff --git a/subsys/softdevice_handler/Kconfig b/subsys/softdevice_handler/Kconfig index 429e0febaf..1c69080d4d 100644 --- a/subsys/softdevice_handler/Kconfig +++ b/subsys/softdevice_handler/Kconfig @@ -6,9 +6,6 @@ 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 @@ -46,6 +43,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 @@ -72,8 +71,12 @@ config NRF_SDH_CLOCK_HFCLK_LATENCY range 0 $(UINT16_MAX) default 1500 +endmenu + if NRF_SDH_BLE +menu "Default BLE configuration" + config NRF_SDH_BLE_CONN_TAG int "Connection tag" range 1 255 @@ -121,14 +124,25 @@ config NRF_SDH_BLE_VS_UUID_COUNT config NRF_SDH_BLE_SERVICE_CHANGED bool "Include the Service Changed characteristic in the Attribute Table" +endmenu + endif # NRF_SDH_BLE +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_to_str() and + nrf_sdh_soc_evt_to_str(). 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 e252d1ea14..94bbafa35b 100644 --- a/subsys/softdevice_handler/nrf_sdh.c +++ b/subsys/softdevice_handler/nrf_sdh.c @@ -19,22 +19,10 @@ 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. */ +static atomic_t sdh_is_suspended; /* Whether the SoftDevice event interrupts are disabled. */ +static atomic_t sdh_transition; /* Whether enable/disable process was started. */ -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) +static char *state_to_str(enum nrf_sdh_state_evt s) { switch (s) { case NRF_SDH_STATE_EVT_ENABLE_PREPARE: @@ -50,38 +38,49 @@ static char *state_tostr(enum nrf_sdh_state_evt s) }; } -static int sdh_state_req_observer_notify(enum nrf_sdh_state_req req) +/** + * @brief Notify a state change to state observers. + * + * Extern in nrf_sdh_ble.c + * + * @param state The state to be notified. + * @return true If any observers are busy. + * @return false If no observers are busy. + */ +bool 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); - } + bool busy; + bool all_ready; + bool busy_is_allowed; - 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; - } - } - - 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)); + LOG_DBG("State change: %s", state_to_str(state)); } else { LOG_DBG("State change: %#x", state); } + all_ready = true; + 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); + /* If it's a _PREPARE event, dispatch only to busy observers, and update + * their busy state in RAM. Otherwise dispatch unconditionally to all observers. + */ + if (busy_is_allowed && obs->is_busy) { + obs->is_busy = !!obs->handler(state, obs->context); + if (obs->is_busy) { + LOG_DBG("SoftDevice observer %p is busy", obs); + } + all_ready &= !obs->is_busy; + } else { + busy = obs->handler(state, obs->context); + (void) busy; + __ASSERT(!busy, "Returning non-zero from these events is ignored"); + } } + + return !all_ready; } __weak void softdevice_fault_handler(uint32_t id, uint32_t pc, uint32_t info) @@ -107,7 +106,7 @@ __weak void softdevice_fault_handler(uint32_t id, uint32_t pc, uint32_t info) } } -int nrf_sdh_enable_request(void) +static int nrf_sdh_enable(void) { int err; const nrf_clock_lf_cfg_t clock_lf_cfg = { @@ -119,115 +118,177 @@ int nrf_sdh_enable_request(void) .hfint_ctiv = CONFIG_NRF_SDH_CLOCK_HFINT_CALIBRATION_INTERVAL, }; - if (sdh_enabled) { - return -EALREADY; - } - - atomic_set(&sdh_transition, true); - - err = sdh_state_req_observer_notify(NRF_SDH_STATE_REQ_ENABLE); + err = sd_softdevice_enable(&clock_lf_cfg, softdevice_fault_handler); 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; + LOG_ERR("Failed to enable SoftDevice, nrf_error %#x", err); + return -EINVAL; } + atomic_set(&sdh_is_suspended, false); atomic_set(&sdh_transition, false); - /* Notify observers about starting SoftDevice enable process. */ - sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_ENABLE_PREPARE); + /* Enable event interrupt, the priority has already been set by the stack. */ + NVIC_EnableIRQ((IRQn_Type)SD_EVT_IRQn); + + (void)sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_ENABLED); - err = sd_softdevice_enable(&clock_lf_cfg, softdevice_fault_handler); + return 0; +} + +static int nrf_sdh_disable(void) +{ + int err; + + err = sd_softdevice_disable(); if (err) { - LOG_ERR("Failed to enable SoftDevice, nrf_error %#x", err); + LOG_ERR("Failed to disable SoftDevice, nrf_error %#x", err); return -EINVAL; } - atomic_set(&sdh_enabled, true); - atomic_set(&sdh_suspended, false); + atomic_set(&sdh_transition, false); - /* Enable event interrupt, the priority has already been set by the stack. */ - NVIC_EnableIRQ((IRQn_Type)SD_EVT_IRQn); + NVIC_DisableIRQ((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_DISABLED); return 0; } -int nrf_sdh_disable_request(void) +int nrf_sdh_enable_request(void) { - int err; + bool busy; + uint8_t enabled; - if (!sdh_enabled) { + (void)sd_softdevice_is_enabled(&enabled); + if (enabled) { return -EALREADY; } + if (sdh_transition) { + return -EINPROGRESS; + } + atomic_set(&sdh_transition, true); - /* Notify observers about SoftDevice disable request. */ - err = sdh_state_req_observer_notify(NRF_SDH_STATE_REQ_DISABLE); - if (err) { - /** TODO: should this be Success instead? */ + /* Assume all observers to be busy */ + TYPE_SECTION_FOREACH(struct nrf_sdh_state_evt_observer, + nrf_sdh_state_evt_observers, obs) { + obs->is_busy = true; + } + + busy = sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_ENABLE_PREPARE); + if (busy) { /* 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); + return nrf_sdh_enable(); +} - /* Notify observers about starting SoftDevice disable process. */ - sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_DISABLE_PREPARE); +int nrf_sdh_disable_request(void) +{ + bool busy; + uint8_t enabled; - err = sd_softdevice_disable(); - if (err) { - LOG_ERR("Failed to disable SoftDevice, nrf_error %#x", err); - return -EINVAL; + (void)sd_softdevice_is_enabled(&enabled); + if (!enabled) { + return -EALREADY; } - atomic_set(&sdh_enabled, false); + if (sdh_transition) { + return -EINPROGRESS; + } - NVIC_DisableIRQ((IRQn_Type)SD_EVT_IRQn); + atomic_set(&sdh_transition, true); - /* Notify observers about a finished SoftDevice enable process. */ - sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_DISABLED); + /* Assume all observers to be busy */ + TYPE_SECTION_FOREACH(struct nrf_sdh_state_evt_observer, + nrf_sdh_state_evt_observers, obs) { + obs->is_busy = true; + } - return 0; + busy = sdh_state_evt_observer_notify(NRF_SDH_STATE_EVT_DISABLE_PREPARE); + if (busy) { + /* Leave sdh_transition to 1, so process can be continued */ + return -EBUSY; + } + + return nrf_sdh_disable(); } -int nrf_sdh_request_continue(void) +int nrf_sdh_observer_ready(struct nrf_sdh_state_evt_observer *obs) { + int err; + bool busy; + uint8_t enabled; + + if (!obs) { + return -EFAULT; + } if (!sdh_transition) { - return -EINVAL; + return -EPERM; + } + if (!obs->is_busy) { + LOG_WRN("Observer %p is not busy", obs); + return 0; + } + + obs->is_busy = false; + + (void)sd_softdevice_is_enabled(&enabled); + + busy = sdh_state_evt_observer_notify(enabled ? NRF_SDH_STATE_EVT_DISABLE_PREPARE + : NRF_SDH_STATE_EVT_ENABLE_PREPARE); + + /* Another observer needs to ready itself */ + if (busy) { + return 0; } - if (sdh_enabled) { - return nrf_sdh_disable_request(); + if (enabled) { + err = nrf_sdh_disable(); } else { - return nrf_sdh_enable_request(); + err = nrf_sdh_enable(); } -} -bool nrf_sdh_is_enabled(void) -{ - return sdh_enabled; + __ASSERT(!err, "Failed to change SoftDevice state"); + (void) err; + + return 0; } void nrf_sdh_suspend(void) { - if (!sdh_enabled || sdh_suspended) { + uint8_t sd_is_enabled; + + (void)sd_softdevice_is_enabled(&sd_is_enabled); + + 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; } @@ -235,12 +296,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 cb097cffd2..9b5c029270 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_to_str(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; } @@ -303,11 +349,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_to_str(ble_evt->header.evt_id)); if (ble_evt->header.evt_id == BLE_GAP_EVT_CONNECTED) { idx_assign(ble_evt->evt.gap_evt.conn_handle); @@ -326,8 +368,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 093bb8b773..ba35c54aee 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_to_str(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 nrf_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) { - nrf_err = sd_rand_seed_set(seed); - memset(seed, 0, sizeof(seed)); - if (nrf_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", nrf_err); -} - static void soc_evt_poll(void *context) { uint32_t nrf_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_to_str(evt_id)); /* Forward the event to SoC observers. */ TYPE_SECTION_FOREACH( @@ -93,8 +72,8 @@ static void soc_evt_poll(void *context) } __ASSERT(nrf_err == NRF_ERROR_NOT_FOUND, - "Failed to receive SoftDevice event, nrf_error %#x", nrf_err); + "Failed to receive SoftDevice SoC event, nrf_error %#x", nrf_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..52a78b7f31 --- /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..53a5247c83 100644 --- a/subsys/softdevice_handler/sdh.ld +++ b/subsys/softdevice_handler/sdh.ld @@ -1,5 +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) ITERABLE_SECTION_ROM(nrf_sdh_ble_evt_observers, 4) diff --git a/subsys/softdevice_handler/sdh_ram.ld b/subsys/softdevice_handler/sdh_ram.ld new file mode 100644 index 0000000000..70daac4c20 --- /dev/null +++ b/subsys/softdevice_handler/sdh_ram.ld @@ -0,0 +1 @@ +ITERABLE_SECTION_RAM(nrf_sdh_state_evt_observers, 4) diff --git a/subsys/storage/bm_storage/sd/bm_storage_sd.c b/subsys/storage/bm_storage/sd/bm_storage_sd.c index 67720ab81d..a5251bd031 100644 --- a/subsys/storage/bm_storage/sd/bm_storage_sd.c +++ b/subsys/storage/bm_storage/sd/bm_storage_sd.c @@ -4,17 +4,17 @@ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause */ -#include -#include #include -#include -#include -#include #include +#include +#include +#include #include #include #include #include +#include +#include /* 128-bit word line. This is the optimal size to fully utilize RRAM 128-bit word line with ECC * (error correction code) and minimize ECC updates overhead, due to these updates happening @@ -65,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) { @@ -227,7 +225,7 @@ int bm_storage_backend_init(struct bm_storage *storage) return -EBUSY; } - state.sd_enabled = nrf_sdh_is_enabled(); + sd_softdevice_is_enabled((uint8_t *)&state.sd_enabled); state.type = BM_STORAGE_SD_STATE_IDLE; @@ -340,26 +338,32 @@ static void on_soc_evt(uint32_t evt, void *ctx) if (!state.paused) { queue_process(); } else { - nrf_sdh_request_continue(); + nrf_sdh_observer_ready(&sdh_state_evt); } } -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(); - } -} - -static bool on_state_req_change(enum nrf_sdh_state_req req, void *ctx) -{ - state.paused = true; + return 0; - 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/tests/subsys/bluetooth/services/ble_nus/src/unity_test.c b/tests/subsys/bluetooth/services/ble_nus/src/unity_test.c index 3a702dfc7d..a11f0b8dae 100644 --- a/tests/subsys/bluetooth/services/ble_nus/src/unity_test.c +++ b/tests/subsys/bluetooth/services/ble_nus/src/unity_test.c @@ -16,7 +16,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;