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

BLE disconnects during multiple SPI transfers on nrf52832

Hello everyone,

I have a nrf52832 (SDK v15.2.0) that is connected to a tablet via BLE.  However, if I have several SPI transfers one after another, the BLE suddenly disconnects. It doesn't make a difference neither if I use the DMA or if I'm blocking. The priority of the SPI interrupts is also very low and equal to 6. I need to mention that all the SPI transfers are done in the function I schedule once (which is called do_all_the_xfers() here). So it looks the following:

static void do_all_the_xfers(void * data, uint16_t len) {
    for(uint32_t i = 0; i < 4294967295; i++) {
        status = pltf_spim_xfer2();
        if(status != NO_ERROR) return;
    }
}

While pltf_spim_xfer2() looks like this:

static const nrfx_spi_t spi = NRFX_SPI_INSTANCE(FLASH_SPI_INSTANCE);
bool spi_xfer_done = false;

void spi_event_handler(nrfx_spi_evt_t const * p_event,
                       void *                    p_context) {
    spi_xfer_done = true;
}

status_t pltf_spim_xfer2(void) {
   uint32_t err_code, flags;

   flags = 0;
   spi_xfer_done = false;
   nrfx_spi_xfer_desc_t xfer;
   char read_id_cmd = 0x9F;
   char rx_buf[3];
  
   xfer.p_tx_buffer = &read_id_cmd;
   xfer.tx_length = 1;
   xfer.p_rx_buffer = NULL;
   xfer.rx_length   = 0;

   nrf_gpio_pin_clear(FLASH_SPI_SS_PIN);
   err_code = nrfx_spi_xfer(&spi, &xfer, flags);
   if(err_code != 0) { NRF_LOG_INFO("err_code: %i", err_code); NRF_LOG_FLUSH(); }

   while(!spi_xfer_done){};

   spi_xfer_done = false;
   xfer.p_tx_buffer = NULL;
   xfer.tx_length = 0;
   xfer.p_rx_buffer = rx_buf;
   xfer.rx_length   = 3;

   nrf_gpio_pin_clear(FLASH_SPI_SS_PIN);
   err_code = nrfx_spi_xfer(&spi, &xfer, flags);
   if(err_code != 0) { NRF_LOG_INFO("err_code: %i", err_code); NRF_LOG_FLUSH(); }

   while(!spi_xfer_done){};

   return  NO_ERROR;
}

Therefore, the scheduler doesn't go back to the main loop until its done with all the transfers. Nevertheless, according to my understanding the Bluetooth has such a high priority that even in case of a while(1) loop, its interrupts are handled. So what could be the problem?

Thanks in advance!

Parents
  • Hello,

    From where do you call do_all_the_xfers()?

    The SPI interrupt priority decides the interrupt priority, that is, what priority SPI messages from the external device will use.

    If you call do_all_the_xfers() from a callback with higher priority, that will be the priority that this SPI transfer use.

    So where do you call do_all_the_xfers() from?

Reply
  • Hello,

    From where do you call do_all_the_xfers()?

    The SPI interrupt priority decides the interrupt priority, that is, what priority SPI messages from the external device will use.

    If you call do_all_the_xfers() from a callback with higher priority, that will be the priority that this SPI transfer use.

    So where do you call do_all_the_xfers() from?

Children
  • Hi Edvin,

    After pressing a certain button on the tablet I receive a Bluetooth callback on the nrf side. Within this callback I call app_sched_event_put(NULL, 0, do_all_the_xfers); I guess, this should be ok, since it will be worked off by the main thread afterwards, right?

  • So you call app_sched_execute() from a main() context, right? E.g. inside idle_state_handle() called from the main()-loop?

    If so, it should be fine, I guess.

    That was my initial guess, so let's investigate further.

    What is your device connected to? (over BLE). A phone or another nRF device? Or something else?

    Is this a central or a peripheral?

    Can you please check the disconnection reason? When you get the BLE_GAP_EVT_DISCONNECTED event, can you insert this piece of code:

            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("Disconnected");
                NRF_LOG_INFO("Disconnect reason %d", p_ble_evt->evt.gap_evt.params.disconnected.reason);
                // LED indication will be changed when advertising starts.
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                break;

    What is the reason? Which one does it refer to in ble_hci.h? Do you get the disconnected event on the device that is using SPI at all?

    Best regards,

    Edvin

  • Hi Edvin,

    My nrf is connected to a Samsung tablet S4 and the nrf is acting as peripheral while the tablet acts as central. I checked the disconnection reason and it turns out that it is an connection timeout (BLE_HCI_CONNECTION_TIMEOUT). In my opinion this kinda means that the nrf is too busy doing other stuff than to handle the bluetooth connection. The connection parameters are initially negotiated between the nrf and the tablet, I can try to tune these parameters but I don't think that this is the actual reason. Also, when adding nrf_delay_ms(10); every time after an spi transaction it doesn't happen anymore, but just slows things down too much. Is there a possibility to check the current priority since you mentioned that this changes depending on the context you call a function from? I still think that this is not the issue, since the function is processed in the main thread but just to be 100% sure.

    Thanks and best regards,

    pingu

  • Hello pingu. The nrf_delay_ms() is not recommended when you are using the softdevice. As long as it is called from a low enough priority, it doesn't necessarily harm anything,  but the only thing it does is to halt the CPU, drawing power for the delay that you use (10ms), because it is preventing it from going to sleep.

    Just to confirm, the BLE_HCI_CONNECTION_TIMEOUT is the reason you receive on the NRF, right?

    Is it possible to provide a sniffer trace? A trace captured with nRF Sniffer is sufficient.

    Do you by chance have SVCALL_AS_NORMAL_FUNCTION defined?

  • Hi Edvin,

    Just to confirm, the BLE_HCI_CONNECTION_TIMEOUT is the reason you receive on the NRF, right

    that's correct.

    I captured a trace with the nRF Sniffer, however, the disconnection event doesn't pop up on wireshark. So after it happened, I don't see any traffic anymore. I'm not sure if this is due to the sniffer setup (it turned out to be a little bit buggy and it is quite difficult to capture a trace, sometimes nothing is traced)... The SVCALL_AS_NORMAL_FUNCTION  is not defined.nrf52832 trace.pcapng

Related