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.

  • 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

Related