NVM process on SPI bus seems to be interfered with during BLE_GATTS_EVT_WRITE event

During an execution of a  winbond w25q64jv command (any command) during a BLE_GATTS_EVT_WRITE event the SPI bus goes inactive after the command is sent:

There is apparently no issue if I do any NVM operation outside a BLE_GATTS_EVT_WRITE event. 

Parents
  • I added a call to the NVM function (Test_write_and_read_of_NVM();) that is known to work was added here:

    static void on_Command_write(ble_Status_cus_t *stat_cus, ble_Cmnd_cus_t *cmnd_cus, ble_cus_data_t *p_cus, ble_evt_t const * p_ble_evt)
    {
        ble_gatts_evt_write_t const *p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
        uint8_t SOBRSafe_comnd = 0;
        uint32_t err_code;
        uint8_t SOBRSafe_err = SOBRSAFE_NO_ERROR;
        uint8_t rcvd_payload[PING_DATA_LENGTH]; 
        uint16_t rcvd_data_lngth = p_evt_write->len;
        timestamp_s curr_time;
        app_source_data *pull_strt_time;
        uint16_t ii = 0;
        Test_write_and_read_of_NVM();
        // Command Value Characteristic Written to.
        if (p_evt_write->handle == cmnd_cus->custom_value_handles.value_handle)
        {

    When I pause execution is shows it is running here:

    ret_code_t spi_transfer(uint8_t *txBuff, uint8_t *rxBuff, size_t tx_length, size_t rx_length, uint8_t cs)
    {
        nrfx_spim_xfer_desc_t xferDesc = NRFX_SPIM_XFER_TRX(txBuff, tx_length, rxBuff, rx_length);
    
        // Reset rx buffer and transfer flag
        memset(rxBuff, 0, rx_length);
        spi_xfer_done = false;
    
        /*NOTE: Below manual operation of CS pin is necessary because driver does not 
                natively handle multiple spi slaves on one spi instance */
        nrf_gpio_pin_clear(cs);
    
        //TODO: use nonblocking mode
        ret_code_t ret_err = nrfx_spim_xfer(&m_spi, &xferDesc, 0);
        
        while (!spi_xfer_done) 
        {
            __WFE();
        }
    
        /*NOTE: Below manual operation of CS pin is necessary because driver does not 
                natively handle multiple spi slaves on one spi instance */    
        nrf_gpio_pin_set(cs);
        
        return ret_err;
    }

    SPI communication during the Test_write_and_read_of_NVM() execution:

    So, it's appears calling the function during a BLE_GATTS_EVT_WRITE event is a problem.  I've have since rewritten code to not do any NVM processing during the BLE_GATTS_EVT_WRITE event, but it would be good to know why the results are different. 

Reply
  • I added a call to the NVM function (Test_write_and_read_of_NVM();) that is known to work was added here:

    static void on_Command_write(ble_Status_cus_t *stat_cus, ble_Cmnd_cus_t *cmnd_cus, ble_cus_data_t *p_cus, ble_evt_t const * p_ble_evt)
    {
        ble_gatts_evt_write_t const *p_evt_write = &p_ble_evt->evt.gatts_evt.params.write;
        uint8_t SOBRSafe_comnd = 0;
        uint32_t err_code;
        uint8_t SOBRSafe_err = SOBRSAFE_NO_ERROR;
        uint8_t rcvd_payload[PING_DATA_LENGTH]; 
        uint16_t rcvd_data_lngth = p_evt_write->len;
        timestamp_s curr_time;
        app_source_data *pull_strt_time;
        uint16_t ii = 0;
        Test_write_and_read_of_NVM();
        // Command Value Characteristic Written to.
        if (p_evt_write->handle == cmnd_cus->custom_value_handles.value_handle)
        {

    When I pause execution is shows it is running here:

    ret_code_t spi_transfer(uint8_t *txBuff, uint8_t *rxBuff, size_t tx_length, size_t rx_length, uint8_t cs)
    {
        nrfx_spim_xfer_desc_t xferDesc = NRFX_SPIM_XFER_TRX(txBuff, tx_length, rxBuff, rx_length);
    
        // Reset rx buffer and transfer flag
        memset(rxBuff, 0, rx_length);
        spi_xfer_done = false;
    
        /*NOTE: Below manual operation of CS pin is necessary because driver does not 
                natively handle multiple spi slaves on one spi instance */
        nrf_gpio_pin_clear(cs);
    
        //TODO: use nonblocking mode
        ret_code_t ret_err = nrfx_spim_xfer(&m_spi, &xferDesc, 0);
        
        while (!spi_xfer_done) 
        {
            __WFE();
        }
    
        /*NOTE: Below manual operation of CS pin is necessary because driver does not 
                natively handle multiple spi slaves on one spi instance */    
        nrf_gpio_pin_set(cs);
        
        return ret_err;
    }

    SPI communication during the Test_write_and_read_of_NVM() execution:

    So, it's appears calling the function during a BLE_GATTS_EVT_WRITE event is a problem.  I've have since rewritten code to not do any NVM processing during the BLE_GATTS_EVT_WRITE event, but it would be good to know why the results are different. 

Children
  • Hello,

    ccrider said:
    I am not waiting for a callback.

    That sounds like a reasonable workaround. However, I am still not sure what you are doing in your snippets. 

    ccrider said:
    I added a call to the NVM function (Test_write_and_read_of_NVM();) that is known to work was added here:

    Do you refer to the Test_write_and_read_of_NVM()?

    Is Test_write_and_read_of_NVM() the same as in your previous snippet?

    ccrider said:

    When I pause execution is shows it is running here:

    Where? Is it stuck here?

    while (!spi_xfer_done)
    {
        __WFE();
    }

    ccrider said:
    I am not waiting for a callback. 

    So where is "spi_xfer_done" being changed?

    My suspection is that you are waiting for a callback to set spi_xfer_done to true, but this callback will not be executed because you are waiting in another callback with the same or higher priority. 

    So there are two workarounds for this:

    1: In your on_Command_write() callback, just set a flag or something, and then handle the SPI transfer from the main context later.

    2: Increase the spi IRQ priority. You can set it to 2 or 3, as described here. The way you set it is in sdk_config.h. Search for SPI_IRQ_PRIORITY and NRFX_SPI_DEFAULT_CONFIG_IRQ_PRIORITY and set them both to e.g. 3.

    Best regards,

    Edvin

Related