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

[bug report & fix] app_uart_fifo is sending APP_UART_TX_EMPTY event before the last byte is sent

Hi Team,

We are implementing an UART communication between a M4 processor (UART master) and a nRF51 (UART slave) and we want to use the UART in Low Power mode with flow control.

M4 and nRF are sharing the 4 UART standard line (RX, TX CTS, RTS). We add a fifth line (WTS), which is set when the nRF needs to transmit some data to the M4 and is clear when the communication is ended. To clear the line we are triggering the event APP_UART_TX_EMPTY which is provided by the app_uart_fifo library (cf. code below)

    case NRF_DRV_UART_EVT_TX_DONE:
        // Get next byte from FIFO.
        if (app_fifo_get(&m_tx_fifo, tx_buffer) == NRF_SUCCESS)
        {
            (void)nrf_drv_uart_tx(tx_buffer, 1);
        }
        if (FIFO_LENGTH(m_tx_fifo) == 0)
        {
            // Last byte from FIFO transmitted, notify the application.
            app_uart_event.evt_type = APP_UART_TX_EMPTY;
            m_event_handler(&app_uart_event);
        }
        break;

In that code and if we are dealing with the last byte to send, you can see that app_fifo_get(...) will take the last byte of the fifo and put it in tx_buffer and return NRF_SUCCESS. And then the tx_buffer is push in the TX register of the UART and will be sent. But now, the fifo is empty, and we can also see that the next instruction (FIFO_LENGTH) will return 0 and send the APP_UART_TX_EMPTY event, before the effective transmission of the last byte !

That fact is verified by the picture below:

image description

I fix that bug in changing the instruction if (FIFO_LENGTH(m_tx_fifo) == 0) by else:

        case NRF_DRV_UART_EVT_TX_DONE:
        // Get next byte from FIFO.
        if (app_fifo_get(&m_tx_fifo, tx_buffer) == NRF_SUCCESS)
        {
            (void)nrf_drv_uart_tx(tx_buffer, 1);
        }
        else
        {
            // Last byte from FIFO transmitted, notify the application.
            app_uart_event.evt_type = APP_UART_TX_EMPTY;
            m_event_handler(&app_uart_event);
        }
        break;

and you can see the result in the following picture: image description

I've check, this issue is in SDK 11 but it has been corrected in SDK 12.

Kind Regards

Patrice

Related