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

  • //start rx
    nrfx_uarte_rx(&m_uart_instance,m_primary_buf,len);
    nrfx_uarte_rx(&m_uart_instance,m_secondary_buf,len);

    This won't work. For double-buffered scheme, you need to switch buffers on RXSTARTED event. I don't know whether SDK libraries support this mode, I have implemented it with direct programming of UARTE.

    void GNSS_UART_IRQHandler(void)
    {
    	if (COMM_UART->EVENTS_RXSTARTED)
    	{
    		COMM_UART->EVENTS_RXSTARTED = 0;
    		rxptr = (rxptr == uart_rx_buffer) ? uart_rx_buffer+UART_RX_BUFFER_SIZE/2 : uart_rx_buffer;
    		COMM_UART->RXD.PTR = (u32) rxptr;
    		COMM_UART->RXD.MAXCNT = UART_RX_BUFFER_SIZE / 2;
    	}
    	...
    }
    
    void gnss_uart_init(int baudrate, gnss_rx_callback rxcb)
    {
        ...
        rxptr = uart_rx_buffer;
    	COMM_UART->RXD.MAXCNT = UART_RX_BUFFER_SIZE / 2;
    	COMM_UART->RXD.PTR = (u32) rxptr;
    	COMM_UART->SHORTS = (1 << 5); // endrx-startrx
    	COMM_UART->ENABLE = 0x08; // enable
    	COMM_UART->EVENTS_RXSTARTED = 0;	
    	COMM_UART->TASKS_STARTRX = 1;
    	...
    }

  • Hi Dmitry, I tried your solution and the problem persists.

    The code I used is

    void UARTE0_UART0_IRQHandler(void)
    {
      if (m_uart_instance.p_reg->EVENTS_RXSTARTED)
      {
        m_uart_instance.p_reg->EVENTS_RXSTARTED = 0; // clear register
        m_uart_instance.p_reg->RXD.PTR = (uint32_t) m_secondary_buf;
        m_uart_instance.p_reg->RXD.MAXCNT = UART_RX_BUF_SIZE;
          //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;
        }
      }
      if(m_uart_instance.p_reg->EVENTS_RXDRDY)
      {
        m_uart_instance.p_reg->EVENTS_RXDRDY=0; //clear register
        m_bytes_received++;
        uint32_t amount = m_uart_instance.p_reg->RXD.AMOUNT;
      }
      if(m_uart_instance.p_reg->EVENTS_ENDRX)
      {
        m_uart_instance.p_reg->EVENTS_ENDRX=0; //clear register
        nrfx_uarte_event_t evt;
        evt.type = NRFX_UARTE_EVT_RX_DONE;
        evt.data.rxtx.bytes  = m_uart_instance.p_reg->RXD.AMOUNT;
        evt.data.rxtx.p_data = m_secondary_buf;
        handle_nrfx_event(&evt,NULL);
        //m_bytes_received++;
        uint32_t amount = m_uart_instance.p_reg->RXD.AMOUNT;
      }
    
      if(m_uart_instance.p_reg->EVENTS_ERROR)
      {
        err_code = m_uart_instance.p_reg->ERRORSRC;
        m_uart_instance.p_reg->ERRORSRC = err_code;
        m_uart_instance.p_reg->EVENTS_ERROR=0; //clear register
        uint32_t amount = m_uart_instance.p_reg->RXD.AMOUNT;
        nrfx_uarte_event_t evt;
        evt.type = NRFX_UARTE_EVT_ERROR;
        evt.data.error.error_mask = err_code;
        evt.data.error.rxtx.bytes=amount;
        evt.data.error.rxtx.p_data = m_secondary_buf;
        handle_nrfx_event(&evt,NULL);
      }
      if(m_uart_instance.p_reg->EVENTS_ENDTX)
      {
        nrfx_uarte_event_t event;
        event.type = NRFX_UARTE_EVT_TX_DONE;
        handle_nrfx_event(&event,NULL);
      }
    }

    And I'm just counting the bytes I received, by looking at the variable m_bytes_received

    The init function is

    void uart_msg_init(uart_msg_init_t *p_init)
    {
      if(p_init->handler==0)
      {
        APP_ERROR_CHECK(NRF_ERROR_INVALID_DATA);
      }
      handler = p_init->handler;
      //CONFIG uarte 
      m_uart_instance = (nrfx_uarte_t)NRFX_UARTE_INSTANCE(0); //initialize UARTE0. the cast is safe to do
     /** APPLY CONFIG in nrfx_uarte.c*/
      //set tx pin as output pin
      nrf_gpio_pin_set(TX_PIN_NUMBER);
      nrf_gpio_cfg_output(TX_PIN_NUMBER);
      //set rx pin as input pin
      nrf_gpio_cfg_input(RX_PIN_NUMBER, NRF_GPIO_PIN_NOPULL);
      m_uart_instance.p_reg->BAUDRATE = NRF_UARTE_BAUDRATE_115200;
      m_uart_instance.p_reg->PSEL.CTS = NRF_UARTE_PSEL_DISCONNECTED;
      m_uart_instance.p_reg->PSEL.RTS = NRF_UARTE_PSEL_DISCONNECTED;
      m_uart_instance.p_reg->CONFIG   = (uint32_t)NRF_UARTE_PARITY_EXCLUDED | (uint32_t)NRF_UARTE_HWFC_DISABLED;
      m_uart_instance.p_reg->PSEL.RXD = RX_PIN_NUMBER;
      m_uart_instance.p_reg->PSEL.TXD = TX_PIN_NUMBER;
    /** END APPLY CONFIG*/
    
      /** INTERRUPT ENABLE */
      m_uart_instance.p_reg->EVENTS_ENDRX     = 0;
      m_uart_instance.p_reg->EVENTS_ENDTX     = 0;
      m_uart_instance.p_reg->EVENTS_ERROR     = 0;
      m_uart_instance.p_reg->EVENTS_RXTO      = 0;
      m_uart_instance.p_reg->EVENTS_RXSTARTED = 0;
      m_uart_instance.p_reg->SHORTS           = (1<<5);//NRF_UARTE_SHORT_ENDRX_STARTRX;
      m_uart_instance.p_reg->TASKS_STARTRX    = 1; 
      m_uart_instance.p_reg->INTENSET         = (NRF_UARTE_INT_ENDRX_MASK |NRF_UARTE_INT_ENDTX_MASK | NRF_UARTE_INT_RXDRDY_MASK|
                                               NRF_UARTE_INT_RXSTARTED_MASK | NRF_UARTE_INT_ERROR_MASK | NRF_UARTE_INT_RXTO_MASK);
     
      /** INTERRUPT ENABLE */
      NVIC_SetPriority(UARTE0_UART0_IRQn,APP_TIMER_CONFIG_IRQ_PRIORITY);
      NVIC_EnableIRQ(UARTE0_UART0_IRQn);
      m_uart_instance.p_reg->ENABLE = UARTE_ENABLE_ENABLE_Enabled; // ENABLE UARTE
      //END of INIT
      memset(m_tmp_buffer,0,UART_RX_BUF_SIZE);
      m_bytes_received=0;
      reset_uart();
      debug_buffer_idx=0;
    }

    The number of bytes is always less than 9 per packet.

    Did I make some mistake enabling the interrupts?

  • Ok, I solved.

    In the end, the error was on the other side. Even though I was transmitting bytes, and the oscilloscope decoded them correctly, the NRF52832 didn't manage to decode them, and did not raise any error in the UARTE registers

Related