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

Data throughput between nrf52810 BLE & UART

Hi,

In my application, I would like to transfer data from MCU ---(UART#1)---> BLE#1(Peripheral) ---> BLE#2(Central) ---(UART#2)---> PC.
I start my code based on ble_app_uart_pca10040e_s112 & ble_app_uart_c_pca10040_s132.

The model I am using for BLE#1 is nrf52810.
The data of 78 byte is transferred from MCU to BLE#1 through UART#1 every 20ms.
The data only transfer in one way. i.e. No data send back from PC to MCU is needed.

I have confirmed the above example code works properly with the following setting:
The UART#1 baud rate between MCU and BLE#1: 250kbps
The UART#2 baud rate between BLE#2 and PC: 460kbps
Both peripheral and central BLE tx_phys and rx_phys is set to BLE_GAP_PHY_AUTO.
No flow control for both UART#1 and UART#2.
Peripheral m_ble_nus_max_data_len is set to 78. (As all data are fixed size of 78 byte)
Peripheral NRF_SDH_BLE_GATT_MAX_MTU_SIZE is set to 81 in sdk_config.h. (I expect it is data length +3 bytes?)
Central BLE#2 ECHOBACK_BLE_UART_DATA is set to 0.

What I would like to do is to increase the transfer rate as follow:
Every 5ms, 78 byte data transfer from MCU to BLE#1, with baud rate 690kbps.

I have confirmed that the 78 bytes is transferred correcly from MCU to BLE#1 only if the BLE#1 is not advertising or connected, by checking the total received data length, header (first 5 bytes) and footer (last 5 bytes) are received correctly.
However, if the BLE starts advertising, BLE#1 does not receive the data correctly.
I added some counter and found the success vs failure ratio is about 15~20 vs 1000.
I suspect if the BLE is processing (some interrupt event?) affects the UART FIFO process? (Just some guess, please correct me)

And what I would like to ask is:
1. If the targeted data through put is possible?
Due to some restriction on MCU processing, UART transfer have to be finished within 1.2ms.
The remaining 3.8ms is for MCU accessing other sensors to collect the 78 byte data.
Therefore the baud rate of UART#1 have to be around 690kbps, which can finish the transfer through UART#1 within 1.1ms.
Lower baud rate (i.e. 460kbps) will be too slow for as it takes around 1.7ms.

2. How to increase the data throughput between BLE?
I have already increase the PHY to BLE_GAP_PHY_2MBPS for both tx and rx (although my application is transfering data one way) on both peripheral and central.
And confirmed it is changed by the BLE_GAP_EVT_PHY_UPDATE event in ble_evt_handler. (By referencing this post: devzone.nordicsemi.com/.../nrf52832-ble_gap_phy_2mbps-configuraion-in-ble_app_uart-peripheral-mode)
Is there anything else I have to configure?
Is the transfer rate between BLE 300kbps?
Is there anyway I can check if my setting is correct?

3. What caused the received data from UART#1 lost some bytes? Is there anyway to improve the performance?
When the BLE is advertising or transmitting data, UART#1 will not receive data correcly.
Some bytes are missing. For example, if the original data from MCU is:
ABCDEFG1234567...
It will receive with some randomly missing byte like:
ABDEF24567... or ACDEF12457...
And I cannot figure out what caused the problem.

Thank you in advanced.
Joe

  • Hi Joe, 

    1. Could you please explain how you use UART ? Do you use Easy DMA ? Do you use any of our uart libraries ? 

    Which UART baudrate did you actually operate at ? We support up to 1Mbps baud. 

    2. To increase the throughput on BLE, it's important to: 

    - Transmit as much as possible (queue data as much as possible)

    - Low connection interval

    - Use Data length extension at least lager than NRF_SDH_BLE_GATT_MAX_MTU_SIZE 

    Please check using our \examples\ble_central_and_peripheral\experimental\ble_app_att_mtu_throughput example to test. We observed around 600kbps using 1Mbps BLE PHY and about 1.2Mbps using 2Mbps BLE PHY. 

    3. It's hard to tell ,if you don't use Easy DMA and if you don't have HWFC missing byte would definitely happens if the CPU is busy doing something else. 

  • Hi Hung Bui,

    Thank you for your reply.

    I am currently busying on other stuffs, but I have a quick question about #3 first.

    As my application is basically a one way NUS (Nordic UART service) from MCU --UART--> BLE ---> BLE --UART--> PC, so I originally expect is just to increase the overall throughput.

    The MCU UART only have 2 pin so hardware flow control is not available.
    For the peripheral, I am using the example of nRF5SDK160098a08e2/examples/ble_peripheral/ble_app_uart.
    For the central, it is ble_central/ble_app_uart_c as its counterpart.
    Looks like the ble_app_uart example uses app_uart_fifo, and it takes 1 byte every time until the buffer is empty?

    I read several posts on DevZone and figure out that there are some config like NRFX_UART_ENABLED, NRFX_UART0_ENABLED, NRFX_UARTE_ENABLED, NRFX_UARTE0_ENABLED, UART_EASY_DMA_SUPPORT, UART0_CONFIG_USE_EASY_DMA etc.

    So my question is:
    #3a How do I enable / apply EasyDMA to the example? And how do I confirm if I am using EasyDMA?
    Seems just turning on the UART_EASY_DMA_SUPPORT or UART0_CONFIG_USE_EASY_DMA does not change.
    I am not quite sure if it is using EasyDMA or not.
    Or does the example does not support EasyDMA? so I have to write something myself?
    It will be helpful if there is any sample code I could reference.

    In sdk_config.h, the UART setting which looks related are as follow:
    NRFX_UARTE_ENABLED 1
    NRFX_UARTE0_ENABLED 0
    NRFX_UART_ENABLED 1
    NRFX_UART0_ENABLED 0
    UART_ENABLED 1
    UART_EASY_DMA_SUPPORT 1
    UART_LEGACY_SUPPORT 1
    UART0_ENABLED 1
    UART0_CONFIG_USE_EASY_DMA 1
    APP_UART_ENABLED 1

    #3b After looking for the above setting, I am quite confuse with UART, UART0, UARTE, UARTE0.
    Can you briefly explain whats the difference?

    Thank you very much.

    Best Regards,
    Joe

  • Hi Joe, 

    NRFX_UART is just to support the legacy UART peripheral (no EasyDMA), you can uncheck that. 

    If you are using ble_app_uart, most likely you are using app_uart for handling UART communication. This library unfortunately not a best choice for application without HWFC and high baudrate.

    The reason is that due to the nature of UARTE, you don't receive any event when a byte is received, and you only receive an event when the EasyDMA buffer is full, it has to set the EasyDMA buffer to 1 byte to receive an event for each byte. And this causes the problem when you don't have HWFC and the CPU is busy for BLE. No advantage of using EasyDMA in this implementation.

    We have a more advanced UARTE library called libuarte. You can find the example at \examples\peripheral\libuarte. The documentation for the library is here.

    This advance library uses a timer to count for the number of byte received. And the async library on top of the driver has a timer  to generate a timeout if there is no transaction. The trade off is that more PPI channel and TIMER(s) are needed. 

    In your case, you have all data fixed to 78 bytes, you can use the driver and don't really need the async library. I think you can also use UARTE directly. An example of using UARTE directly can be found here (the example is for TX, but RX should be similar).

  • Hi Hung Bui,

    Thank you for your suggestion and sample code. I have tried with UARTE and now I am able to receive the data to buffer called uarte_buffer[200].

    So the next step is to pass the buffer content to BLE when the interrupt occurs, where NRF_UARTE0->EVENTS_ENDRX == 1.

    I have reference the original UART sample code (it's placed in function uart_event_handle, case APP_UART_DATA_READY):

    do
    {
    	uint16_t length = (uint16_t)index;
    	err_code = ble_nus_data_send(&m_nus, data_array, &length, m_conn_handle);
    	if ((err_code != NRF_ERROR_INVALID_STATE) &&
    		(err_code != NRF_ERROR_RESOURCES) &&
    		(err_code != NRF_ERROR_NOT_FOUND))
    	{
    		APP_ERROR_CHECK(err_code);
    	}
    } while (err_code == NRF_ERROR_RESOURCES);

    The above code works correctly , no matter BLE is connected or disconnected.
    When not connected it "do nothing"; When connected, it transmit to the connected BLE and I have confirmed I can view the data on the other side.

    However with my UARTE:

    void send_thru_ble(void)
    {
        uint16_t length = (uint16_t)78;	// Data length is always is 78
        uint32_t       err_code;
    	
    	NRF_LOG_INFO("START: send_thru_ble");
    	do
    	{
    		err_code = ble_nus_data_send(&m_nus, uarte_buffer, &length, m_conn_handle);
    		if ((err_code != NRF_ERROR_INVALID_STATE) &&
    			(err_code != NRF_ERROR_RESOURCES) &&
    			(err_code != NRF_ERROR_NOT_FOUND))
    		{
    			APP_ERROR_CHECK(err_code);
    		}
    	} while (err_code == NRF_ERROR_RESOURCES);
    	NRF_LOG_INFO("FINISH: send_thru_ble");
    }

    When the interrupt function (UARTE0_UART0_IRQHandler) being called where NRF_UARTE0->EVENTS_ENDRX == 1, I will call the above send_thru_ble().
    When there is no BLE connection, it does not transmit anything and both logs are viewable through RTT Viewer.
    However, if the BLE is connected, the system somehow looks hung there, and no log could be seen on RTT Viewer.
    I suspect there is some problem when running the ble_nus_data_send, but I don't know how to figure it out.
    Because if I set breakpoint on the line err_code = ble_nus_data_send(...), the system will get into NRF_BREAKPOINT_COND; // On assert, the system can only recover with a reset.

    The differences of sdk_config.h are the following:
    UART:
    NRFX_PRS_ENABLED 1
    NRFX_UARTE0_ENABLED 0
    NRFX_UART_ENABLED 1
    UART_LEGACY_SUPPORT 1

    UARTE:
    NRFX_PRS_ENABLED 0
    NRFX_UARTE0_ENABLED 1
    NRFX_UART_ENABLED 0
    UART_LEGACY_SUPPORT 0

    Do you have any hint for me either on:
    1. How to debug it this case; or
    2. Any setting I have missed to make ble_nus_data_send work?

    Best Regards,
    Joe

  • Sorry but I am quite urgent on resolving the problem of transmitting through BLE.
    Could anyone help on this?

    Thank you very much.

Related