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

UARTE Clear Rx Buffer

Hello, there,

I am trying to get the UARTE working on a custom nRF52840 board. In my setup, I am expecting a response to every transmission on UART.

Here's my setup code:

NRF_LIBUARTE_ASYNC_DEFINE(UARTE0, 0, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);
NRF_QUEUE_DEF(UARTERxBuffer, UARTE0RxBufferQueue, 4, NRF_QUEUE_MODE_NO_OVERFLOW);

//Initialising UARTE module
nrf_libuarte_async_config_t nrf_libuarte_async_config = {
      .tx_pin = JETFILE2_UART_TX_PIN,
      .rx_pin = JETFILE2_UART_RX_PIN,
      .baudrate = NRF_UARTE_BAUDRATE_115200,
      .parity = NRF_UARTE_PARITY_EXCLUDED,
      .hwfc = NRF_UARTE_HWFC_DISABLED,
      .timeout_us = 100,
      .int_prio = APP_IRQ_PRIORITY_LOW,
  };
  
  ret_code_t err_code = nrf_libuarte_async_init(&UARTE0, &nrf_libuarte_async_config, UARTE0EventHandler, (void *)&UARTE0);
  APP_ERROR_CHECK(err_code);

  nrf_libuarte_async_enable(&UARTE0);

Here's my event handler:

/*
 * Function: UARTE0EventHandler
 * Params: (Please refer to nRF documentation)
 * returns: None
 * Description: Handle for all UARTE events.
 */

void UARTE0EventHandler(void *context, nrf_libuarte_async_evt_t *p_evt) {
  nrf_libuarte_async_t *p_libuarte = (nrf_libuarte_async_t *)context;
  ret_code_t ret;

  switch (p_evt->type) {
  case NRF_LIBUARTE_ASYNC_EVT_ERROR:
    break;
  case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
    //Data received on UART. If a queue is available, "push" the Rx data into that queue.
    if (nrf_queue_available_get(&UARTE0RxBufferQueue) > 0) {
      UARTERxBuffer pushBuffer;
      pushBuffer.length = p_evt->data.rxtx.length;
      pushBuffer.p_data = p_evt->data.rxtx.p_data;

      //Push the data into the queue
      ret = nrf_queue_push(&UARTE0RxBufferQueue, &pushBuffer);
      APP_ERROR_CHECK(ret);
    }

    //As recommended by nRF(Infocenter -> nRF52 Series -> nRF52840 -> Specs -> Peripherals -> UARTE -> Reception), release the data.
    nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
    nrf_drv_
    break;
  case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
    break;
  case NRF_LIBUARTE_ASYNC_EVT_OVERRUN_ERROR:
    break;
  default:
    break;
  }
}

Here's my application code:

void coreApplication(void) {
  char requestVersion[20] = {0x55, 0xA7, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x03, 0x01, 0x00, 0x00};

  UARTE0TransmitData(requestVersion, 16);

  while (1) {
    uint8_t receivedData[30] = {0};
    //If a queue is not empty, read the content and process the data.
    if (nrf_queue_is_empty(&UARTE0RxBufferQueue) == false) {

      UARTERxBufferStruct buf;
      nrf_queue_pop(&UARTE0RxBufferQueue, &buf);

      //Reset the queue
      nrf_queue_reset(&UARTE0RxBufferQueue);

      memcpy(receivedData, buf.data, buf.length);

      //Toggle the LED
      bsp_board_led_invert(0);

      UARTE0TransmitData(requestVersion, 16);
    }

    nrf_delay_ms(100);
    NRF_LOG_FLUSH();
  }
}

While I am able to successfully transmit and receive, I want to know how to clear the Rx Buffer and reset the write position after each response from the other device.

Currently, the buffer wold just overflow, which is undesirable in my application.

Thank you.

Parents
  • The libuarte provide lossless asynchronous transfer. If you have specific requirements to how to flushing buffers (I assume you have control of when you can do this safely in case it is in the middle of a tx/rx transfer) you will either need to modify the library or use a different uart example as a starting point. 

    I do not quite understand how you can overflow the libuarte, you can provide several buffers, and as long as you can handle incomming data before all buffers are all full you should be safe.

    Best regards,
    Kenneth

  • Hi ,

    Thank you for your response. I'm sorry that I didn't ask my question correctly. Here's what's happening:

    1. I initialised 3 buffers, each of 255 bytes wide.
    2. I sent some message to another system, which in-turn sends a 28 byte response.
    3. Everything works as expected. I get an event after 28 bytes until 9 times(252 bytes till now).
    4. After the 9th time, I again get an evert, as expected, because one buffer is filled. And then the buffer fills from start.

    What I want is this:

    1. After I process a response from the other device, I want to reset the write location of Rx buffer so that it starts from beginning.

    Can you please tell me how to achieve this?

Reply
  • Hi ,

    Thank you for your response. I'm sorry that I didn't ask my question correctly. Here's what's happening:

    1. I initialised 3 buffers, each of 255 bytes wide.
    2. I sent some message to another system, which in-turn sends a 28 byte response.
    3. Everything works as expected. I get an event after 28 bytes until 9 times(252 bytes till now).
    4. After the 9th time, I again get an evert, as expected, because one buffer is filled. And then the buffer fills from start.

    What I want is this:

    1. After I process a response from the other device, I want to reset the write location of Rx buffer so that it starts from beginning.

    Can you please tell me how to achieve this?

Children
  • You are right that NRF_LIBUARTE_ASYNC_EVT_RX_DATA comes on timeout and on buffer getting full, in your case the 9th message will be split on two NRF_LIBUARTE_ASYNC_EVT_RX_DATA events (instead of only one). I am not aware of any way to avoid that no. The risk of manipulation the buffers is that you may lose bytes.

  • Thank you Kenneth for the information.

    I finally got the code working the way I want. Here's the basic implementation that I will work on further:

    /*
     * Function: coreApplication
     * Params: None
     * returns: None
     * Description: Core Application Code
     */
    
    void coreApplication(void) {
      char requestVersion[20] = {0x55, 0xA7, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x03, 0x01, 0x00, 0x00};
    
      UARTE0TransmitData(requestVersion, 16);
    
      uint8_t receivedData[30] = {0xFF};
      size_t lastPopSize = 0;
    
      while (1) {
        //If a queue is not empty, read the content and process the data.
        if (nrf_queue_is_empty(&UARTE0RxBufferQueue) == false) {
    
          UARTERxBufferStruct popBuffer;
    
          //Pop the data from the queue.
          nrf_queue_pop(&UARTE0RxBufferQueue, &popBuffer);
          
          //Copy the data into the buffer and process it.
          memcpy(&receivedData[lastPopSize], popBuffer.data, popBuffer.length);
    
          //Update this variable.
          lastPopSize = popBuffer.length;
        } else {
          //Reset the queue
          nrf_queue_reset(&UARTE0RxBufferQueue);
    
          //Reset the index
          lastPopSize = 0;
    
          //Reset the buffer
          memset(receivedData, 0xFF, sizeof(receivedData));
    
          //Toggle LED
          bsp_board_led_invert(0);
          
          //Transmit the heartbeat packet.
          UARTE0TransmitData(requestVersion, 16);
          nrf_delay_ms(500);
        }
    
        NRF_LOG_FLUSH();
      }
    }

    I appreciate the help.

Related