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

UART overrun handling FIFO

Hi

We've some trouble with the UART (not UARTE) of the nRF52840. We use a baudrate of 38400. Because of HW limitations and power constrains, we do either have flow control nor DMA. We use currently the SDK Version 15.2.

Under some circumstances, an overrun error (UART_ERRORSRC_OVERRUN_Msk) occures. This because the softdevice will sometimes block the irq of the UART so the bytes can not be transfered from the internal 6 byte FIFO. The problem was that the application never recovered from this error. According to the post UART Overrun Error after Reset we used the iteration to clear the FIFO and are able to recover fine.

At the moment, the driver starts after each NRFX_UART_EVT_RX_DONE a new reception. The UART Driver needs an interrupt callback after each byte is received (this is the main reason we do not use a larger buffer so far).


void uart_event_handler(nrfx_uart_event_t const * p_event, void* p_context)
{
    switch (p_event->type) {
    case (NRFX_UART_EVT_ERROR):

        nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_RXTO);
        nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_RXDRDY);
        nrf_uart_event_clear(NRF_UART0, NRF_UART_EVENT_ERROR);
    
    
        if(errorCode == UART_ERRORSRC_OVERRUN_Msk){
            for(uint32_t i = 0; i < NRF_UART_FIFO_SIZE; i++)
            {
                nrf_uart_rxd_get(uart_instance.p_reg);
            }        
        }
    
        nrfx_uart_rx(&uart_instance, &m_rxByte, 1u);

        break;
    case (NRFX_UART_EVT_RX_DONE):
        pushToBuffer(m_rxByte);
        nrfx_uart_rx(&uart_instance, &m_rxByte, 1u);
        nrfx_uart_rx_enable(&uart_instance);


        break;

    case (NRFX_UART_EVT_TX_DONE):
        if (instance != nullptr) {
            instance->onTxDone();
        }
        break;
    default:
        DRV_UART_ERROR_DEBUGPRINTF("Warning: Unhandled UART - EVENT occured \r\t");
        break;

    }

}

  • Is it possible to get to know how many bytes currently are in the FIFO so the Driver is able to get in each interrupt run all "pending" bytes? I would prefer instead to read as many bytes as possible during the event NRFX_UART_EVT_RX_READY by using for example

  for(uint32_t i = 0; i < numerOfBytesReceived; i++)
  {
      pushToBuffer(nrf_uart_rxd_get(uart_instance.p_reg));
  }

  • Would you suggest another apporeach / is there a better way to handle that?

Many thanks

  • his because the softdevice will sometimes block the irq of the UART s

    Try raising the UART IRQ priority to APP_IRQ_PRIORITY_HIGHEST.

    The highest prio available to the app can actually preempt some non-timing critical softdevice tasks. This may (or may not) be enough for 38k baud.

    UARTE and UART sould have roughly similar power consumtion. Both need HFCLK running for proper UART timing.

Related