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

APP UART FIFO has performance issues

If the UARTE interrupt service routine is delayed from running more than 1 byte's worth of time, then APP UART FIFO does not see all bytes queued in the UARTE's easyDMA buffer.

In file app_uart_fifo.c in function uart_event_handler, the event handler for NRF_DRV_EVT_RX_DONE only removes the first byte from the UARTE buffer and ignores any remaining bytes in the buffer.  Function uart_event_handler is called from function rx_done_event in file nrfx_uarte.c where it passes a pointer to the buffer and number of bytes in the buffer in the event variable.  So the issue is really in function uart_event_handler where it is ignoring the number of bytes being passed in variable event.

Below is part of the original code with the problem:

static void uart_event_handler(nrf_drv_uart_event_t * p_event, void* p_context)
{
    app_uart_evt_t app_uart_event;
    uint32_t err_code;

    switch (p_event->type)
    {
        case NRF_DRV_UART_EVT_RX_DONE:
            // Write received byte to FIFO.
            err_code = app_fifo_put(&m_rx_fifo, p_event->data.rxtx.p_data[0]);
            if (err_code != NRF_SUCCESS)

Below are the changes I made to fix the issue in my system:

static void uart_event_handler(nrf_drv_uart_event_t * p_event, void* p_context)
{
    app_uart_evt_t app_uart_event;
    uint32_t err_code;
    uint8_t byte;

    switch (p_event->type)
    {
        case NRF_DRV_UART_EVT_RX_DONE:
            // Write received byte to FIFO.
            err_code = NRF_SUCCESS;
            byte = p_event->data.rxtx.bytes;
            while ((err_code == NRF_SUCCESS) && (byte--))
            {
                err_code = app_fifo_put(&m_rx_fifo, p_event->data.rxtx.p_data[0]);
                p_event->data.rxtx.p_data++;
            }
            if (err_code != NRF_SUCCESS)

I found the issue in SDK 15.0.0.  The issue surfaced when I was trying to constantly send data over the BLE at the same time receive several hundred bytes over UARTE.

Parents
  • Hi,

    The app_uart_fifo is only using a RX/TX buffer size of 1 byte. When starting the recpetion using nrf_drv_uart_rx() the length parameter is always set to 1. So you should only get NRF_DRV_UART_EVT_RX_DONE events with data.rxtx.bytes set to 1. The app_uart_fifo was originally designed for the NRF51 series, where the UART did not have easyDMA.

    A replacement for app_uart is to use the serial library instead, it is able to take full advantage of the EasyDMA and have better performance. See this link.

    Best regards,

    Sigurd

Reply
  • Hi,

    The app_uart_fifo is only using a RX/TX buffer size of 1 byte. When starting the recpetion using nrf_drv_uart_rx() the length parameter is always set to 1. So you should only get NRF_DRV_UART_EVT_RX_DONE events with data.rxtx.bytes set to 1. The app_uart_fifo was originally designed for the NRF51 series, where the UART did not have easyDMA.

    A replacement for app_uart is to use the serial library instead, it is able to take full advantage of the EasyDMA and have better performance. See this link.

    Best regards,

    Sigurd

Children
No Data
Related