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

STOPRX task of UARTE during reception of bytes

Hi all

Previously, I used the nRF52832 with the interrupt-driven UART at 1Mbaud. But due to SoftDevice interrupts that blocked the UART-RX-IRQ for more than 6 bytes, I tried to use the UARTE with EasyDMA.

I need to receive an arbitrary amount of bytes and can therefore not wait until the RX buffer is filled. So, I tried the suggestion from this thread, by enabling the shortcut between ENDRX and STARTRX and by triggering the STOPRX task in a certain interval.

Now, I check in a certain interval if the RXDRDY event occurred. If yes, I set the second RX buffer as the active buffer and trigger afterwards the STOPRX task. After the ENDRX event occurred, I copy the amount of received bytes.

My code looks like this:

void UART_init(void)
{
   // Disable UART
   NRF_UARTE0->ENABLE = (UARTE_ENABLE_ENABLE_Disabled << UARTE_ENABLE_ENABLE_Pos);

   // Set baudrate
   NRF_UARTE0->BAUDRATE = UARTE_BAUDRATE_BAUDRATE_Baud1M;

   // Disable flow control and parity check
   NRF_UARTE0->CONFIG = (UART_DISABLE_HW_FLOW | UART_EXCLUDE_PARITY);

   // Set TX and RX pin
   NRF_UARTE0->PSEL.TXD = HWH_HIF_MISO_TX;
   NRF_UARTE0->PSEL.RXD = HWH_HIF_MOSI_RX;

   // Set the TX and RX buffers
   gRX_buf_1_active = true;
   NRF_UARTE0->RXD.PTR = (uint32_t)gRX_buf_1;
   NRF_UARTE0->TXD.PTR = (uint32_t)gTX_buf;
   NRF_UARTE0->RXD.MAXCNT = 255;
   NRF_UARTE0->TXD.MAXCNT = 0;

   // Clear all possible pending events
   NRF_UARTE0->EVENTS_RXDRDY = 0;
   NRF_UARTE0->EVENTS_ENDRX = 0;
   NRF_UARTE0->EVENTS_TXDRDY = 0;
   NRF_UARTE0->EVENTS_ENDTX = 0;
   NRF_UARTE0->EVENTS_ERROR = 0;
   NRF_UARTE0->EVENTS_RXTO = 0;
   NRF_UARTE0->EVENTS_RXSTARTED = 0;
   NRF_UARTE0->EVENTS_TXSTARTED = 0;
   NRF_UARTE0->EVENTS_TXSTOPPED = 0;

   // Clear Interrupts
   NRF_UARTE0->INTENCLR = 0xFFFFFFFFUL;

   // Enable shortcut bwetwen ENDRX and STARTRX
   NRF_UARTE0->SHORTS = UARTE_SHORTS_ENDRX_STARTRX_Enabled << UARTE_SHORTS_ENDRX_STARTRX_Pos;

   // Enable UART
   NRF_UARTE0->ENABLE = (UARTE_ENABLE_ENABLE_Enabled << UARTE_ENABLE_ENABLE_Pos);

   // Start RX
   NRF_UARTE0->TASKS_STARTRX = 1;
}

void UART_handle(uint8_t * const pData, size_t const data_size)
{
   uint32_t rx_length;
   uint32_t i;

   if (NRF_UARTE0->EVENTS_RXDRDY)
   {
      // Switch the RX buffer
      if (gRX_buf_1_active)
      {
         NRF_UARTE0->RXD.PTR = (uint32_t)gRX_buf_2;
         NRF_UARTE0->RXD.MAXCNT = 255;
         gRX_buf_1_active = false;
      }
      else
      {
         NRF_UARTE0->RXD.PTR = (uint32_t)gRX_buf_1;
         NRF_UARTE0->RXD.MAXCNT = 255;
         gRX_buf_1_active = true;
      }

      // Stop the reception
      // RX is restarted after the ENDRX event due to shortcut
      NRF_UARTE0->EVENTS_ENDRX = 0;
      NRF_UARTE0->TASKS_STOPRX = 1;
      while (NRF_UARTE0->EVENTS_ENDRX == 0) {}
      NRF_UARTE0->EVENTS_ENDRX = 0;
      NRF_UARTE0->EVENTS_RXDRDY = 0;

      // Copy the received bytes from the used RX buffer
      rx_length = NRF_UARTE0->RXD.AMOUNT;
      for (i = 0; i < rx_length; i++)
      {
         if (i < data_size)
         {
            if (gRX_buf_1_active) {pData[i] = gRX_buf_2[i];}
            else                  {pData[i] = gRX_buf_1[i];}
         }
      }
   }
}

I assumed that due to the enabled shortcut the reception should immediately switch to the second buffer. But it seems that I lose some bytes (or get corrupted bytes) when the STOPRX task is executed during the reception of bytes. E.g. the byte stream "00 11 22 33 44 55 66 77 88 99 AA BB CC DD EE FF" is sent to the nRF52, but I receive in RX_BUF_1 the bytes "00 11 22 33 44 55 66" and in RX_BUF_2 the bytes "2C DB DD EE FF". Here is a trace from the flow:

Should the STOPRX task not be triggered during the reception of bytes or am I missing something? Do you know this problem?

Many thanks in advance.

Best regards

Related