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

Libuarte is not working with baud rates other than 115200

Hi Team,

We are using the Libuarte driver for our data transfer purpose with the Baudrate of 115200 and  timeout of 100usec.

        nrf_libuarte_async_config..timeout_us = 100.

With the above configuration it is working fine and when we change the Baudrate to 9600 it is not working. And we changed the timeout value to below value, but with this we are receiving the data but not fully means ,if we are sending the 72 bytes we are receiving only 51 bytes.

         nrf_libuarte_async_config..timeout_us = 1500 

Is there any dependency with timeout and Baudrate values and how to choose this timeout value for different baudrates. Is there any other settings we need to change when we change the baudrate. Is there any calculation for this timeout and other settings.

Could you any one help us on this issue, we need to deliver the code Customer with the baudrate of 9600, but it is not working.

Here with i am sharing my Code:

NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 1, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 512, 3);

void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
{
    nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
   
    ret_code_t ret = NRF_SUCCESS;
    buffer_t buf;
    
    switch (p_evt->type)
    {
        case NRF_LIBUARTE_ASYNC_EVT_ERROR:
              error_flag++;
              break;
            
        case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
   
            buf.p_data = p_evt->data.rxtx.p_data;
            buf.length = p_evt->data.rxtx.length;
                
            Update_Rx_Buf(buf.p_data, buf.length);
            
            //ret = nrf_queue_push(&m_buf_queue, &buf);
            
            if(NRF_SUCCESS == ret)
            {
              rx_done_flag++;
              nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
            }
            break;
            
        case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
            
            tx_done_flag++;
#if 0
            if (m_loopback_phase)
            {
                nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
                
                if (!nrf_queue_is_empty(&m_buf_queue))
                {
                    buffer_t buf;
                    ret = nrf_queue_pop(&m_buf_queue, &buf);
                    APP_ERROR_CHECK(ret);
                    UNUSED_RETURN_VALUE(nrf_libuarte_async_tx(p_libuarte, buf.p_data, buf.length));
                }
            }
#endif
            break;
        default:
            break;
    }
}


void hal_UARTE_Init(void)
{
  ret_code_t err_code;
  
  nrf_libuarte_async_config_t nrf_libuarte_async_config = {
            .tx_pin     = TX_PIN_NUMBER,
            .rx_pin     = RX_PIN_NUMBER,
            .baudrate   = NRF_UARTE_BAUDRATE_9600,
            .parity     = NRF_UARTE_PARITY_EXCLUDED,
            .hwfc       = NRF_UARTE_HWFC_DISABLED,
            .timeout_us = 1700,
            .int_prio   = APP_IRQ_PRIORITY_LOW,
            .pullup_rx  = NRF_GPIO_PIN_PULLUP
    };

    err_code = nrf_libuarte_async_init(&libuarte, &nrf_libuarte_async_config, uart_event_handler, (void *)&libuarte);

    APP_ERROR_CHECK(err_code);

    nrf_libuarte_async_enable(&libuarte);
    
    err_code = nrf_libuarte_async_tx(&libuarte, "Host UARTE", 11);

}

void hal_nrf_libuarte_async_tx(uint8_t * p_data, uint16_t length)
{
  ret_code_t ret;

   ret = nrf_libuarte_async_tx(&libuarte, p_data, length);
      
   if((NRF_SUCCESS != ret) && (NRF_ERROR_BUSY != ret))
   {
      APP_ERROR_CHECK(ret);
   }
}

Parents
  • I suggest to set the timeout value to more than 2x transferring 1byte (including start and stop bit). So for 9600baud that is 2 * (1+8+1) / 9600 = 2080us or more. I can't see how that should fail.

    Why do you have a nrf_libuarte_async_rx_free() in both TX and RX? Edit: I guess the second is not used due to the #if 0.

  • Hi Kenneth,

    Thanks for  your valuable reply.  Need more clarity on "Libuarte" working, means how it is utilizing the Byte counter Timer(Timer0) and Timeout counter Timer(RTC1) along with Easy DMA.

      NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 1, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);

    Case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:

     Once data is Received in Rx Event, after updating to Application buffer  I am calling this free function.

                           nrf_libuarte_async_rx_free() 

    case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
            Not doing anything, only incrementing the counter.

    Our Issues Are:

    1. When we are sending the 200  bytes  as first packet and 100 bytes in Second packet , receiving the first 200 bytes properly and for second 100 i am receiving 55 bytes as one packet and 45 bytes in Second packet, not receiving all at a time.

    What We observed is the Uarte buffer size is 255 bytes, first time it is Receiving 200 bytes as single packet and for second 100 bytes it is splitting the packets as per UARTE buffer size (255) means 200 + 100   = 200 + 55 + 45. Total 300 bytes it is Receiving in 3 iterations instead of 2 iterations.

    So how to avoid this packet splitting, once i Send the 200 bytes i want to clear the Rx Buffer, so that for second packet (100 Bytes) it will Receive all bytes as Single Packet.

    Is there any way to clear pointer or Buffer after Every packet reception.

    2. Some times when we integrate our code with other applications not receiving all the bytes properly but same application is working fine with other apps.

    3. Is there any sample application code for libuarte(not example code which is in Nordic SDK) which will cover the all the scenarios.

    4. Is there any other changes or settings are required apart from Time out setting  like in SDK Config file or in UARTE Driver layer to support Multiple Baud rates in application layer.

    Regards,

    Srinivas.V

      

