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

LIBUARTE on ble_app_uart with DMA

Hi All,

I have 2 boards nrf52840 pc10056 and I need to run ble_app_uart using LIBUARTE with DMA in order to obtain a more robust uart communication

I would like to use an uart DMA that will work in background saving the byte received in a buffer (fixed length) and once that it is full having an interrupt where I can check this buffer and send it to the central unit.

Is there any easy way to set  everything up and change the code of ble_app_uart? Any suggestion??

Thanks

Parents
  • Hi

    I'm having some trouble understanding what exactly you mean. Is it the UART or the BLE communication you're having trouble with? It seems to me that you're able to receive the UART data filling up your buffer to the peripheral, and then sending this data to the central. Are you having trouble clearing the RX buffer from the peripheral before receiving a new "batch" of UART data?

    Best regards,

    Simon

  • Hi Simonr,

    In this moment I'm able to receive the data from the micro-controller to the peripheral via UART (I'm sending a fixed length packet from micro to peripheral). Once that I receive this packet I've tried to do 2 things:

    1) The peripheral receive the DATA from the micro-controller via UART and print them again on its own UART (I print the packet received on the terminal, in order to have a visual of what is happening and if the peripheral is receiving good the data from the micro-controller).

    void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
    {
        nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
        uint32_t       err_code;
        ret_code_t ret;
    
        switch (p_evt->type)
        {
            case NRF_LIBUARTE_ASYNC_EVT_ERROR:
                bsp_board_led_invert(1);
                break;
            case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
                bsp_board_led_invert(2);
                ret = nrf_libuarte_async_tx(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
                nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data , p_evt->data.rxtx.length);    // if I remove this line of code I will have more or less the same behavior 
                break;
            case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
                bsp_board_led_invert(3);
                break;
            default:
                break;
        }
    }

     The important code lines are:

    -     ret = nrf_libuarte_async_tx(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
    -     nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data , p_evt->data.rxtx.length);

    In this case it works perfectly (It means I can see on the terminal the packet that I'm sending from the micro-controller).

    For instance, if I comment out the line where I make free the buffer:

    -     ret = nrf_libuarte_async_tx(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
    -   //  nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data , p_evt->data.rxtx.length);

    What will happen is that I will see on terminal a number of packets that is proportional to the RX buffer before to stop working. Rx that I set here:

    - NRF_LIBUARTE_ASYNC_DEFINE (libuarte, 0, 3, 0, 4, "RX", 3);

    It means that, if I have a bigger RX buffer I'll see more packet on the terminal before it stops.

    Conclusion on this point: 

    - If I want to print on terminal what I' m receiving from micro-controller is important to make free the RX buffer. In that case everything is working good and reliable.

    2) The peripheral will send the packets that it receives, from the micro-controller via UART, to the central over bluetooth. The central, once got the packet, will print it on the terminal. 

    void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
    {
        nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
        uint32_t       err_code;
        ret_code_t ret;
    
        switch (p_evt->type)
        {
            case NRF_LIBUARTE_ASYNC_EVT_ERROR:
                bsp_board_led_invert(1);
                break;
            case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
                bsp_board_led_invert(2);
                err_code= ble_nus_data_send(&m_nus, p_evt->data.rxtx.p_data, &p_evt->data.rxtx.length, m_conn_handle);
                do
                {
                    if ((err_code != NRF_ERROR_INVALID_STATE) &&
                        (err_code != NRF_ERROR_RESOURCES) &&
                        (err_code != NRF_ERROR_NOT_FOUND))
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                } while (err_code == NRF_ERROR_RESOURCES);
                nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data , p_evt->data.rxtx.length);    // if I remove this line of code I will have more or less the same behavior 
                break;
            case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
                bsp_board_led_invert(3);
                break;
            default:
                break;
        }
    }

    Important lines:

    -    err_code= ble_nus_data_send(&m_nus, p_evt->data.rxtx.p_data, &p_evt->data.rxtx.length, m_conn_handle);
    -    nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data , p_evt->data.rxtx.length);

    In this case the peripheral start to sends packets to the central, but after a while it stops and crash.

    The number of packets sent, like in the 1) case, is proportional to the RX buffer size that I've set here:

    NRF_LIBUARTE_ASYNC_DEFINE (libuarte, 0, 3, 0, 4, "RX", 3);

    All of this happens without commenting out:

    -   nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data , p_evt->data.rxtx.length);

    So, it's like that the RX_buffer cannot be cleaned once that I send data over bluetooth with "ble_nus_data_send".

    So, my problem is that when I try to send the packet from the peripheral to the central over bluetooth, it stops after a while. The behaviour in the case 2 is the one where I'm asking you help. The case 1 is just a case where the problem seems to have the same behaviour once that I comment out the "nrf_libuarte_async_rx_free".

