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

NRFX_UARTE nrf52832 not receiving all bytes

Dear Nordic fellows,

I have a Rigado BMD-350 that can transmit correctly bytes to another device via UARTE, but who cannot receive data correctly.

I'm using SDK15.3.0, softdevice 6.1.1.

For debugging,  I disabled all the bluetooth stack, and I initialized only the UART module like this

void my_uarte_init()
{
  nrfx_uarte_config_t uart_conf;
  memset(&uart_conf,0,sizeof(uart_conf));
  uart_conf.baudrate           = NRF_UARTE_BAUDRATE_115200;//p_init->serial.baud;
  uart_conf.hwfc               = NRF_UARTE_HWFC_DISABLED;//p_init->serial.hwfc;
  uart_conf.interrupt_priority = APP_TIMER_CONFIG_IRQ_PRIORITY; // 7 
  uart_conf.p_context          = 0 ; //initialized by the nrfx init function
  uart_conf.parity             = NRF_UARTE_PARITY_EXCLUDED;//p_init->serial.parity;
  uart_conf.pselcts            = PIN_NOT_CONNECTED; //NOT_CONNECTED
  uart_conf.pselrts            = PIN_NOT_CONNECTED;
  uart_conf.pselrxd            = RX_PIN_NUMBER; //8
  uart_conf.pseltxd            = TX_PIN_NUMBER; //6

  m_uart_instance = (nrfx_uarte_t)NRFX_UARTE_INSTANCE(0); //initialize UARTE0. the cast is safe to do
  err_code = nrfx_uarte_init(&m_uart_instance,&uart_conf,handle_nrfx_event);

  memset(m_tmp_buffer,0,UART_RX_BUF_SIZE);
  memset(debug_buffer,0,UART_RX_BUF_SIZE);
  debug_buffer_idx=0;
  m_tmp_buf_idx=0;
  m_tmp_buffer[0]=0;
  nrfx_uarte_rx(&m_uart_instance,m_tmp_buffer,1);
}

Buffer are 250bytes long each.

For the debugging purposes, I receive only one byte per NRFX_UARTE_EVT_ENDRX event.

There are two problems:

  • the number of bytes received is not correct
  • Some messages are not received

This is the event handling function:

static void handle_nrfx_event(nrfx_uarte_event_t const *p_event ,void* p_context)
{
  my_uart_evt_t event;// set the status to "Processing command"
  switch(p_event->type)
  {
    case NRFX_UARTE_EVT_ERROR:
      event.type = UART_EVT_UART_ERROR;
      event.data.uart_err.err_code = p_event->data.error.error_mask;
      event.data.uart_err.data     = p_event->data.error.rxtx.p_data;
      event.data.uart_err.length    = p_event->data.error.rxtx.bytes;
      handler(&event);
      break;
    case NRFX_UARTE_EVT_TX_DONE://NRFX_UARTE_EVT_TX_DONE:
      event.type   = UART_EVT_CMD_SENT;
      handler(&event);  
      break;
    case NRFX_UARTE_EVT_RX_DONE://NRFX_UARTE_EVT_RX_DONE:
      //DEBUG
      memcpy(&(debug_buffer[debug_buffer_idx]),p_event->data.rxtx.p_data,p_event->data.rxtx.bytes);
      debug_buffer_idx += p_event->data.rxtx.bytes;
      nrfx_uarte_rx(&m_uart_instance,m_tmp_buffer,1);
      return;
  }
}

When I test the function, sending 11 bytes ({0xb0,0xb0,0x0b,0x87,0x02,0x54,0x45,0x53,0x54,0x30,0x34}) at 115200 baud, 8N1 the debug_buffer, which only stores received data, is as follows: (I bolded the changes on the debug_buffer)

0B 87 02 54 45 53 54 30 ...

After the second transmission of the same 11 bytes, the debug_buffer becomes:

0B 87 02 54 45 53 54 30 34 B0 B0 ...

After the third:

0B 87 02 54 45 53 54 30 34 B0 B0 0B 87 02 54 45 53 54 30 ...

If, instead, I use nrfx_uarte_rx(&m_uart_instance, m_tmp_buffer,11) the device won't display the first reception of data, but at the second transfer the debug_buffer will be

0B 87 02 54 45 53 54 30 34 B0 B0 ...

which is all the data, but with the first two bytes at the end

I think I initialized the nrfx_uarte module correctly, and I think the minimal receiving procedure is correct.

Does anyone have a suggestion on what the problem could be?

