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

UART FIFO Flush: How to determine that UART TX is completed

Hi everyone,

in our project we transmit from an android app to Nordic BLE big amount of data (up to 180.000 bytes). I do it by using hvx notifications (MTU 247) and each time I get the notification I try to transmit the data over UART. But we have realized that the uart TX takes too much time and causes packet loss. So I have decieded to store the BLE data and send it after the BLE notifications are completed. Now I face the problem that the UART FIFO (2048) will be full and causes system fault. I need to find out a way where I can determine when the TX transmition is completed and I can flush the TX buffer. I ve searched the uart driver but could find the right function for that. Can anyone help me regarding that?

Thx and Regards

Parents
  • Thanks for the support. I will get back to you after I got some new results.

  • Ok, just let me know when you have more questions. 

  • So our final conclusion: I can transfer 80KB of data from Android device->Nordic->UART->PC(Matlab) in around 4,4 seconds which is still too long (1000ms of sound data, 2300ms BLE 1Mbits, 1000ms UART). The bottleneck is the UART (1Mbits) ofcourse in case we use 2Mbits. My collegue asked me today why do I am not using the USBD interface for the data transfer. I checked out the examples and I am not sure if its possible to use it with Matlab directly. Have someone any experience with BLE->USB?

  • Hi

    If I understand you correctly you spend 2.3 seconds transferring the entire image over Bluetooth, and then 1.0 seconds afterwards to send it over UART?

    If so then you would probably realize the biggest savings if you are able to send the data over the UART during BLE activity, so that you don't have to wait until the end of the BLE transmission before starting UART TX. In this case you should be able to shave off almost the entire 1 second spent during UART activity, since it appears the BLE communication is slower than the UART communication in your example. 

    I realize you did the UART transfer after the BLE transfer to solve some other issue, but tackling this issue will probably be easier than to move everything to USB. 

    It is technically possible to configure the USB interface in the nRF52840, and handover information from the BLE stack to USB, but I doubt it will be significantly faster compared to the UART running at 1Mbaud. 

    Best regards
    Torbjørn

  • Yeah I have tried to send small heaps (244Bytes, each BLE Packet) on every "on_HVX" interrupt. I have faced crashes at some point (for example packetnr. 55 out of 365 BLE Packets). It was necessary to slow down the BLE notifications (by 4 ms for each packet). The reason for crash I guess was that the interrupt came before UART wasn't done with a packet transfer.  BLE 2MBit is (as expected) a bit faster than UART can handle. But unfortunately reducing the speed to BLE 1MBit was not the solution. I had to build some (4ms) delays between notifications on Android side. In sdk_config I have:


    #define NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL 7.5

    #define NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL 30


    #define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247

    #define NRF_SDH_BLE_GAP_EVENT_LENGTH 400

    and  

    config of the PHY:

    ble_gap_phys_t const phys =
    {
    .rx_phys = BLE_GAP_PHY_1MBPS,
    .tx_phys = BLE_GAP_PHY_1MBPS,
    };

    has no impact since the delay of 4 ms is necessary.

    The part of the code for on_hvx:

    static void on_hvx(ble_timeandsound_c_t * p_ble_timeandsound_c, ble_evt_t const * p_ble_evt)
    {

    ....

    if(pcounter <= NumOfExpPackets)
    {
      u16counter++; 
      ble_tas_uart_senddata(p_ble_evt->evt.gattc_evt.params.hvx.data, m_ble_max_data_len,   counter);
      //NRF_LOG_INFO(" PACKET = %d", pcounter);
    }else
    {
      u16counter = 0;
    }

    ....

    p_ble_timeandsound_c->evt_handler(p_ble_timeandsound_c, &ble_timeandsound_c_evt);

    }

    So there is no delay in on_hvx handle and m_ble_max_data_len = 244.

    Regarding LOG_INFO or debug information; does it has any impact on UART speed? 

Reply
  • Yeah I have tried to send small heaps (244Bytes, each BLE Packet) on every "on_HVX" interrupt. I have faced crashes at some point (for example packetnr. 55 out of 365 BLE Packets). It was necessary to slow down the BLE notifications (by 4 ms for each packet). The reason for crash I guess was that the interrupt came before UART wasn't done with a packet transfer.  BLE 2MBit is (as expected) a bit faster than UART can handle. But unfortunately reducing the speed to BLE 1MBit was not the solution. I had to build some (4ms) delays between notifications on Android side. In sdk_config I have:


    #define NRF_BLE_SCAN_MIN_CONNECTION_INTERVAL 7.5

    #define NRF_BLE_SCAN_MAX_CONNECTION_INTERVAL 30


    #define NRF_SDH_BLE_GATT_MAX_MTU_SIZE 247

    #define NRF_SDH_BLE_GAP_EVENT_LENGTH 400

    and  

    config of the PHY:

    ble_gap_phys_t const phys =
    {
    .rx_phys = BLE_GAP_PHY_1MBPS,
    .tx_phys = BLE_GAP_PHY_1MBPS,
    };

    has no impact since the delay of 4 ms is necessary.

    The part of the code for on_hvx:

    static void on_hvx(ble_timeandsound_c_t * p_ble_timeandsound_c, ble_evt_t const * p_ble_evt)
    {

    ....

    if(pcounter <= NumOfExpPackets)
    {
      u16counter++; 
      ble_tas_uart_senddata(p_ble_evt->evt.gattc_evt.params.hvx.data, m_ble_max_data_len,   counter);
      //NRF_LOG_INFO(" PACKET = %d", pcounter);
    }else
    {
      u16counter = 0;
    }

    ....

    p_ble_timeandsound_c->evt_handler(p_ble_timeandsound_c, &ble_timeandsound_c_evt);

    }

    So there is no delay in on_hvx handle and m_ble_max_data_len = 244.

    Regarding LOG_INFO or debug information; does it has any impact on UART speed? 

Children
  • Hi 

    If you have room to buffer the entire image in RAM then you should be able to simply use this buffer. Once the BLE data starts coming in you store it in the buffer, and once the buffer has got enough data to send a block over the UART you send a block from the buffer over the UART. 

    The incoming data from BLE will always go to the buffer first, and it doesn't matter what the UART is doing. 

    If the UART is quicker than the BLE link then they will stay more or less in sync, but if the UART is slower then the buffer will store the data while the UART is working. 

    Comodo said:
    Regarding LOG_INFO or debug information; does it has any impact on UART speed? 

    Which backend are you using? 
    The RTT backend should have very little impact on system performance. 

    Best regards
    Torbjørn

  • Hi I have tried that with a buffer of 100.000Bytes size and fed it with BLE data but it is always the same:

    -> NRF_ERROR_NO_MEM (4)

    I have also tried to buffer 20 Packets (20 x 244Bytes) and start then with the UART but no effect.

  • Hi 

    It seems like the buffers are full then. When the NRF_ERROR_NO_MEM error occurs you should stop sending bytes to the UART, and buffer them locally instead. 

    Once the APP_UART_TX_EMPTY event occurs you know that the UART has emptied it's internal buffers and are ready to receive more data. 

    Best regards
    Torbjørn

Related