Reply
  • Hi Kenneth,

    Thanks for  your valuable reply.  Need more clarity on "Libuarte" working, means how it is utilizing the Byte counter Timer(Timer0) and Timeout counter Timer(RTC1) along with Easy DMA.

      NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 1, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);

    Case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:

     Once data is Received in Rx Event, after updating to Application buffer  I am calling this free function.

                           nrf_libuarte_async_rx_free() 

    case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
            Not doing anything, only incrementing the counter.

    Our Issues Are:

    1. When we are sending the 200  bytes  as first packet and 100 bytes in Second packet , receiving the first 200 bytes properly and for second 100 i am receiving 55 bytes as one packet and 45 bytes in Second packet, not receiving all at a time.

    What We observed is the Uarte buffer size is 255 bytes, first time it is Receiving 200 bytes as single packet and for second 100 bytes it is splitting the packets as per UARTE buffer size (255) means 200 + 100   = 200 + 55 + 45. Total 300 bytes it is Receiving in 3 iterations instead of 2 iterations.

    So how to avoid this packet splitting, once i Send the 200 bytes i want to clear the Rx Buffer, so that for second packet (100 Bytes) it will Receive all bytes as Single Packet.

    Is there any way to clear pointer or Buffer after Every packet reception.

    2. Some times when we integrate our code with other applications not receiving all the bytes properly but same application is working fine with other apps.

    3. Is there any sample application code for libuarte(not example code which is in Nordic SDK) which will cover the all the scenarios.

    4. Is there any other changes or settings are required apart from Time out setting  like in SDK Config file or in UARTE Driver layer to support Multiple Baud rates in application layer.

    Regards,

    Srinivas.V

      

Children
  • It sounds to me that the peer that is transmitting UART data to the nRF52840 sometimes have gaps in the communication that sometimes is larger than the configured timeout (1500us). When a timeout occurs it will pass the received data to the application while waiting for more data, so you will need to either increase the timeout (for instance by study the UART data on an logic analyzer to find suitable timeout value) or you will need to look into the implementation on the peer (for instance to reduce the gaps between UART bytes).

    Kenneth

  • Hi Kenneth,

    Once again Thanks for your timely reply.

    I tried with increased timeout value as well but some times we are able to receive the data but some times not.

    Is that something i need to do in Libuarte side, like modifying the driver side or Application fine tuning.

    If you people have any proven code with Libuarte with Asynchronous mode, i will use the same and i will prove that Peer side having some gaps.

    Even i tried with Serial terminals like TeraTerm , RealTerm as well but same behavior, is that some thing we need to look into Libuarte Side.

    Once again i am sharing my code, Could you please suggest changes which are required in code:

    Is there any way to point the Rx Buffer to starting pointer instead of offset index, means to back to 0th index of Buffer instead of pointing to offset Index.

      

    NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 1, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 255, 3);
    
    void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
    {
        nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
       
        ret_code_t ret = NRF_SUCCESS;
        buffer_t buf;
        
        switch (p_evt->type)
        {
            case NRF_LIBUARTE_ASYNC_EVT_ERROR:
                  error_flag++;
                  break;
                
            case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
       
                buf.p_data = p_evt->data.rxtx.p_data;
                buf.length = p_evt->data.rxtx.length;
                
                //Once we received the all the data updating to Application buf for processing. 
                Update_Rx_Buf(buf.p_data, buf.length); 
                
                //Once data is updated to App buf clearing the Libuarte pointer.
                if(NRF_SUCCESS == ret)
                {
                  rx_done_flag++;
                  nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
                }
                break;
                
            case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
                
                tx_done_flag++;
                break;
                
            default:
                break;
        }
    }
    
    
    
    void hal_UARTE_Init(void)
    {
      ret_code_t err_code;
      
      nrf_libuarte_async_config_t nrf_libuarte_async_config = {
                .tx_pin     = TX_PIN_NUMBER,
                .rx_pin     = RX_PIN_NUMBER,
                .baudrate   = NRF_UARTE_BAUDRATE_9600,
                .parity     = NRF_UARTE_PARITY_EXCLUDED,
                .hwfc       = NRF_UARTE_HWFC_DISABLED,
                .timeout_us = 2084,  //2400    2*(1+ 8 + 1) / 9600
                .int_prio   = APP_IRQ_PRIORITY_LOW,
                .pullup_rx  = NRF_GPIO_PIN_PULLUP
        };
    
        err_code = nrf_libuarte_async_init(&libuarte, &nrf_libuarte_async_config, uart_event_handler, (void *)&libuarte);
    
        APP_ERROR_CHECK(err_code);
    
        nrf_libuarte_async_enable(&libuarte);
        
        err_code = nrf_libuarte_async_tx(&libuarte, "Host UARTE", 11);
    
    }
    
    
    void hal_nrf_libuarte_async_tx(uint8_t * p_data, uint16_t length)
    {
      ret_code_t ret;
    
       ret = nrf_libuarte_async_tx(&libuarte, p_data, length);
          
       if((NRF_SUCCESS != ret) && (NRF_ERROR_BUSY != ret))
       {
          APP_ERROR_CHECK(ret);
       }
    }
    
    bool DataReceived()
    {
      bool returner = false;
      
      if(RxBuffer[ORP_PACKET_LENGTH] != 0x00)    /** Received teh Lenth byte or first byte of the packet */
      {
        returner = true;
    #if 1
        int i = 0;
        while(ReceiveIndex < RxBuffer[ORP_PACKET_LENGTH])  /** Waiting for Total No of bytes Receiption */
        {
          i++;
          if(i > 30000)                                   /** Maximum no of bytes we can recieve in one packet is 128, SO maximum we need to wait till that time.*/
          {
            //RxBuffer[ORP_PACKET_LENGTH] = 0x00;
            memset(RxBuffer, 0x00, sizeof(RxBuffer));
            returner = false;                             //Fails and breaks out of while loop
            break;
          }
        }                                                 //Wait to get all data
    #endif
      }
      return returner;
    }

    Regards,

    Srinivas.V

Related