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

nRF52840 flow control

Is it possible to communicate between 2 Nordic kits at 1 M baud without HW flow control? I came across this post in the forum which states that bytes can be missed when switching from primary RAM buffer to secondary RAM buffer if flow control is not enabled. This is an older post. Is this still applicable to nRF52840 and SDK 14.2.0?

https://devzone.nordicsemi.com/f/nordic-q-a/14656/app_uart_communication_error-without-flow-control

I noticed that the flow control (yellow)  kicks in after 60-70 us at 1 M baud. This seems to be coincident with the internal FIFO size of 6 bytes. The BLE is not enabled in this scenario and I am using nrf_drv_uart directly (without using app_uart_fifo or app_uart or nrf_serial libraries). If flow control was not enabled, I am seeing overrun errors after 6th or 7th byte.

  • Hi, if you enable EasyDMA (sdk_config.h) and use the driver directly you should be able to do this without loosing any data. I recommend to always call nrf_drv_uart_rx() until NRF_ERROR_BUSY, this way you ensure the secondary buffer is always ready to receive data when the first is full. Also you should set the buffer length to more than 1, e.g. >10.

  • Thanks for the response. This was very helpful. So my application is command/response communication scheme between master and slave. Size of response depends on the command sent. So would the sequence of TX/RX using the APIs would be as below.  I had to call the rx_abort between one TX and the next. Otherwise, the size of buffers gets out of sync.

    uint8_t rx_byte[256];
    while(1)
    {
    	// Command 1 (8 byte), Resp 1 (16 bytes)
    	while(NRF_SUCCESS != nrf_drv_uart_tx(&app_uart_inst, command_1, 8) );   
    	while( NRF_ERROR_BUSY != nrf_drv_uart_rx(&app_uart_inst, rx_byte, 16));
    	while( NRF_ERROR_BUSY != nrf_drv_uart_rx(&app_uart_inst, rx_byte, 16));
    	if(err_code != NRF_ERROR_BUSY)
    	{
    		APP_ERROR_CHECK(err_code);
    	}       
    
    	nrf_delay_ms(300);
    
    	nrf_drv_uart_rx_abort(&app_uart_inst); // generates a RXDONE event - ignore
    	
    	// Command 2 (4 byte), Resp 1 (128 bytes)
    	while(NRF_SUCCESS != nrf_drv_uart_tx(&app_uart_inst, command_2, 4) );   
    	while( NRF_ERROR_BUSY != nrf_drv_uart_rx(&app_uart_inst, rx_byte, 128));
    	while( NRF_ERROR_BUSY != nrf_drv_uart_rx(&app_uart_inst, rx_byte, 128));
    	if(err_code != NRF_ERROR_BUSY)
    	{
    		APP_ERROR_CHECK(err_code);
    	}       
    
    	nrf_delay_ms(300);
    
    	nrf_drv_uart_rx_abort(&app_uart_inst); // generates a RXDONE event - ignore
    			
    }

  • How about just supplying a large fixed buffer, e.g. 512bytes, and then the application may just read the RAM location directly? Of course the application then would possible need to handle the case that some bytes in a response may be written at the end of the buffer and continue at the start of the buffer (because the messages likely won't fit exactly in the 512bytes), but I don't expect that is a big problem.

Related