Skip to content

Conversation

lemrey
Copy link
Contributor

@lemrey lemrey commented Sep 23, 2025

  • Introduce observer priority levels, e.g. HIGHEST, HIGH, USER, USER_LOW, LOWEST
  • Remove NRF_SDH_BLE (no longer configurable)
  • Remove nrf_sdh_app_ram_start_get(), unused and not useful
  • Remove nrf_sdh_is_enabled() in favor of native SoftDevice function
  • Merge request observers with state observers
  • Remove nrf_sdh_request_continue()
  • Improve functions for stringifying events and export them
  • Split random seed request handling to a dedicated file
  • Put some Kconfigs behind menus

@lemrey lemrey requested review from a team as code owners September 23, 2025 12:38
@lemrey lemrey requested a review from a team September 23, 2025 12:39
@github-actions github-actions bot added the changelog-entry-required Update changelog before merge. Remove label if entry is not needed or already added. label Sep 23, 2025
@github-actions
Copy link

You can find the documentation preview for this PR here.

@lemrey lemrey force-pushed the sdh branch 4 times, most recently from b6616a3 to 9cf07f8 Compare September 24, 2025 07:06
@lemrey lemrey requested a review from a team as a code owner September 24, 2025 07:06
@lemrey lemrey force-pushed the sdh branch 3 times, most recently from 5fd1e4e to 749680f Compare September 24, 2025 09:53
endmenu

config NRF_SDH_SOC_RAND_SEED
bool "Automatically seed SoftDevice random seeds requests"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
bool "Automatically seed SoftDevice random seeds requests"
bool "Automatically respond to SoftDevice random seed requests"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, reworded

bool "Automatically seed SoftDevice random seeds requests"
depends on NRF_SECURITY
depends on MBEDTLS_PSA_CRYPTO_C
depends on PSA_WANT_GENERATE_RANDOM
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize now that PSA_WANT_GENERATE_RANDOM is not required after we changed from using psa_generate_random() to using cracen_get_trng(). (PRNG to TRNG.)
So the PSA_WANT_GENERATE_RANDOM dependency should be removed from here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, removed it

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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit

Suggested change
nrf_sdh_soc_evt_tostr(). Disable to save non-volatile memory.
nrf_sdh_soc_evt_tostr(). Disable to save non-volatile memory.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


