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

SPIS not working with S140 softdevice on nRF52840

Hello,

we are developing a firmware for the nRF52840 which requires the use of Bluetooth and the SPIS (SPI Slave) functionality.

We are using S140 & SDK 16.

We encounter the following problem:

During init, we configure a 2 byte TX buffer for SPIS.

After init, the master initiates a 2 byte transaction.


With a logic analyzer we can observe that the nRF is correctly clocking out the 2 byte long buffer on MISO. 

But for every successive transaction, the nRF is clocking out the default byte (as defined in register DEF).

The SPIS event handler is an empty function, so it should not reconfigure anything.

We traced the problem to the function  nrf_pwr_mgmt_run(void)

void nrf_pwr_mgmt_run(void)
{
    PWR_MGMT_FPU_SLEEP_PREPARE();
    PWR_MGMT_SLEEP_LOCK_ACQUIRE();
    PWR_MGMT_CPU_USAGE_MONITOR_SECTION_ENTER();
    PWR_MGMT_DEBUG_PIN_SET();

 

    // Wait for an event.
#ifdef  SOFTDEVICE_PRESENT
    if (nrf_sdh_is_enabled())
    {
       ret_code_t ret_code = sd_app_evt_wait();
       ASSERT((ret_code == NRF_SUCCESS) || (ret_code == NRF_ERROR_SOFTDEVICE_NOT_ENABLED));
       UNUSED_VARIABLE(ret_code);
    }
    else
#endif // SOFTDEVICE_PRESENT
    {
        // Wait for an event.
        __WFE();
        // Clear the internal event register.
        __SEV();
        __WFE();
    }

 

    PWR_MGMT_DEBUG_PIN_CLEAR();
    PWR_MGMT_CPU_USAGE_MONITOR_SECTION_EXIT();
    PWR_MGMT_SLEEP_LOCK_RELEASE();
}

The SPIS works for successive transactions when we either

1. Don't call the nrf_power_mgmt_run(void) function
2. Comment out the lines '
PWR_MGMT_FPU_SLEEP_PREPARE();' and 'ret_code_t ret_code = sd_app_evt_wait();'

We therefore suspect that the call to sd_app_evt_wait() is the culprit.
Additionally, if we replace the call to nrf_power_mgmt_run(void) to a call to __WFE() the SPIS is also still working.

Is the SPIS not compatible with the BLE stack? Are we missing something else?
We would greatly appreciate any input on this problem.

  • We updated the handler as follows:

    static void spi_evt_handler( nrfx_spis_evt_t const* p_event, void* p_contex )
    {
      NRF_LOG_DEBUG( "Event: %d", p_event->evt_type);
      if( p_event->evt_type == NRFX_SPIS_BUFFERS_SET_DONE ) 
      {
        NRF_LOG_DEBUG( "Buffer set");
      }
      else if( ( p_event->evt_type == NRFX_SPIS_XFER_DONE ) )
      {
        NRF_LOG_DEBUG( "Transmission Done: %d, %d", p_event->rx_amount, p_event->tx_amount);
        APP_ERROR_CHECK( nrfx_spis_buffers_set( spi_instance, spi_defaultTxBuffer, 2, NULL, 0 ) );
      }
    }

    The result is the same.

    We also added some logging to the event handler.

    <debug> app: Event: 0
    <debug> app: Buffer set
    
    
    // snip
    
    <debug> app: Event: 1
    <debug> app: Transmission Done: 2, 2

    We only get one event of type NRFX_SPIS_BUFFERS_SET_DONE and one of type NRFX_SPIS_XFER_DONE. Nothing for the second transmission.

  • Found the problem:

    static nrfx_spis_t spi_instance = NRFX_SPIS_INSTANCE( 0 ); // <- declare here
    
    static void*   spi_defaultContext;
    static uint8_t spi_defaultTxBuffer[2];
    static uint8_t spi_defaultRxBuffer[2];
    
    void spi_init( void )
    {
      // snip
    
      nrfx_spis_buffers_set( spi_instance, spi_defaultTxBuffer, 2, spi_defaultRxBuffer.controlSequence, 2 );
    }

    We initialized p_instance in spi_init() and pointed the static pointer spi_instance to it.

    --> pointer to a stack location that gets overwritten.

    Thank you very much for the help!

Related