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

Parents
  • 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

  • Hi Joe, 
    I think it was because the interrupt level. If you call the function inside an interrupt handler with more or equal priority to level 4 it will cause  a hardfault.
    Please have a look here: https://infocenter.nordicsemi.com/topic/sds_s132/SDS/s1xx/processor_avail_interrupt_latency/exception_mgmt_sd.html?cp=4_5_2_0_15_1

    You need to configure the UARTE interrupt level to level 5 or above. 

    Please try to step into the code and check where you get the assert, it's most likely because of the hvx API call. 

  • Hi Hung Bui,

    Thank you very much!
    It's really the problem of interrupt level.
    With UARTE, I can use up to 691k baud rate without any problem for Peripheral (UARTE -> BLE) and Central (BLE -> UARTE).

    To increase the through put, instead of sending 78 KB per 5ms through BLE, I have set double for it, which is 156 KB per 10 ms.

    But then I found another problem.
    The distance between the two BLE is very short (about 5 cm).
    If it is more then 5cm, the speed will become very slow or even being disconnected.
    I think it's strange and should be some setting problem?

    Some settings I have changed which may be related:
    Tx Power to 4 for Peripheral
    Both TX RX Phy is BLE_GAP_PHY_2MBPS for both Peripheral and Central
    MIN_CONN_INTERVAL MSEC_TO_UNITS(8, UNIT_1_25_MS)
    MAX_CONN_INTERVAL MSEC_TO_UNITS(10, UNIT_1_25_MS)

    Thanks,
    Joe

Reply
  • Hi Hung Bui,

    Thank you very much!
    It's really the problem of interrupt level.
    With UARTE, I can use up to 691k baud rate without any problem for Peripheral (UARTE -> BLE) and Central (BLE -> UARTE).

    To increase the through put, instead of sending 78 KB per 5ms through BLE, I have set double for it, which is 156 KB per 10 ms.

    But then I found another problem.
    The distance between the two BLE is very short (about 5 cm).
    If it is more then 5cm, the speed will become very slow or even being disconnected.
    I think it's strange and should be some setting problem?

    Some settings I have changed which may be related:
    Tx Power to 4 for Peripheral
    Both TX RX Phy is BLE_GAP_PHY_2MBPS for both Peripheral and Central
    MIN_CONN_INTERVAL MSEC_TO_UNITS(8, UNIT_1_25_MS)
    MAX_CONN_INTERVAL MSEC_TO_UNITS(10, UNIT_1_25_MS)

    Thanks,
    Joe

Children
No Data
Related