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

Dubble buffered UARTE reception

Hi NordicSemi

I have a project where we receive data via the UARTE. To avoid missing data caused by higher prioritized tasks we want to use the DMA facilities. 

nrf52832 with softdevice and SDK version 15.2

But as we do not know how many bytes we receive we want to use the double buffered facilities, allowing us to process one buffer while the other are used for reception.

But we are not always receiving data, and we still not know how many data are going to be received, therefore we want to periodically forcefully swap from one buffer to the other.

Is this possible.

I have tried with the following (only relevant code snippets shown):

static void FpiUartEventHandler(nrf_drv_uart_event_t * p_event, void * p_context)
{
  uint8_t *p = p_event->data.rxtx.p_data;
  uint32_t l = p_event->data.rxtx.bytes;
  switch(p_event->type)
  {
  case NRFX_UARTE_EVT_ERROR:
    while(l--)
      FifoPut(&fifoRxUart, *p++);

/* Restart reception */
    nrf_drv_uart_rx(&m_uart, bufferRx[0], FPI_UART_MAX_LENGTH);
    nrf_drv_uart_rx(&m_uart, bufferRx[1], FPI_UART_MAX_LENGTH);
    break;
  case NRF_DRV_UART_EVT_TX_DONE:
  {
    FpiUartTransmitNext();
    break;
  }
  case NRF_DRV_UART_EVT_RX_DONE:
  {
    while(l--)
      FifoPut(&fifoRxUart, *p++);

    ret = nrf_drv_uart_rx(&m_uart, p_event->data.rxtx.p_data, FPI_UART_MAX_LENGTH);

    break;
  }
  default:
    break;
  }
}

static void FpiPoll(void * p_context)
{
/* Used as timeout, to ensure that data is not left in receive buffer too long */
  nrf_drv_uart_rx_abort(&m_uart); /* end receiving on primary buffer, automatically switching to secondary buffer */
}

void FpiInit(void)
{
  nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG;
  config.pseltxd = HAL_UART_TX_PIN;
  config.pselrxd = HAL_UART_RX_PIN;
  APP_ERROR_CHECK(nrf_drv_uart_init(&m_uart, &config, FpiUartEventHandler));
  APP_ERROR_CHECK(nrf_drv_uart_rx(&m_uart, bufferRx[0], FPI_UART_MAX_LENGTH));
  APP_ERROR_CHECK(nrf_drv_uart_rx(&m_uart, bufferRx[1], FPI_UART_MAX_LENGTH)); // Do not use double buffering at the time.

  APP_ERROR_CHECK(app_timer_create(&m_fpi_timer_id, APP_TIMER_MODE_REPEATED,  FpiPoll));
  APP_ERROR_CHECK(app_timer_start(m_fpi_timer_id, APP_TIMER_TICKS(FPI_TIMER_PERIOD), NULL));
}

The nrf_drv_uart_rx_abort does trigger the TO event on the UART receiver and the FpiUartEventHandler is called. But in the driver the secondary buffer is forcefully canceled.

Therefore it seems to be impossible to use the double buffered feature together with the nrf_drv_uart_rx_abort. 

Did I miss something?

BR and thanks in advance.

Parents
  • Hi,

    I'm not sure exactly how this should work. The rx_abort function triggers the STOPRX task in the peripheral. The UARTE has a HW FIFO that can receive up to 4 bytes before the TO event. The RX FIFO must be flushed after the timeout, in order to not lose data. There is no shortcut between the timeout event and STARTRX, so you will anyway have to start the RX through using CPU after this event is received.

    I do not think the double buffering feature is created with variable length transfers in mind.

    Best regards,
    Jørgen 

  • Hi

    The 4 byte HW receive buffer is not much as the soft device has higher priority, and can take the resources in longer time that 4 bytes received on a UART at 921600 baud. I have analysed the behavior when I try to restart the reception after using the RX-abort, when simultaneously receiving data.

    "I do not think the double buffering feature is created with variable length transfers in mind.": You are probably right. But I can not be the first one needing this. And I believe that the HW supports it. But the SDK avoids using it.

    But it seems to be a problem I must handle elsewhere. :-(

    Kasper

Reply
  • Hi

    The 4 byte HW receive buffer is not much as the soft device has higher priority, and can take the resources in longer time that 4 bytes received on a UART at 921600 baud. I have analysed the behavior when I try to restart the reception after using the RX-abort, when simultaneously receiving data.

    "I do not think the double buffering feature is created with variable length transfers in mind.": You are probably right. But I can not be the first one needing this. And I believe that the HW supports it. But the SDK avoids using it.

    But it seems to be a problem I must handle elsewhere. :-(

    Kasper

Children
No Data
Related