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

Use SPI Master within NUS Data Handler

Hi,

I can use the SPI master functionality within nrf_drv_spi.c/.h just fine (i.e. calls from main) until I connect to my nRF52840 and utilize NUS. If I try to issue a nrf_drv_spi_transfer() call from within my NUS data handler (i.e. when handing incoming data over NUS) to read 2 registers from a SPI connected slave (I am the master), I am not getting the expected SPI event handler with event NRF_DRV_SPI_EVENT_DONE when a SPI transfer completes. In the code below, I am calling bmi160_spiReadRegs() from within my NUS data handler. This function is blocking because m_xfer_done is never set to TRUE as a result of spi_event_handler() being called.

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
void spi_event_handler(nrf_drv_spi_evt_t const * p_event,
void * p_context)
{
// The only type passed to this handler is "NRF_DRV_SPI_EVENT_DONE"
m_xfer_done = true;
}
void spi_init()
{
ret_code_t err_code;
if(m_initialized) { return; } // Nothing to do.
nrf_drv_spi_config_t spi_config = NRF_DRV_SPI_DEFAULT_CONFIG;
spi_config.ss_pin = ACC_SPI_CSN; // Driver control.
spi_config.miso_pin = ACC_SPI_MISO;
spi_config.mosi_pin = ACC_SPI_MOSI;
spi_config.sck_pin = ACC_SPI_SCK;
spi_config.mode = NRF_DRV_SPI_MODE_0; // Prev BMI160 exp.
spi_config.frequency = NRF_DRV_SPI_FREQ_8M; // Max Nordic SPI Speed - chip max is 10M
spi_config.bit_order = NRF_DRV_SPI_BIT_ORDER_MSB_FIRST; // From prev egs.
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

If I issue the same SPI read on main using nrf_drv_spi_transfer(), the SPI event handler is called with event NRF_DRV_SPI_EVENT_DONE as expected. But, if I issue the nrf_drv_spi_transfer() from my NUS data handler, my SPI event handler is never called (at all).

I see other references to similar issues on DevZone. For these issues, NUS or SPI priority changes are suggested. I have tried this, but to no avail. 

Specifically, I have set NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY to 2 to match NUS, but to no avail. See below.

 

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// <o> NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY - Interrupt priority
// <0=> 0 (highest)
// <1=> 1
// <2=> 2
// <3=> 3
// <4=> 4
// <5=> 5
// <6=> 6 default
// <7=> 7
#ifndef NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY
#define NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY 2
#endif
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 

I have also tried changing the priority of NUS to match SPI. I set it to 6 as below.

Fullscreen
1
2
3
4
5
6
7
// <o> BLE_NUS_BLE_OBSERVER_PRIO
// <i> Priority with which BLE events are dispatched to the UART Service.
// Default 2
#ifndef BLE_NUS_BLE_OBSERVER_PRIO
#define BLE_NUS_BLE_OBSERVER_PRIO 6
#endif
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Neither of these addressed the issue. If I call nrf_drv_spi_transfer() within my NUS data handler, the SPI event handler is never called with event NRF_DRV_SPI_EVENT_DONE.

This confuses me as the NUS UART example calls UART reads/writes within the NUS data handler and the UART priority is the same as SPI (both 6).

Perhaps this is not priority related?

Help, clues, etc are appreciated.

Thanks,

Mark J