-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Description
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?