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

Bug in app_uart in SDK 10

Hello, I think there's a bug in the app_uart library in SDK 10 that occurs when the FIFO is enabled.

Using SDK nRF51_SDK_10.0.0_dc26b5e, I was trying to write data to the UART as fast as possible in a loop with the baud rate set to 1M, to test the maximum throughput. The problem is that sometimes bytes were output from the UART out of order.

It looks like the problem is in app_uart_put in app_uart_fifo.c:

uint32_t app_uart_put(uint8_t byte)
{
    uint32_t err_code;

    tx_tmp = byte;
    err_code = nrf_drv_uart_tx(&tx_tmp, 1);

    if (err_code == NRF_ERROR_BUSY)
    {
        err_code = app_fifo_put(&m_tx_fifo, byte);
    }

    return err_code;
}

It's not checking if there are any bytes in the FIFO waiting to be sent, before it sends the byte to the UART driver directly. So if it's called in the time after the UART driver finishes sending the last byte, but before the event handler starts sending the next byte from the FIFO, then it will send the byte out of order.

Parents
  • Sorry for the late reply.

    There is a bug.

    But it's not the lack of checking if the FIFO is empty before calling nrf_drv_uart_tx. nrf_drv_uart_tx will return NRF_ERROR_BUSY as long as there is something in the FIFO, since new bytes are fetched from the FIFO and passed to the driver in the interrupt handler.

    There is a race condition in app_uart_put. When nrf_drv_uart_tx returns NRF_ERROR_BUSY and the transmission finishes right after that but before the new byte is actually put into the FIFO, then this new byte will linger in the FIFO until app_uart_put is called again (non-empty FIFO won't trigger a new transmission, nrf_drv_uart_tx must be called for this to happen). And the byte passed to this call is transmitted before this one from the FIFO, thus the order is incorrect. This can be observed when some delay is added in app_uart_put, right before app_fifo_put.

    This will be fixed in SDK 11 which will be released in the start of March.

    For SDK 11.0.0-2.alpha it is possible to replace nrf_drv_uart.c, nrf_drv_uart.h and app_uart_fifo.c with the files from this zip. Here is also the diff with the changes.

Reply
  • Sorry for the late reply.

    There is a bug.

    But it's not the lack of checking if the FIFO is empty before calling nrf_drv_uart_tx. nrf_drv_uart_tx will return NRF_ERROR_BUSY as long as there is something in the FIFO, since new bytes are fetched from the FIFO and passed to the driver in the interrupt handler.

    There is a race condition in app_uart_put. When nrf_drv_uart_tx returns NRF_ERROR_BUSY and the transmission finishes right after that but before the new byte is actually put into the FIFO, then this new byte will linger in the FIFO until app_uart_put is called again (non-empty FIFO won't trigger a new transmission, nrf_drv_uart_tx must be called for this to happen). And the byte passed to this call is transmitted before this one from the FIFO, thus the order is incorrect. This can be observed when some delay is added in app_uart_put, right before app_fifo_put.

    This will be fixed in SDK 11 which will be released in the start of March.

    For SDK 11.0.0-2.alpha it is possible to replace nrf_drv_uart.c, nrf_drv_uart.h and app_uart_fifo.c with the files from this zip. Here is also the diff with the changes.

Children
Related