This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Best practice for when to enable SoftDevice (sd_* vs. NVIC_*)

The issue is that if a peripheral needs to enable interrupts (or anything else partly protected by the SoftDevice) and is configured before enabling the SoftDevice, the NVIC_* functions must be used in the initialization and the sd_* functions for disabling/de-initialization. This can quickly lead to strange code and unforeseen bugs. The same is true for using the sd_mutex* etc.

So what is considered "best practice" for this issue when using the SoftDevice?

My initial thought would be to enable the SoftDevice immediately after initializing clocks and anything else that the SoftDevice might be depend on, and always use sd_* everywhere. And wait to enable the device manager, advertising, etc. until it makes sense to do so.

This does make debugging a bit more problematic. But are there any other drawbacks that I am missing? Or does anyone have a better approach?

A define to indicate if a SoftDevice is used could be added to make drivers etc. more general, but for BLE-centered applications this define would need to be checked quite a lot of places.

  • @ned_zeppelin: From my point of view:

    • If you don't have to use the interrupt/peripheral that is partly protected by the softdevice before the softdevice is enabled, you should enable the softdevice first and enable the interrupt using sd_* function.

    • If you need to use the interrupt before the softdevice is enabled, you can use NVIC_* function. However, when you enabled the softdevice, you would need to reconfigure the interrupt using sd_* provided functions. This mainly is to avoid your interrupt priority violated with the priority levels reserved for the softdevice.

  • As a request, It would be nice if the SDK followed some guideline regarding this. If the drivers had a consistent use of a define so that they could be used either with the SoftDevice enabled from the start (i.e. using sd_* functions everywhere) or SoftDevice not enabled (using NVIC_* etc. everywhere), it would save the users some error-prone editing of the SDK.

    My current issue is to have a safe debug printout using the sd_mutex* functions, which requires editing of most of the drivers.

  • @ned_zeppelin: Sorry for the late response. I was checking with our SDK team. Currently we only use the preprocessor flag SOFTDEVICE_PRESENT to detect if the driver should be used the sd_* api or not.

    And it assumes that when you have the softdevice in flash you should enable the softdevice before using the driver. We are working on adding the checking that the softdevice is present but not enabled.

    Regarding your issue with sd_mutex_ could you let me know some more information about that ? I guess you want to look a variable before you printing it out ? I'm not sure there is an equivalent call for mutex when softdevice is disabled.

  • Hi, but most of the drivers do not conform to the SOFTDEVICE_PRESENT define. I2C, app_gpiote, etc. use NVIC_* directly and hence cannot be used without modifcation if the SoftDevice is enabled 'immediately' in main.

    Furthermore, the SDK-provided mutex cannot be initialized or used before the SoftDevice is enabled, which is another good reason to enable the SoftDevice before anything else.

    So that's what I ended up doing; modifying everything to use sd_* and enabling the SoftDevice before anything else.

  • @ned_zeppelin: I guess you were talking about the calls to set the interrupt and priority, such as:

     NVIC_ClearPendingIRQ(UART0_IRQn);
     NVIC_SetPriority(UART0_IRQn, irq_priority);
     NVIC_EnableIRQ(UART0_IRQn);
    

    I personally haven't seen issue when using them with softdevice enabled as long as the priority is set correctly (App high or app low). But you are right, as mentioned in the Softdevice spec: "the application program must comply with the restriction and use the NVIC API for configuration when the SoftDevice is enabled".

    I will report this as a bug internally.

Related