nRF52840 UARTE0 EasyDMA receives more bytes than expected

Greetings!

I'm currently making a project that involves using UART in EasyDMA Mode (via Zephyr Async API).

I have noticed an interesting behavior when you try to receive via UARTE0 (provided by Interface/Debug chip VCOM).

For example, I'm enabling the reception with 

uart_rx_enable(uart, rx_buf, 10, SYS_FOREVER_US);

After that I'm sending >10, let's say 20 bytes. After 10 bytes received I get an UART_RX_RDY callback, everything is very fine, but if I will restart the reception with

uart_rx_enable(uart, rx_buf, 10, SYS_FOREVER_US);

I will instantly get one more UART_RX_RDY callback. Buffer will contain that second 10 bytes part.

My question is: Who is actually responsible for such a behavior? Is this some shadow UART buffer in RAM? If so, how can I control its size? Because I don't need it to buffer more than I have set up. Also I'm thinking about the Interface chip, probably if it has received something via VCOM, it stores some data inside in a hidden buffer.

If I switch to UARTE1, no such behavior is observed. Only UARTE0 via USB vcom.

Simple snippet for testing, some minimal editing may be needed:

#include <zephyr/kernel.h>
#include <zephyr/drivers/uart.h>
static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
{
switch (evt->type) {
case UART_RX_RDY:
printk("RX READY\n");
printk("%d \n", evt->data.rx.len);
break;
}
}

static uint8_t rx_buf[10] = {0}; //A buffer to store incoming UART data

const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart0));
int main(void)
{
int err = 0;
if (!device_is_ready(uart)) {
return err;
}
err = uart_callback_set(uart, uart_cb, NULL);
if (err) {
return err;
}
uart_rx_enable(uart, rx_buf, 10, SYS_FOREVER_US);
while (1)
{
k_msleep(5000); // Mash your keyboard here, make > 10 bytes in these 5 seconds
uart_rx_enable(uart, rx_buf, 10, SYS_FOREVER_US);
}
return 0;
}

Thanks in advance,

BR

Vlad

Parents
  • Hi Vlad

    After that I'm sending >10, let's say 20 bytes. After 10 bytes received I get an UART_RX_RDY callback, everything is very fine, but if I will restart the reception

    I do not fully understand your setup. You are sending and receiving, or receiving at the other end?

    But if it is that it works for uarte1 and you see a problem with uart0, maybe you can send me a minimal project that compiles and I can test here. 

    Please do mention the SDK version you are using, and any other details regarding the setup if any.

    Regards,
    Naeem

Reply
  • Hi Vlad

    After that I'm sending >10, let's say 20 bytes. After 10 bytes received I get an UART_RX_RDY callback, everything is very fine, but if I will restart the reception

    I do not fully understand your setup. You are sending and receiving, or receiving at the other end?

    But if it is that it works for uarte1 and you see a problem with uart0, maybe you can send me a minimal project that compiles and I can test here. 

    Please do mention the SDK version you are using, and any other details regarding the setup if any.

    Regards,
    Naeem

Children
  • Hi Naeem,

    Let's split my task on simple parts.

    I'm indeed using two separate UARTs to transfer data in a special way, but it's not the point here, I will simplify the setup as much as possible to still be able to reproduce this behavior.

    So, for this simple setup I have: PC connected to the nRF52840 UARTE0 via USB cable (On board Interface Chip).

    I send the data FROM PC (using Minicom but everything will work, puTTY, nRF Serial Term etc.) to my board. Board only receives data.

    My board in EasyDMA mode accepts some bytes of data till 50 bytes will arrive OR till it will be stopped by Bluetooth interrupt to read it earlier.

    The thing is: if you send less or equal to 50 bytes from PC to board, everything is fine. If you send more, the next time you will start and stop RX routine, buffer will already have some data inside (that data which was sent after initial 50 bytes).

    I use 2.6.1 toolchain, nothing more special to tell, just a basic project. I will send you the code below. For simplicity, I put len of buffer equal 10 bytes. As soon as the board will boot, try to send at least 20 bytes or more data to it, you can for example mash your keyboard buttons and wait. After 5 seconds you will see the next thing in the console:

    *** Booting nRF Connect SDK v3.5.99-ncs1-1 ***
    RX READY
    Received: 10 bytes // THIS WILL SHOW ASAP AFTER YOU ENTER 10 BYTES
    RX Disabled
    RX READY
    Received: 10 bytes // THIS WILL SHOW AFTER UART_RX WILL BE RESTARTED IN WHILE LOOP
    RX Stopped
    RX Disabled

    Code:

    #include <zephyr/kernel.h>
    #include <zephyr/drivers/uart.h>
    
    static uint8_t rx_buf[10] = {0};
    const struct device *uart = DEVICE_DT_GET(DT_NODELABEL(uart0));
    static void uart_cb(const struct device *dev, struct uart_event *evt, void *user_data)
    {
    
        switch (evt->type) {
    
        case UART_TX_DONE:
            break;
    
        case UART_TX_ABORTED:
            break;
    
        case UART_RX_RDY:
            printk("RX READY\n");
            printk("Received: %d bytes\n", evt->data.rx.len);
            break;
    
        case UART_RX_BUF_REQUEST:
            break;
    
        case UART_RX_BUF_RELEASED:
            break;
    
        case UART_RX_DISABLED:
            printk("RX Disabled\n");
            break;
    
        case UART_RX_STOPPED:
            printk("RX Stopped\n");
            break;
    
        default:
            break;
        }
    }
    
    
    int main(void)
    {
        int err = 0;
    
        if (!device_is_ready(uart)) {
            return err;
        }
    
        err = uart_callback_set(uart, uart_cb, NULL);
        if (err) {
            return err;
        }
    
        uart_rx_enable(uart, rx_buf, 10, SYS_FOREVER_US);
    
        while (1)
        {
            k_msleep(5000);
            uart_rx_enable(uart, rx_buf, 10, SYS_FOREVER_US);
        }
    
        return 0;
    }
    

    Config:

    CONFIG_GPIO=y
    CONFIG_SERIAL=y
    CONFIG_UART_ASYNC_API=y
    

    BR

  • Hi Naeem,

    are there any additional updates regarding this situation?

    BR

Related