Reply
  • Hi Simonr,

    In this moment I'm able to receive the data from the micro-controller to the peripheral via UART (I'm sending a fixed length packet from micro to peripheral). Once that I receive this packet I've tried to do 2 things:

    1) The peripheral receive the DATA from the micro-controller via UART and print them again on its own UART (I print the packet received on the terminal, in order to have a visual of what is happening and if the peripheral is receiving good the data from the micro-controller).

    void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
    {
        nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
        uint32_t       err_code;
        ret_code_t ret;
    
        switch (p_evt->type)
        {
            case NRF_LIBUARTE_ASYNC_EVT_ERROR:
                bsp_board_led_invert(1);
                break;
            case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
                bsp_board_led_invert(2);
                ret = nrf_libuarte_async_tx(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
                nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data , p_evt->data.rxtx.length);    // if I remove this line of code I will have more or less the same behavior 
                break;
            case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
                bsp_board_led_invert(3);
                break;
            default:
                break;
        }
    }

     The important code lines are:

    -     ret = nrf_libuarte_async_tx(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
    -     nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data , p_evt->data.rxtx.length);

    In this case it works perfectly (It means I can see on the terminal the packet that I'm sending from the micro-controller).

    For instance, if I comment out the line where I make free the buffer:

    -     ret = nrf_libuarte_async_tx(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
    -   //  nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data , p_evt->data.rxtx.length);

    What will happen is that I will see on terminal a number of packets that is proportional to the RX buffer before to stop working. Rx that I set here:

    - NRF_LIBUARTE_ASYNC_DEFINE (libuarte, 0, 3, 0, 4, "RX", 3);

    It means that, if I have a bigger RX buffer I'll see more packet on the terminal before it stops.

    Conclusion on this point: 

    - If I want to print on terminal what I' m receiving from micro-controller is important to make free the RX buffer. In that case everything is working good and reliable.

    2) The peripheral will send the packets that it receives, from the micro-controller via UART, to the central over bluetooth. The central, once got the packet, will print it on the terminal. 

    void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
    {
        nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
        uint32_t       err_code;
        ret_code_t ret;
    
        switch (p_evt->type)
        {
            case NRF_LIBUARTE_ASYNC_EVT_ERROR:
                bsp_board_led_invert(1);
                break;
            case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
                bsp_board_led_invert(2);
                err_code= ble_nus_data_send(&m_nus, p_evt->data.rxtx.p_data, &p_evt->data.rxtx.length, m_conn_handle);
                do
                {
                    if ((err_code != NRF_ERROR_INVALID_STATE) &&
                        (err_code != NRF_ERROR_RESOURCES) &&
                        (err_code != NRF_ERROR_NOT_FOUND))
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                } while (err_code == NRF_ERROR_RESOURCES);
                nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data , p_evt->data.rxtx.length);    // if I remove this line of code I will have more or less the same behavior 
                break;
            case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
                bsp_board_led_invert(3);
                break;
            default:
                break;
        }
    }

    Important lines:

    -    err_code= ble_nus_data_send(&m_nus, p_evt->data.rxtx.p_data, &p_evt->data.rxtx.length, m_conn_handle);
    -    nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data , p_evt->data.rxtx.length);

    In this case the peripheral start to sends packets to the central, but after a while it stops and crash.

    The number of packets sent, like in the 1) case, is proportional to the RX buffer size that I've set here:

    NRF_LIBUARTE_ASYNC_DEFINE (libuarte, 0, 3, 0, 4, "RX", 3);

    All of this happens without commenting out:

    -   nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data , p_evt->data.rxtx.length);

    So, it's like that the RX_buffer cannot be cleaned once that I send data over bluetooth with "ble_nus_data_send".

    So, my problem is that when I try to send the packet from the peripheral to the central over bluetooth, it stops after a while. The behaviour in the case 2 is the one where I'm asking you help. The case 1 is just a case where the problem seems to have the same behaviour once that I comment out the "nrf_libuarte_async_rx_free".

Children
No Data
Related