Edit: added SDK

  • Edit2:

    If I set it to receive 11 bytes, I get the bytes every two rounds

  • There may be another line of code required as the debug buffer index seems to grow forever in the code snippets above:

     debug_buffer_idx += p_event->data.rxtx.bytes;
     debug_buffer_idx %= LENGTH_OF_DEBUG_BUFFER;   // Ensure buffer wraps around

  • Hi, thanks for the answer.

    Right now I'm sending 11 bytes for each transmission, and I'm checking right after if all the data has been received.

    With this, I mean that an overflow is not occurring, because I'm sending at maximum 10 packets before resetting the nrf52832 (and reinitializing all variables).

  • Hi,

    I see that with 11-byte configuration, everything works as one could expect. Device doesn't know where is the start of your packet, so it breaks a stream into 11-byte chunks in random places... and there are bad news - you have no way to know how many bytes are already in the buffer until RX_DONE event is received. The solution depends on your case. If you can define a points in time when to start reception, for example as a response on transmitted command, you're lucky. If your messages can arrive at any time, a simplest solution is to set a timeout that will restart a reception... but sometimes you will lose data during restart procedure.

    I suggest a most reliable way - to configure UARTE in double-buffered mode: set ENDRX-STARTRX shortcut and switch buffers on RXSTARTED event, then configure a timer in counter mode that will increment on RXDRDY event, so your application will know how many bytes are in current buffer. In this case your logic will decide where is the start of a message - by unique header byte, by time difference between received bytes, or come up with your method.

  • Hi Dmitry, thanks

    I tried your first solution, but it didn't work and I will explain myself right now.

    I added some variables

    #define UART_RX_BUF_SIZE 250
    static uint8_t          m_uart_rx_buffer[UART_RX_BUF_SIZE];
    static uint8_t          m_uart_rx_buffer_index;
    static uint8_t          m_tmp_buffer[UART_RX_BUF_SIZE];
    static uint8_t          m_tmp_buffer1[UART_RX_BUF_SIZE];
    
    static uint8_t*         m_primary_buf   = m_tmp_buffer;
    static uint8_t*         m_secondary_buf = m_tmp_buffer1;
    static bool             is_currently_primary_buffer_m_tmp_buffer = true;
    

    And a function that starts the reception

    static void start_rx(uint8_t len)
    {
      //start rx
      nrfx_uarte_rx(&m_uart_instance,m_primary_buf,len);
      nrfx_uarte_rx(&m_uart_instance,m_secondary_buf,len);
    
      //invert primary buffer with secondary buffer for next round
      if(is_currently_primary_buffer_m_tmp_buffer)
      {
        //invert the boolean
        is_currently_primary_buffer_m_tmp_buffer = !is_currently_primary_buffer_m_tmp_buffer;
        //switch the pointer of primary buffer with secondary buffer
        m_primary_buf   = m_tmp_buffer1;
        m_secondary_buf = m_tmp_buffer;
      }
      else // currently m_primary_buf = m_tmp_buffer_1
      {
        //invert the boolean
        is_currently_primary_buffer_m_tmp_buffer = !is_currently_primary_buffer_m_tmp_buffer;
        //switch the pointer of primary buffer with secondary buffer
        m_primary_buf   = m_tmp_buffer;
        m_secondary_buf = m_tmp_buffer1;
      }
    }

    the function reset_uart() became

    void reset_uart()
    {
      m_uart_rx_buffer_index=0;
      m_uart_rx_buffer[0]=0;
      start_rx(11);
    }
    

    The debugging function that handles the NRFX_UARTE_EVT_RX_DONE event.

    static void handle_nrfx_event(nrfx_uarte_event_t const *p_event ,void* p_context)
    {
      // handle events. all are listed, it shouldn't go to the default case
      switch(p_event->type)
      {
        case NRFX_UARTE_EVT_ERROR:
          break;
        case NRFX_UARTE_EVT_TX_DONE://NRFX_UARTE_EVT_TX_DONE:
          break;
        case NRFX_UARTE_EVT_RX_DONE://NRFX_UARTE_EVT_RX_DONE:
          //DEBUG
          memcpy(&(debug_buffer[debug_buffer_idx]),p_event->data.rxtx.p_data,p_event->data.rxtx.bytes);
          debug_buffer_idx += p_event->data.rxtx.bytes;
          start_rx(11);
          return;
      }
    }

    The result is always:

    • First sending of 11 bytes is not received
    • Second sending of the 11 bytes results in 0B 87 02 54 45 53 54 30 34 B0 B0  (last 2 bytes should be the first ones)
    • All odd sendings result in a non-event
    • All even sendings result in a adding of the debug_buffer of the sequence 0B 87 02 54 45 53 54 30 34 B0 B0  
Related