status = cracen_get_trng(seed, sizeof(seed));
if (status != PSA_SUCCESS) {
LOG_ERR("Failed to generate true random number, psa_status %#x", status);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PSA error values uses 0 for success and negative integers for errors. Similar to errno.
I think format %d will be more readable.

Suggested change
LOG_ERR("Failed to generate true random number, psa_status %#x", status);
LOG_ERR("Failed to generate true random number, psa_status %d", status);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, I think I checked and saw they were hex values but I checked again and they are not. So I am reverting this to %d as it was before.

/* Discard seed immediately */
memset(seed, 0, sizeof(seed));

if (nrf_err) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could be more explicit when checking the error here.

Suggested change
if (nrf_err) {
if (nrf_err != NRF_SUCCESS) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, just for this specific case since we have PSA errors as well, better be explicit I guess.

* 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 returnin non-zero when receiving
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* An observer may halt the SoftDevice state change by returnin non-zero when receiving
* An observer may halt the SoftDevice state change by returning non-zero when receiving

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected

state.paused = true;

return (state.type == BM_STORAGE_SD_STATE_IDLE);
case NRF_SDH_STATE_EVT_BLE_ENABLED:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it can make sense to explicitly list all events from enum nrf_sdh_state_evt here. Though, having a case for NRF_SDH_STATE_EVT_BLE_ENABLED that does the same as default looks a bit strange and redundant.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll leave this as-is if it's alright

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok with me 👍

Comment on lines 45 to 51
if (IS_ENABLED(CONFIG_NRF_SDH_STR_TABLES)) {
LOG_INF("State change request: %s", req_tostr(req));
LOG_DBG("State change: %s", state_tostr(state));
} else {
LOG_INF("State change request: %#x", req);
LOG_DBG("State change: %#x", state);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we give this and the state_tostr() function the same treatment as the nrf_sdh_ble_evt_tostr() and nrf_sdh_soc_evt_tostr()? Or are you happy with how it looks currently?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure we need to export this one, if needed we can take it later.
Here we are not stringifying the events, just printing "enabled" / "disabled".

LOG_DBG("Notify observer %p => ready", obs);
} else {
TYPE_SECTION_FOREACH(struct nrf_sdh_state_evt_observer, nrf_sdh_state_evt_observers, obs) {
busy = obs->handler(state, obs->context);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The state event observers are also called from nrf_sdh_ble_enable().

Should we add (void) in front here: https://github.com/lemrey/sdk-nrf-bm/blob/749680f702c3ec718f30aef0795d283555d1fa00/subsys/softdevice_handler/nrf_sdh_ble.c#L252v
to show that it returns a value but we choose to ignore it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I should have fixed this by calling to a common function now.

Comment on lines 52 to 65
busy = obs->handler(state, obs->context);
if (busy) {
/* Do not let SoftDevice change state now */
LOG_DBG("Notify observer %p => busy", obs);
return -EBUSY;
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not seem right.

If returning 1 from a state event observer as a response to NRF_SDH_STATE_EVT_ENABLED or NRF_SDH_STATE_EVT_DISABLED, busy would be set to 1 here and we return -EBUSY. If there is more than one registered state event observer, this could led to one or more state event observers not being called, because we return early.

Or do we depend on the user to ensure that 0 is always returned when handling NRF_SDH_STATE_EVT_ENABLED or NRF_SDH_STATE_EVT_DISABLED state events?

I'm able to observe this if adding a second state event observer in the hello_softdevice sample, then log from both and returning 1 from both. This does not make sense for NRF_SDH_STATE_EVT_ENABLED and NRF_SDH_STATE_EVT_DISABLED.

Another thing that we should maybe document or do something about is the fact that the state event observers can be invoked several times with the same event if one or more modules would return busy and later invoke nrf_sdh_request_continue(), which would resend the event to all observers that have already returned not busy.

Consider three observers, where the first and third in the observer list would return zero while the second one in the observer list would return busy and later call nrf_sdh_request_continue(). How would this look for each of the three?

Wrote this and saw later that you are thinking of removing the nrf_sdh_request_continue function.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, let me adjust this and add some asserts.


/* Helper macros to check for equality */

#define _NRF_SDH_OBSERVER_PRIO_HIGHEST_HIGHEST 1
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

don't use underscores for first character

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, will rename

* If :option:`CONFIG_NRF_SDH_STR_TABLES` is enabled, returns the event name.
* Otherwise, returns the supplied integer as a string.
*
* @param evt A NRF_SOC_SVCS enumeration value.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ before symbols links to it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nordicjm Can you please provide some context on this suggestion? Thanks.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks

};

if (sdh_enabled) {
(void) sd_softdevice_is_enabled(&sd_is_enabled);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(void) sd_softdevice_is_enabled(&sd_is_enabled);
(void)sd_softdevice_is_enabled(&sd_is_enabled);

fix in whole PR

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK

@lemrey lemrey force-pushed the sdh branch 2 times, most recently from 88c1e77 to 5032ba2 Compare October 3, 2025 10:50
lemrey added 13 commits October 3, 2025 14:48
Add a placeholder entry for sdh to be able to reference it
in the changelog.

Signed-off-by: Emanuele Di Santo <[email protected]>
This change aims to simplify the configuration options.
This is currently a core component, and can't really be optional.
If it were to be turned off, no BLE library would work.

Signed-off-by: Emanuele Di Santo <[email protected]>
It is more correct to use an SoC observer to do this, rather than doing
it directly in nrf_sdh_soc (the stack observer).  Make the feature
optional, and leave it enabled by default.

Signed-off-by: Emanuele Di Santo <[email protected]>
Introduce an allowed set of priorities for observers, with validity checks.
These are: HIGHEST, HIGH, USER, USER_LOW, LOWEST.

These could be extended ala SYS_INIT to include a priority within a level,
but it seemed a bit overkill for now.

Each library or piece of code in the SDK shall have an hardcoded priority,
because just changing the priority of one component would break the others.
In general, a component's observer must have a lower priority than the
observers in its dependencies.

Signed-off-by: Emanuele Di Santo <[email protected]>
Add GATTS and GATTC event strings to the table.
Renamed gap_evt_tostr() to ble_evt_tostr() to reflect that it now
can print all BLE events.

Signed-off-by: Emanuele Di Santo <[email protected]>
Add a Kconfig menu for clock configuration, to make the menu nicer.

Signed-off-by: Emanuele Di Santo <[email protected]>
Add a Kconfig menu for BLE configuration, to make the menu nicer.

Signed-off-by: Emanuele Di Santo <[email protected]>
Rework the functions in nrf_sdh_ble and nrf_sdh_soc that mapped BLE and
SOC events to their stringified version to make them public and align
their names. Instead of printing "unknown" if the event is not known,
default to printing its numerical value in hexadecimal.

That is also the default behavior if CONFIG_NRF_SDH_STR_TABLES is unset,
and the table is not compiled. This is better than toggling the
availability of the whole function, because we avoid conditional
compilation around it.

Signed-off-by: Emanuele Di Santo <[email protected]>
Update the assert message at the end of the polling loops to print
which kind of event we failed to pull, e.g. SoC or BLE.

Signed-off-by: Emanuele Di Santo <[email protected]>
There was a distinction between observers that could stop the SoftDevice
state changes, and those that didn't. The former were called
"request observers" and the latter "state observers".

Since both observers are interested in the SoftDevice state,
this commit merges the two, keeping only "state observers",
for the purpose of simplifying things a bit.

Now, state observers can return non-zero to these events:
- NRF_SDH_STATE_EVT_ENABLE_PREPARE and
- NRF_SDH_STATE_EVT_DISABLE_PREPARE
to halt the state change.

The return value from the observer is ignored for other events.

Signed-off-by: Emanuele Di Santo <[email protected]>
These can return -EBUSY, which was missing.

Signed-off-by: Emanuele Di Santo <[email protected]>
This API is not useful in NCS BM.

Signed-off-by: Emanuele Di Santo <[email protected]>
This function shifts the responsibility of changing the state of the
SoftDevice to the observer that halted its state change. This means
that potentially all observers that halt the state change not only
become responsible of the process (which may not be ideal) but also
have to maintain some state and logic to restart that process.

Instead, let the component who requested the state change in the first
place retry the operation.

Signed-off-by: Emanuele Di Santo <[email protected]>
lemrey added 4 commits October 3, 2025 14:54
Use the native SoftDevice function sd_softdevice_is_enabled() instead.

Signed-off-by: Emanuele Di Santo <[email protected]>
Only check if the SoftDevice handler is suspended,
not if the SoftDevice is enabled.

Signed-off-by: Emanuele Di Santo <[email protected]>
Rename an internal variable.

Signed-off-by: Emanuele Di Santo <[email protected]>
Remove these, and force users to put a semicolon themselves.

Signed-off-by: Emanuele Di Santo <[email protected]>
@lemrey lemrey requested a review from a team as a code owner October 3, 2025 12:54
@github-actions github-actions bot added the doc-required PR must not be merged without tech writer approval. label Oct 3, 2025
@lemrey
Copy link
Contributor Author

lemrey commented Oct 3, 2025

Added changlog entries

SoftDevice handler
##################

The SoftDevice handler is a library that handles SoftDevice initialization tasks, and pulls and dispatches the SoftDevice events to registered components.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be good with more skin on the bone, though I guess that can be added later as well.

No changes since the latest nRF Connect SDK Bare Metal release.
* Removed:

* The ``NRF_SDH_BLE`` Kconfig option.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be like this:

Suggested change
* The ``NRF_SDH_BLE`` Kconfig option.
* The ``CONFIG_NRF_SDH_BLE`` Kconfig option.


* Added:

* The :option:`NRF_SDH_SOC_RAND_SEED` Kconfig option to control whether to automatically respond to SoftDevice random seed requests.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* The :option:`NRF_SDH_SOC_RAND_SEED` Kconfig option to control whether to automatically respond to SoftDevice random seed requests.
* The :kconfig:option:`CONFIG_NRF_SDH_SOC_RAND_SEED` Kconfig option to control whether to automatically respond to SoftDevice random seed requests.

* @{
*/


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extra newline.

* 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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* Five priority levels are defined, highest, high, user, user low, lowest.
* Five priority levels are defined: highest, high, user, user low, and lowest.

LOG_MODULE_DECLARE(nrf_sdh, CONFIG_NRF_SDH_LOG_LEVEL);

const char *gap_evt_tostr(int evt)
const char *ble_evt_tostr(int evt)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const char *ble_evt_tostr(int evt)
const char *ble_evt_to_str(int evt)

Comment on lines 27 to 30
case BLE_GAP_EVT_CONNECTED:
return "BLE_GAP_EVT_CONNECTED";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think I prefer the current implementation. Otherwise we start devolving into too much macro magic.

@eivindj-nordic eivindj-nordic added this to the v1.0.0 milestone Oct 13, 2025
@eivindj-nordic
Copy link
Contributor

@lemrey Please rebase :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog-entry-required Update changelog before merge. Remove label if entry is not needed or already added. doc-required PR must not be merged without tech writer approval.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants