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

How to add app_fifo with LIBUARTE ?

Hi All,

I used app_uart_fifo.c and it worked however RX is not good so I switched to LIBUARTE.

The RX part is good with LIBUARTE however when TX traffic is high nrf_libuarte_async_tx might skip data I need.

Any good idea to integrate app_fifo with LIBUARTE for TX and is there blocking API of nrf_libuarte_async_tx ?

BR,

Sam

  • ex.

    If there are several lines need to be sent out in high frequency.

    ex.

    Line A => nrf_libuarte_async_tx

    (very short time)

    Line B => nrf_libuarte_async_tx

    (very short time)

    Line C => nrf_libuarte_async_tx

    Some line will be lost so I need buffer to hold all Line A,B,C

    BR,

    Sam

  • Hi,

    It is not possible to run two different libraries on a single UART instance, this would require you to run libUARTE on UARTE0 for TX on GPIO P0.06 and app_uart_fifo on UARTE1 for RX on GPIO P0.08 or similar.

    What baudrate are you running at, and are you using HW flow control pins? I'm not sure that running two different libraries is the best solution to your issues. Are you checking error codes when calling nrf_libuarte_async_tx? This function should return NRF_ERROR_BUSY if a transfer is ongoing. You can then buffer the message in your application and start a new transfer as soon as you receive the NRF_LIBUARTE_ASYNC_EVT_TX_DONE event.

    Best regards,
    Jørgen

  • Hi,

    My idea is to port this stuff with nrf_libuarte_async_tx

    uint32_t app_uart_put(uint8_t byte)
    {
        uint32_t err_code;
    
        err_code = app_fifo_put(&m_tx_fifo, byte);
        if (err_code == NRF_SUCCESS)
        {
            // The new byte has been added to FIFO. It will be picked up from there
            // (in 'uart_event_handler') when all preceding bytes are transmitted.
            // But if UART is not transmitting anything at the moment, we must start
            // a new transmission here.
            if (!nrf_drv_uart_tx_in_progress())
            {
                // This operation should be almost always successful, since we've
                // just added a byte to FIFO, but if some bigger delay occurred
                // (some heavy interrupt handler routine has been executed) since
                // that time, FIFO might be empty already.
                if (app_fifo_get(&m_tx_fifo, tx_buffer) == NRF_SUCCESS)
                {
                    err_code = nrf_drv_uart_tx(tx_buffer, 1);
                }
            }
        }
    
        return err_code;
    }

    However I need equivalent nrf_drv_uart_tx_in_progress() API in libuarte however it's not available.

    BR,

    Sam 

  • LibUARTE does not use the UART driver, it uses the UARTE HAL layer directly. Have you considered the Serial port library?

  • Hi Sir,

    Serial port library doesn't work for RX case.

    I managed to use app_fifo with libuarte like this.

    void uart_event_handler(void * context, nrf_libuarte_async_evt_t * p_evt)
    {
        nrf_libuarte_async_t * p_libuarte = (nrf_libuarte_async_t *)context;
        static uint8_t ch = 0;
        ret_code_t ret;
    
        static uint16_t idx = 0;
        uint16_t to_read;
        uint16_t to_write;
    
    
        switch (p_evt->type)
        {
        case NRF_LIBUARTE_ASYNC_EVT_ERROR:
            bsp_board_led_invert(1);
            app_sched_event_put(NULL, 0, uart_evt_recover);
    
            break;
        case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
            // ch = p_evt->data.rxtx.p_data[0];
            // igs_printf("<%s>(%d)", p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
            // ret = nrf_libuarte_async_tx(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
    
            to_read = RX_LINE_BUF_SIZE - idx;
            if (to_read > p_evt->data.rxtx.length) {
                to_read = p_evt->data.rxtx.length;
            }
    
            strncpy(m_data_array + idx, p_evt->data.rxtx.p_data, to_read);
            idx += (to_read);
            m_data_array[idx] = 0;
            // igs_printf("[%s](%d)",m_data_array, idx);
    
            if ((m_data_array[idx - 1] == '\n') || (idx >= (RX_LINE_BUF_SIZE - 1))) {
                app_sched_event_put(NULL, 0, uart_evt_get);
                idx = 0;
            }
    
            nrf_libuarte_async_rx_free(p_libuarte, p_evt->data.rxtx.p_data, p_evt->data.rxtx.length);
    //            ret = nrf_libuarte_async_tx(p_libuarte, &ch, 1);
    //            APP_ERROR_CHECK(ret);
            // bsp_board_led_invert(1);
            break;
        case NRF_LIBUARTE_ASYNC_EVT_TX_DONE:
            // app_sched_event_put(NULL, 0, uart_evt_tx);
        if (!nrf_libuarte_async_tx_in_progress(&libuarte))
        {
            to_write = UART_TX_BUF_SIZE;
            if (app_fifo_read(&m_tx_fifo, tx_buffer, &to_write) == NRF_SUCCESS)
            {
                ret = nrf_libuarte_async_tx(&libuarte, tx_buffer, to_write);
                // if (ret !=  NRF_SUCCESS) {
                if (ret ==  NRF_ERROR_BUSY) {
    
                    bsp_board_led_invert(0);
                    // uart_evt_recover(NULL, 0);
                    // app_sched_event_put(NULL, 0, uart_evt_recover);
                }
            }
        }
            bsp_board_led_invert(1);
            break;
        default:
            break;
        }
    }
    

    I suggest to add API nrf_libuarte_async_tx_in_progress(&libuarte) officially for this usage.

    BR,

    Sam

Related