nrf_libuarte_async_rx_free not working. Tx Buffer overflow

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;
        //receive data event
    case NRF_LIBUARTE_ASYNC_EVT_RX_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);
        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);
        }
        m_loopback_phase = true;
        break;

    case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
        if (m_loopback_phase)
        {
            nrf_libuarte_async_rx_free(&libuarte1, textAT1_Uart1, sizeof(textAT1_Uart1));
            // 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));
            }
        }
        break;
    default:
        break;
    }
}

Hi,  I am using libuartes and when I receive text from other device my nrf52833 will respone "textAT1_Uart1". But I can not free them (using &libuartes1 because I'm using 2 uartes so how can I free them ? Thank in advance

Parents
  • Hi, 

    You cannot free the size of textAT1_Uart1 every time, unless you make sure that the received chunks are always this size (without any timeout in between), and that you have set the buffer size in libUARTE definition macro to the same size, e.g:

    NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, sizeof(text_AT1_Uart1), 3);

    The buffer pointer of textAT1_Uart1 also likely does not match the internal buffers allocated inside libUARTE, so it does not make sense to pass this to the free-function.

    The libUARTE library will create N number of buffers (3 in above code) of the given size (255 in above code), which is the buffers you need to free by calling nrf_libuarte_async_rx_free(). If the size of these buffers are set to 255 in the definition macro, you need to free exactly 255 bytes of this buffer, before the buffer is released back to the library.

    If you normally receive packets of 200 bytes, two received packets will be split into 3 events;

    1. 200 bytes received in buffer0
    2. 55 bytes received in buffer0 (buffer0 full)
    3. 145 bytes received in buffer1 (buffer1 now have 110 byte free space).

    I would recommend you to follow the example and call the nrf_libuarte_async_rx_free() function only using the parameters p_evt->data.rxtx.p_data and p_evt->data.rxtx.length.

    Best regards,
    Jørgen

Reply
  • Hi, 

    You cannot free the size of textAT1_Uart1 every time, unless you make sure that the received chunks are always this size (without any timeout in between), and that you have set the buffer size in libUARTE definition macro to the same size, e.g:

    NRF_LIBUARTE_ASYNC_DEFINE(libuarte, 0, 0, 0, NRF_LIBUARTE_PERIPHERAL_NOT_USED, sizeof(text_AT1_Uart1), 3);

    The buffer pointer of textAT1_Uart1 also likely does not match the internal buffers allocated inside libUARTE, so it does not make sense to pass this to the free-function.

    The libUARTE library will create N number of buffers (3 in above code) of the given size (255 in above code), which is the buffers you need to free by calling nrf_libuarte_async_rx_free(). If the size of these buffers are set to 255 in the definition macro, you need to free exactly 255 bytes of this buffer, before the buffer is released back to the library.

    If you normally receive packets of 200 bytes, two received packets will be split into 3 events;

    1. 200 bytes received in buffer0
    2. 55 bytes received in buffer0 (buffer0 full)
    3. 145 bytes received in buffer1 (buffer1 now have 110 byte free space).

    I would recommend you to follow the example and call the nrf_libuarte_async_rx_free() function only using the parameters p_evt->data.rxtx.p_data and p_evt->data.rxtx.length.

    Best regards,
    Jørgen

Children
  • Thanks for your reply Jorgen. It's very valuable with me.
    I use the libuartes example and my code working smoothy but I edited some code like this.
    The difference is line 35 and 36. I want to send anything from my computer (Hercules) and nRF will response textAT1_Uart1. But I don't know why nRF reset after I send some text buffer from my computer seem Rx buffer was not cleared and overflowed. And can you comment on my code to explain the mean of each main line of codes ?. Thank you so much. I really need your help 

    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 textAT1_Uart1[] = "AT1 = uart1\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);
            // ret = nrf_libuarte_async_tx(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
            send_UART_1(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;
        }
    }


Related