This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Increasing bluetooth speed without blocking other peripherals

Hi,

I'm putting together some firmware that takes packets received over SPI and then streams them over BLE. I'm trying to run the BLE at close to 1Mb/s (which is still within spec from my understanding) but I'm getting some inconsistent packet dropping. After some debugging, I have come to some roadblocks.

1) Is there a way to confirm that I'm properly queueing BLE packets? I've instantiated the queued write module and enabled the length extension with the following code:

NRF_BLE_QWR_DEF(m_qwr);   

...
...

err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);

...
...

bool conn_evt_len_ext_enabled;
ble_opt_t  opt;

conn_evt_len_ext_enabled = true;

memset(&opt, 0x00, sizeof(opt));
opt.common_opt.conn_evt_ext.enable = conn_evt_len_ext_enabled ? 1 : 0;

err_code = sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &opt);
APP_ERROR_CHECK(err_code);


and when I want to send bluetooth packets I just use: 

ble_nus_data_send(&m_nus, ble_tx_buf, &ble_packet_length, m_conn_handle);


My understanding is that with my current setup, I can keep running 'ble_nus_data_send' and the microcontroller will just queue whatever I want to send to be sent later. Is that correct? Do I have to wait to receive NRF_SUCCESS?

2) I was reading this blog post: https://devzone.nordicsemi.com/nordic/nordic-blog/b/blog/posts/throughput-and-long-range-demo and went through the demo code and it seems like I can increase BLE transfer speeds by boosting my tx power. Is it recommended to change the tx power and link budget or should I not touch those? During run-time I set my PHY to 2M - does that automatically alter my tx power and link budget?

I should note that I'm building my peripheral FW off of the ble_app_uart example and my central FW off a ble_app_uart_c example - but I've added USB functionality. I'm more than happy to provide any/all code if there are any questions.

Thank you so much!

Ryan

Parents
  • Hi Ryan

    1. Have you been able to track down where exactly the packets are dropped? Does it occur from the SPI to the transmitting device, or is the data lost over the air? I think you should wait for the ble_nus_data_send() to be completed before you call it again.

    2. It only helps to increase the TX power if you're having trouble with the connection in terms of range, higher TX power won't help much if the devices are right next to each other. The 2MBPS PHY does not alter the TX power. 

    Best regards,

    Simon

  • Hi Simon!

    1) Right now it looks like it's happening on the Bluetooth side. I probed the spi pins and the data looks good and is being transmitted at the right rate. As far as waiting for the "success" response I ran into a weird issue.

    I figured things would run fastest if I put everything in the interrupt handlers so I have a timer_interrupt trigger a SPI transaction and then a SPI_interrupt handler that triggers a bluetooth transaction. My original code (where I wait for NRF_SUCCESS) is below:

    void spim_event_handler(nrfx_spim_evt_t const * p_event,
                           void *                  p_context)
    {
        spi_xfer_done = true;
        // Bring CS high
        nrf_gpio_pin_set(NRFX_SPIM_SS_PIN);
        
        // send 3 packets at once to take advantage of the large payload size
        if (spi_trx_counter == 3)
        {
            //NRF_LOG_INFO("READ 3 SPI PACKETS, SEND to BLE");
            spi_trx_counter = 0;
            while(ble_nus_data_send(&m_nus, ble_tx_buf, &ble_packet_length, m_conn_handle) != NRF_SUCCESS);
        }
    }
     

    This became problematic because waiting with "while(ble_nus_data_send(&m_nus, ble_tx_buf, &ble_packet_length, m_conn_handle) != NRF_SUCCESS);" in the interrupt handler prevented the SPI from operating 'while' the bluetooth was running. I confirmed this by probing my SPI pins with an oscilloscope - I'd get 3 SPI packets (all spaced <1ms apart) and then there would be a 6-7ms gap (what I assume is the connection interval) while the code hit the bluetooth transfer. In other words, the BLE was blocking the SPI  

    Removing the "while"  fixed this blocking problem. SPI transactions are happening at the proper rate now - but I worry I'm not queueing packets properly (which is why I'm getting some dropped packets). Do you know if how the queueing is handled in the backend? Or is this something I have to implement myself? If so, does that mean I 'have' to move the BLE transfers to my main loop?

    Edit: I took another look at my sdk_config and I saw the following block:

    // <e> NRF_BLE_QWR_ENABLED - nrf_ble_qwr - Queued writes support module (prepare/execute write)
    //==========================================================
    #ifndef NRF_BLE_QWR_ENABLED
    #define NRF_BLE_QWR_ENABLED 1
    #endif
    // <o> NRF_BLE_QWR_MAX_ATTR - Maximum number of attribute handles that can be registered. This number must be adjusted according to the number of attributes for which Queued Writes will be enabled. If it is zero, the module will reject all Queued Write requests. 
    #ifndef NRF_BLE_QWR_MAX_ATTR
    #define NRF_BLE_QWR_MAX_ATTR 0
    #endif

    I probably need to make NRF_BLE_QWR_MAX_ATTR at least 1 for the NUS notifications. Don't I? I also don't see anything in my sdk config for length extension. Do you know if I have to enable this in my SDK_config?

    2) Ahh that makes alot of sense. So playing with tx power and link budget won't really help me with this blocking problem that I'm dealing with. At least that's cleared up!

    Thanks so much for your help, Simon. I really appreciate it!

    Kindest regards,

    Ryan

