Libuarte_async_tx - loss of bytes while transferring to PC (with active softdevice 132, nrf52832).

Hi,

I am transferring data received via ble to uart PC.

BLE MTU - 247, connection priority - HIGH (15ms).

I successfully receive data from ble, put it in the fifo, then take it out and send it to libuarte.

But less data comes to the PC than I sent (provided that the data was larger than 244 bytes).

Example: I send 256 bytes (00 - FF) from my smartphone, it will be 244 and 12 bytes.

output in RTT:

<info> app: uart_loop fifo_read: 244 bytes
<warning> libUARTE: Started TX total length:244, first chunk:244
<info> app: uart_loop fifo_read: 12 bytes
<warning> libUARTE: Started TX total length:12, first chunk:12

data on PC:

my code:

#include <string.h>
#include <nrf_libuarte_async.h>
#include <nrf_queue.h>
#include <app_fifo.h>
#include "custom_board.h"
#include "config.h"
#include "uart.h"
#include "cpu.h"
#include "log.h"

#define UART_BUF_SIZE (1024 * 8)
#define RX_BUF_SIZE UART_BUF_SIZE
#define TX_BUF_SIZE UART_BUF_SIZE
#define UART_MTU_SIZE 244
#define UART_TX_SIZE 244

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

static uint8_t rx_fifo_buf[RX_BUF_SIZE] __attribute__ ((aligned (32)));
static uint8_t tx_fifo_buf[TX_BUF_SIZE] __attribute__ ((aligned (32)));
static app_fifo_t m_rx_fifo;
static app_fifo_t m_tx_fifo;

static uint8_t rx_buf[UART_MTU_SIZE] __attribute__ ((aligned (32)));
static uint8_t tx_buf[UART_MTU_SIZE] __attribute__ ((aligned (32)));
static bool tx_is_busy = false;
static bool libuarte_is_error = false;

void uart_event_handler(void *context, nrf_libuarte_async_evt_t *p_evt)
{
    ret_code_t err_code;
    nrf_libuarte_async_t *p_libuarte = (nrf_libuarte_async_t *)context;
    uint32_t size;

    switch (p_evt->type)
    {
    case NRF_LIBUARTE_ASYNC_EVT_RX_DATA:
        size = (uint32_t)p_evt->data.rxtx.length;
        err_code = app_fifo_write(&m_rx_fifo, p_evt->data.rxtx.p_data, &size);

        if (size != p_evt->data.rxtx.length || err_code != NRF_SUCCESS)
            libuarte_is_error = true;

        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_is_busy = false;
        break;

    case NRF_LIBUARTE_ASYNC_EVT_ERROR:
    case NRF_LIBUARTE_ASYNC_EVT_OVERRUN_ERROR:
        libuarte_is_error = true;
        tx_is_busy = false;
    break;

    default:
        break;
    }
}

void uart_init(void)
{
    ret_code_t err_code;

    err_code = app_fifo_init(&m_rx_fifo, rx_fifo_buf, RX_BUF_SIZE);
    APP_ERROR_CHECK(err_code);

    err_code = app_fifo_init(&m_tx_fifo, tx_fifo_buf, TX_BUF_SIZE);
    APP_ERROR_CHECK(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_1000000,
        .parity = NRF_UARTE_PARITY_EXCLUDED,
        .hwfc = NRF_UARTE_HWFC_DISABLED,
        .timeout_us = 100,
        .pullup_rx = false,
        .int_prio = APP_IRQ_PRIORITY_LOW_MID};

    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);
}

void uart_tx(const uint8_t *data, uint8_t len)
{
    ret_code_t err_code;
    uint32_t size = len;

    err_code = app_fifo_write(&m_tx_fifo, data, &size);

    if (size != len || err_code != NRF_SUCCESS)
        DBG_LOG_ERROR("%s fifo_write_error!", __func__);
}

void uart_rx(uint8_t *data, uint8_t *len)
{
    ret_code_t err_code;
    uint32_t size = *len;

    if (size > UART_MTU_SIZE)
    {
        DBG_LOG_ERROR("%s len > UART_MTU_SIZE!", __func__);
        *len = 0;
        return;
    }

    err_code = app_fifo_read(&m_rx_fifo, rx_buf, &size);

    if (err_code == NRF_SUCCESS && size != 0)
    {
        memcpy(data, rx_buf, size);
        *len = size;
    }
    else
    {
        *len = 0;
    }
}

void uart_loop(void)
{
    ret_code_t err_code;
    uint32_t n_bytes;

    if (libuarte_is_error)
    {
        libuarte_is_error = false;
        DBG_LOG_ERROR("%s libuarte_error!", __func__);
    }

    if (!tx_is_busy)
    {
        n_bytes = UART_TX_SIZE;
        err_code = app_fifo_read(&m_tx_fifo, tx_buf, &n_bytes);

        if (err_code == NRF_SUCCESS && n_bytes != 0)
        {
            DBG_LOG_INFO("%s fifo_read: %d bytes", __func__, n_bytes);

            tx_is_busy = true;
            err_code = nrf_libuarte_async_tx(&libuarte, tx_buf, n_bytes);
            if (err_code != NRF_SUCCESS)
            {
                tx_is_busy = false;
                DBG_LOG_ERROR("%s libuarte_tx Error!", __func__);
            }
        }
    }
}

main loop:

for (;;)
{
    ble_receive(data, &len);

    if (len)
    {
        uart_tx(data, len);      
    }
    
    uart_loop();

    ...
}

I have tried different settings but without success.
The transfer works successfully if you generate data locally, do not use bluetooth to receive data.

Maybe when data is received via bluetooth, does the libuarte_tx stop?
Ideas and advice? (I would be very happy to discuss and provide additional information)

  • I am using android smartphone to send data and nRF52-DK board to ble receive and transmit via UART to PC.

    Using nRF Connect, I connect to the board, enter the pin code "123456", and then set the connection parameters.

    MTU - 247, connection priority - HIGH.

    nRF Connect

    I have created a 00-FF raw data file (256) and am sending it using the Serial Bluetooth terminal.
    256.zip

    Serial Bluetooth terminalSerial Bluetooth terminalSerial Bluetooth terminal

    And no matter how I changed the settings, on the PC I get fewer bytes than I sent.

    I created a separate project from our codebase that demonstrates this issue (ble_uart.zip). 

    ble_uart.zip

    I hope to help and are willing to provide additional information upon request.

  • I rewrote the example without using libuarte (I only used nrf_drv_uart.h).

    Problem still exists.

    But, as soon as I disabled the debug terminal, the problem disappeared.
    I checked many times, and with the original project too.
    There is no problem if you do not connect a debug terminal.
    But there is a problem if the terminal is connected, even if it is disabled in the configuration (sdk_config.h NRF_LOG_BACKEND_RTT_ENABLED 0, NRF_LOG_BACKEND_UART_ENABLED 0, NRF_LOG_ENABLED 0).

    Can someone comment on why this is happening and suggest a solution that will allow using the debug terminal?

Related