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

SPI handler callbacks not invoked with NRF_SDH_DISPATCH_MODEL_INTERRUPT

Hi, We are currently migrating our codebase from SDK 13 to SDK 14 for NRF52832 based board. One major difference we see is that SPI transfer completion callbacks are not invoked when transaction is started from within BLE context; based on NRF_SDH_DISPATCH_MODEL config's value.

The scenario is as follows : We get some data over a custom BLE service which we write to external flash (connected to SPI0). The read/writes to this flash work ok when done during initialisation. But when SPI writes are invoked from BLE service' callback, the SPI handler indicating completion of transfer is never invoked (when using NRF_SDH_DISPATCH_MODEL_INTERRUPT, which is what majority of the examples use).

Using NRF_SDH_DISPATCH_MODEL_APPSH instead made the transfers work. We are using scheduler since SDK13 but did not face this issue there.

Can anyone shed more light on why the interrupt context is not working here? Does enabling scheduler mandates using APPSH model? If so, there is no protection added to nrf_sdh.c to guard against it (e.g. generate error if scheduler is enabled and interrupt dispatch model is used)

I couldn't find documentation which gives more details about interactions of these config options. Any help/pointers are welcome. Thanks.

Update 1 :

Thanks Martin, emdi for your pointers.

Here is the initialisation code and priority values used :

    /* Priority values used */
    #define APP_BLE_OBSERVER_PRIO                           1
    #define APP_SOC_OBSERVER_PRIO                           1
    #define NRF_SDH_BLE_OBSERVER_PRIO_LEVELS                3
    #define NRF_SDH_SOC_OBSERVER_PRIO_LEVELS                2
    #define SPI_DEFAULT_CONFIG_IRQ_PRIORITY                 7

    /* SoftDevice init code */
    err_code = nrf_sdh_enable_request();
    APP_ERROR_CHECK(err_code);

    // Fetch the start address of the application RAM.
    uint32_t ram_start = 0;
    err_code = nrf_sdh_ble_default_cfg_set(CONN_CFG_TAG, &ram_start);
    APP_ERROR_CHECK(err_code);

    // Enable BLE stack.
    err_code = nrf_sdh_ble_enable(&ram_start);
    APP_ERROR_CHECK(err_code);

    // Subscribe for BLE events.
    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_dispatch, NULL);
    APP_ERROR_CHECK(err_code);

    // Register with the SoftDevice handler module for BLE events.
    NRF_SDH_SOC_OBSERVER(m_sys_observer, APP_SOC_OBSERVER_PRIO, sys_evt_dispatch, NULL);
    APP_ERROR_CHECK(err_code);

The above does not work (SPI handler not called) as mentioned in the question.

Modifying the values as the following, made the SPI callbacks work, but the custom BLE service is now getting starved (my guess).

    #define APP_BLE_OBSERVER_PRIO                           3
    #define APP_SOC_OBSERVER_PRIO                           3
    #define NRF_SDH_BLE_OBSERVER_PRIO_LEVELS                4
    #define NRF_SDH_SOC_OBSERVER_PRIO_LEVELS                4
    #define SPI_DEFAULT_CONFIG_IRQ_PRIORITY                 2

I will dig further, but any help to arrive at right configuration is most welcome. Thanks a lot,

  • Amit
  • Hi,

    My bet is a problem with interrupt priorities and nesting. The fact that it works in the main thread context (when you initialize it all or use a scheduler) points to that. I assume that you configure the new Softdevice Scheduler like documented here? What priority do you use for your service observer and what priority do you use for the SPI? Can you make sure that the SPI has higher interrupt priority than the Softdevice Scheduler.

  • I believe Martin is quite right, you should get your priorities straight ;)

    To shed some light on the SoftDevice handler dispatch model:

    • NRF_SDH_DISPATCH_MODEL_INTERRUPT: SoftDevice events are executed in the interrupt context, whose priority is determined by SD_EVT_IRQn in nrf_soc.h.
    • NRF_SDH_DISPATCH_MODEL_APPSH: SoftDevice events are scheduled and executed in main().

    The problem likely showed up in SDK 14 since the priority of SD_EVT_IRQn has changed from 7 to 6, due to the new SoftDevice. This change was reverted in SDK 14.1 though, as it was unintended.

Related