Skip to content

Unexpected UART DMA Buffer Overflow Behavior in Zephyr When Sending 257 Bytes with 255-Byte Buffer #95267

@RadhikaMaheshwari-eaton

Description

@RadhikaMaheshwari-eaton

Describe the bug

When transmitting 257 bytes of data while the buffer length is set to 255, the system exhibits unexpected behavior during subsequent transmissions. Initially, 255 bytes are received correctly, respecting the buffer limit. However, sending a single character afterward results in receiving both the last remaining byte from the previous transmission and the new character, indicating stale data in the buffer.

Additionally, repeated overflow attempts show inconsistent behavior: the first overflow correctly returns 255 bytes, but subsequent overflows return only 254 bytes, with the first byte being set to NULL. This suggests a one-character loss and potential buffer corruption.

This behavior appears to be linked to Zephyr’s UART DMA handling during overflow scenarios.

Regression

  • This is a regression.

Steps to reproduce

Set the UART receive buffer length to 255 bytes.
Transmit 257 bytes of data.
Observe that only 255 bytes are received (expected).
Transmit a single character immediately after.
Observe that the received data includes:
The last remaining byte from the previous transmission.
The newly sent character.
Repeat the overflow transmission (send 257 bytes again).
Observe that only 254 bytes are received, with the first byte being NULL.

Relevant log output

Impact

Annoyance – Minor irritation; no significant impact on usability or functionality.

Environment

We are working with Zephyr RTOS version 3.6.0 and SDK version 0.16.5-1.
Our implementation involves UART hardware DMA communication on an STM32H743 microcontroller.

Additional Context

Resolution Attempted:
Clearing the buffers before reuse and after errors mitigates the issue. This prevents stale data and reduces overflow-related inconsistencies.
Pseudocode: UART DMA RX Buffer Clearing

function on_uart_rx_buffer_request():
    // Called when UART driver requests a new RX buffer
    clear_buffer(rx_buffer, buffer_length)
    reset_index(rx_index)
    provide_buffer_to_driver(rx_buffer, buffer_length)

function on_uart_rx_stopped():
    // Called when UART RX is stopped due to error or overflow
    clear_buffer(rx_buffer, buffer_length)
    reset_index(rx_index)
    set_rx_state(IDLE)
    // Optionally, notify error to application

function clear_buffer(buffer, length):
    for i from 0 to length-1:
        buffer[i] = 0

function reset_index(index):
    index = 0

Usage Context:
on_uart_rx_buffer_request() is triggered by the driver when a new buffer is needed.
on_uart_rx_stopped() is triggered when RX is stopped due to error/overflow.
Both handlers clear the buffer and reset the index before reuse.
This pattern ensures no stale data is left in the buffer and the index always starts at zero for new RX operations.

Request for Assistance:
@erwango Could you help clarify why Zephyr’s UART DMA behaves this way during overflow scenarios? Is there a recommended approach to handle such cases more robustly?

Metadata

Metadata

Assignees

Labels

area: UARTUniversal Asynchronous Receiver-TransmitterbugThe issue is a bug, or the PR is fixing a bugplatform: STM32ST Micro STM32priority: lowLow impact/importance bug

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions