(Libuartes) Reset nRF when receive RX buffer from computer

Hi, I'm using the example libuartes of nrf5 sdk ver16. This example worked (receive data from computer(Hercules) and send it to back)
I have some customize that is when nRF received data from computer, it will send any data I want back to the computer.
Eg: my computer send "hello" and nrf after receive"hello" it will send to back "nice to meet you". 
But after I send some line "hello" from my computer and receive"nice to meet you" => nRF reset. I think TX (save in somewhere I don't know overflowed)

NRF_LIBUARTE_ASYNC_DEFINE(libuarte1, 0, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 100, 3);
NRF_LIBUARTE_ASYNC_DEFINE(libuarte2, 1, 2, 2, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 100, 3);

static uint8_t text[] = "nrf reset =============\r\n";
static uint8_t textAT1_Uart1[] = "nice to meet you\r\n";
static uint8_t textReceived[100];
static volatile bool m_loopback_phase;

typedef struct
{
    uint8_t *p_data;
    uint32_t length;
} buffer_t;

NRF_QUEUE_DEF(buffer_t, m_buf_queue, 10, NRF_QUEUE_MODE_NO_OVERFLOW);

//Function to send via UART1
void send_UART_1(char *sdata, int len)
{
    ret_code_t ret;
    ret = nrf_libuarte_async_tx(&libuarte1, sdata, len);
    APP_ERROR_CHECK(ret);
}

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;

    switch (p_evt->type)
    {
    case NRF_LIBUARTE_ASYNC_EVT_ERROR:
        break;
    case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
        sprintf(textReceived, "%s", p_evt->data.rxtx.p_data);
        // send_UART_1(textAT1_Uart1, sizeof(textAT1_Uart1));
        // ret = nrf_libuarte_async_tx(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
        ret = nrf_libuarte_async_tx(p_libuarte, textAT1_Uart1, sizeof(textAT1_Uart1));
        if (ret == NRF_ERROR_BUSY)
        {
            buffer_t buf = {
                .p_data = p_evt->data.rxtx.p_data,
                .length = p_evt->data.rxtx.length,
            };

            ret = nrf_queue_push(&m_buf_queue, &buf);
            APP_ERROR_CHECK(ret);
        }
        else
        {
            APP_ERROR_CHECK(ret);
        }
        bsp_board_led_invert(1);
        m_loopback_phase = true;
        break;
    case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
        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));
            }
        }
        bsp_board_led_invert(2);
        break;
    default:
        break;
    }
}

 int main(void)
  {
      bsp_board_init(BSP_INIT_LEDS);
      ret_code_t ret = nrf_drv_clock_init();
      APP_ERROR_CHECK(ret);
      nrf_drv_clock_lfclk_request(NULL);
      ret_code_t err_code = NRF_LOG_INIT(app_timer_cnt_get);
      APP_ERROR_CHECK(err_code);

      NRF_LOG_DEFAULT_BACKENDS_INIT();

      nrf_libuarte_async_config_t nrf_libuarte_async_config1 = {
          .tx_pin = TX_PIN_NUMBER1,
          .rx_pin = RX_PIN_NUMBER1,
          .baudrate = NRF_UARTE_BAUDRATE_115200,
          .parity = NRF_UARTE_PARITY_EXCLUDED,
          .hwfc = NRF_UARTE_HWFC_DISABLED,
          .timeout_us = 100,
          .int_prio = APP_IRQ_PRIORITY_LOW};

      nrf_libuarte_async_config_t nrf_libuarte_async_config2 = {
          .tx_pin = TX_PIN_NUMBER2,
          .rx_pin = RX_PIN_NUMBER2,
          .baudrate = NRF_UARTE_BAUDRATE_115200,
          .parity = NRF_UARTE_PARITY_EXCLUDED,
          .hwfc = NRF_UARTE_HWFC_DISABLED,
          .timeout_us = 100,
          .int_prio = APP_IRQ_PRIORITY_LOW};

      err_code = nrf_libuarte_async_init(&libuarte1, &nrf_libuarte_async_config1, uart_event_handler, (void *)&libuarte1);
      err_code = nrf_libuarte_async_init(&libuarte2, &nrf_libuarte_async_config2, uart_event_handler, (void *)&libuarte2);

      APP_ERROR_CHECK(err_code);
      nrf_libuarte_async_enable(&libuarte1);
      nrf_libuarte_async_enable(&libuarte2);
      APP_ERROR_CHECK(err_code);
      send_UART_1(text, sizeof(text));

      while (true)
      {
          NRF_LOG_FLUSH();
      }
  }