Reply
  • Hi Simon!

    1) Right now it looks like it's happening on the Bluetooth side. I probed the spi pins and the data looks good and is being transmitted at the right rate. As far as waiting for the "success" response I ran into a weird issue.

    I figured things would run fastest if I put everything in the interrupt handlers so I have a timer_interrupt trigger a SPI transaction and then a SPI_interrupt handler that triggers a bluetooth transaction. My original code (where I wait for NRF_SUCCESS) is below:

    void spim_event_handler(nrfx_spim_evt_t const * p_event,
                           void *                  p_context)
    {
        spi_xfer_done = true;
        // Bring CS high
        nrf_gpio_pin_set(NRFX_SPIM_SS_PIN);
        
        // send 3 packets at once to take advantage of the large payload size
        if (spi_trx_counter == 3)
        {
            //NRF_LOG_INFO("READ 3 SPI PACKETS, SEND to BLE");
            spi_trx_counter = 0;
            while(ble_nus_data_send(&m_nus, ble_tx_buf, &ble_packet_length, m_conn_handle) != NRF_SUCCESS);
        }
    }
     

    This became problematic because waiting with "while(ble_nus_data_send(&m_nus, ble_tx_buf, &ble_packet_length, m_conn_handle) != NRF_SUCCESS);" in the interrupt handler prevented the SPI from operating 'while' the bluetooth was running. I confirmed this by probing my SPI pins with an oscilloscope - I'd get 3 SPI packets (all spaced <1ms apart) and then there would be a 6-7ms gap (what I assume is the connection interval) while the code hit the bluetooth transfer. In other words, the BLE was blocking the SPI  

    Removing the "while"  fixed this blocking problem. SPI transactions are happening at the proper rate now - but I worry I'm not queueing packets properly (which is why I'm getting some dropped packets). Do you know if how the queueing is handled in the backend? Or is this something I have to implement myself? If so, does that mean I 'have' to move the BLE transfers to my main loop?

    Edit: I took another look at my sdk_config and I saw the following block:

    // <e> NRF_BLE_QWR_ENABLED - nrf_ble_qwr - Queued writes support module (prepare/execute write)
    //==========================================================
    #ifndef NRF_BLE_QWR_ENABLED
    #define NRF_BLE_QWR_ENABLED 1
    #endif
    // <o> NRF_BLE_QWR_MAX_ATTR - Maximum number of attribute handles that can be registered. This number must be adjusted according to the number of attributes for which Queued Writes will be enabled. If it is zero, the module will reject all Queued Write requests. 
    #ifndef NRF_BLE_QWR_MAX_ATTR
    #define NRF_BLE_QWR_MAX_ATTR 0
    #endif

    I probably need to make NRF_BLE_QWR_MAX_ATTR at least 1 for the NUS notifications. Don't I? I also don't see anything in my sdk config for length extension. Do you know if I have to enable this in my SDK_config?

    2) Ahh that makes alot of sense. So playing with tx power and link budget won't really help me with this blocking problem that I'm dealing with. At least that's cleared up!

    Thanks so much for your help, Simon. I really appreciate it!

    Kindest regards,

    Ryan

Children
No Data
Related