here is my code just edit line 37 into 38. But my code not work smoothy like the example. Please give me some hints. I really appreciate about that.
Best Regart,
Tam

Parents
  • Hello Tam,

    Resets are almost always done by the app error handler when a runtime error has been detected (see Error module). Can you try to set the DEBUG flag and see where the error occurred?

    Note: if you use segger embedded studio, it's sufficient to select the "Debug" build configuration. This will set the flag and make the error handler print a crash log containing the filename and line number of where the error occurred.

    Debug configuration selected from the drop-down menu in the project explorer view:

    Best regards,

    Vidar

  • Hi Berg,
    Thanks for your suggestion. But I don't know how to test UART in Debug mode. Can you give me some hints ?
    Debug->Go->Continue Excution that is all I did and I got this problem when I get the error

  • Hi,

    You are doing it correctly, but I can't see the full error log here:

    This line includes the file name and line number of where the error occured.

  • Hi Berg,

    Here is the full error log. I researched for this error and I found a soulution that is  add nrf_libuarte_async_rx_free() in the UART callback handler to free RX buffer, but in my case I used this function but I'm not sure if I free correctly buffer name and its length

  • Hi,

    Are you calling nrf_libuarte_async_rx_free() from multiple places, or only when you are done processing the UART RX DATA from NRF_LIBUARTE_ASYNC_EVT_RX_DATA? Can you post relevant code here?

  • Hi, I just call nrf_libuarte_async_rx_free() once in line 59.
    As I mentioned above on my question, here is my code just edit line 37 (libuarte example) into 38.

    Here is my project sequence
    step 1. I receive any text from my computer
    step 2. my nRF will save it to the buffer textReceived in line 35 => sprintf(textReceived, "%s", p_evt->data.rxtx.p_data);
    step 3. my nRF will send textAT1 back to computer in line 38 => nrf_libuarte_async_tx(p_libuarte, textAT1_Uart1, sizeof(textAT1_Uart1));
    step 4. NRF_LIBUARTE_ASYNC_EVT_TX_DONE will be call when I send textAT1 in step 3 in this event I call nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length); in line 59
    but I don't know p_evt->data.rxtx.p_data, p_evt->data.rxtx.length correctly ? so Can you help me at this point ? I think this is the main reason caused my prolem

    In the libuates example, this is different from my project at step 3 => instead of calling nrf_libuarte_async_tx(p_libuarte, textAT1_Uart1, sizeof(textAT1_Uart1)); the example call nrf_libuarte_async_tx(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length); and the code work well it has no any problems.

    In my case I used this function nrf_libuarte_async_tx(p_libuarte, textAT1_Uart1, sizeof(textAT1_Uart1)) but I'm not sure if I free correctly buffer name and its length in this call nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);


    NRF_LIBUARTE_ASYNC_DEFINE(libuarte1, 0, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 100, 3);
    NRF_LIBUARTE_ASYNC_DEFINE(libuarte2, 1, 2, 2, NRF_LIBUARTE_PERIPHERAL_NOT_USED, 100, 3);
    
    static uint8_t text[] = "nrf reset =============\r\n";
    static uint8_t textAT1_Uart1[] = "nice to meet you\r\n";
    static uint8_t textReceived[100];
    static volatile bool m_loopback_phase;
    
    typedef struct
    {
        uint8_t *p_data;
        uint32_t length;
    } buffer_t;
    
    NRF_QUEUE_DEF(buffer_t, m_buf_queue, 10, NRF_QUEUE_MODE_NO_OVERFLOW);
    
    //Function to send via UART1
    void send_UART_1(char *sdata, int len)
    {
        ret_code_t ret;
        ret = nrf_libuarte_async_tx(&libuarte1, sdata, len);
        APP_ERROR_CHECK(ret);
    }
    
    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;
    
        switch (p_evt->type)
        {
        case NRF_LIBUARTE_ASYNC_EVT_ERROR:
            break;
        case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
            sprintf(textReceived, "%s", p_evt->data.rxtx.p_data);
            // send_UART_1(textAT1_Uart1, sizeof(textAT1_Uart1));
            // ret = nrf_libuarte_async_tx(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
            ret = nrf_libuarte_async_tx(p_libuarte, textAT1_Uart1, sizeof(textAT1_Uart1));
            if (ret == NRF_ERROR_BUSY)
            {
                buffer_t buf = {
                    .p_data = p_evt->data.rxtx.p_data,
                    .length = p_evt->data.rxtx.length,
                };
    
                ret = nrf_queue_push(&m_buf_queue, &buf);
                APP_ERROR_CHECK(ret);
            }
            else
            {
                APP_ERROR_CHECK(ret);
            }
            bsp_board_led_invert(1);
            m_loopback_phase = true;
            break;
        case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
            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));
                }
            }
            bsp_board_led_invert(2);
            break;
        default:
            break;
        }
    }
    
     int main(void)
      {
          bsp_board_init(BSP_INIT_LEDS);
          ret_code_t ret = nrf_drv_clock_init();
          APP_ERROR_CHECK(ret);
          nrf_drv_clock_lfclk_request(NULL);
          ret_code_t err_code = NRF_LOG_INIT(app_timer_cnt_get);
          APP_ERROR_CHECK(err_code);
    
          NRF_LOG_DEFAULT_BACKENDS_INIT();
    
          nrf_libuarte_async_config_t nrf_libuarte_async_config1 = {
              .tx_pin = TX_PIN_NUMBER1,
              .rx_pin = RX_PIN_NUMBER1,
              .baudrate = NRF_UARTE_BAUDRATE_115200,
              .parity = NRF_UARTE_PARITY_EXCLUDED,
              .hwfc = NRF_UARTE_HWFC_DISABLED,
              .timeout_us = 100,
              .int_prio = APP_IRQ_PRIORITY_LOW};
    
          nrf_libuarte_async_config_t nrf_libuarte_async_config2 = {
              .tx_pin = TX_PIN_NUMBER2,
              .rx_pin = RX_PIN_NUMBER2,
              .baudrate = NRF_UARTE_BAUDRATE_115200,
              .parity = NRF_UARTE_PARITY_EXCLUDED,
              .hwfc = NRF_UARTE_HWFC_DISABLED,
              .timeout_us = 100,
              .int_prio = APP_IRQ_PRIORITY_LOW};
    
          err_code = nrf_libuarte_async_init(&libuarte1, &nrf_libuarte_async_config1, uart_event_handler, (void *)&libuarte1);
          err_code = nrf_libuarte_async_init(&libuarte2, &nrf_libuarte_async_config2, uart_event_handler, (void *)&libuarte2);
    
          APP_ERROR_CHECK(err_code);
          nrf_libuarte_async_enable(&libuarte1);
          nrf_libuarte_async_enable(&libuarte2);
          APP_ERROR_CHECK(err_code);
          send_UART_1(text, sizeof(text));
    
          while (true)
          {
              NRF_LOG_FLUSH();
          }
      }


  • Hi,

    The 'm_loopback_phase' flag is never cleared which will cause the nrf_libuarte_async_rx_free() to be called on every NRF_LIBUARTE_ASYNC_EVT_TX_DONE event even if there is no data in the RX buffer.

    You can move nrf_libuarte_async_rx_free() to the end NRF_LIBUARTE_ASYNC_EVT_RX_DATA event if you are not doing loopback testing.

Reply Children
Related