PARLIO 8-bit loop transmission emits GDMA EOF on every ring wrap with BitScrambler on ESP32-C5 (IDFGH-18286)
Answers checklist
- I have read the ESP-IDF documentation and did not find this behavior documented.
- I searched the issue tracker for similar PARLIO / BitScrambler /
suc_eofloop-transmission reports and did not find this specific issue.
General issue report
Target: ESP32-C5
Peripheral path: PARLIO TX (8-bit) + BitScrambler + GDMA
Mode: loop_transmission = true
Use case: continuous, boundaryless realtime byte stream
In components/esp_driver_parlio/src/parlio_tx.c, the last descriptor of a loop transmission is currently mounted with:
.mark_eof = tx_unit->data_width == 1 ? !t->flags.loop_transmission : true,
.mark_final = t->flags.loop_transmission ? GDMA_FINAL_LINK_TO_START : GDMA_FINAL_LINK_TO_NULL,For data_width > 1, including our 8-bit case, this means the final cyclic DMA descriptor gets suc_eof = 1 on every wrap even though its next pointer links back to the beginning of the ring.
The GDMA linked-list implementation documents suc_eof as notifying the peripheral of an EOF event.
There is already a special case for 1-bit loop transmission related to DIG-559, where EOF is suppressed in loop mode. For 8-bit loop mode it remains enabled.
Observed behavior
We use PARLIO TX as a continuous 8-bit output stream with a BitScrambler attached. The source stream is cyclic and is intended to have no logical frame/transaction boundaries.
With the stock descriptor configuration (suc_eof = 1 on the last node), we consistently observed periodic stream discontinuities. In our analog video application these appeared as:
- fine horizontal raster shifts / "teeth"
- periodic vertical sync corruption
- occasional black bands and full-image vertical jumps
- artifact timing strongly dependent on cyclic ring size
We then performed an A/B test where the only relevant change was clearing suc_eof on the cyclic descriptors after startup.
A/B result
Stock loop descriptors:
last cyclic descriptor: suc_eof = 1Result:
periodic visible stream seams / sync corruptionPatched cyclic descriptors:
all cyclic descriptors: suc_eof = 0Live telemetry after the patch:
RX patched: 9 nodes
TX patched: 9 nodes
PARLIO RX FIFO overflow: 0
PARLIO TX FIFO empty/underflow: 0
PARLIO TX EOF: 0
BitScrambler TX empty: 0Result:
visible raster artifacts disappeared
black-band / layer-shift events disappeared
continuous stream remained stableThis was reproduced using the same realtime pipeline and ring; removing the cyclic EOF marker was the change that eliminated the artifacts.
Why this may be a driver issue
For an infinite loop transmission, a user may reasonably expect the stream to be continuous until parlio_tx_unit_disable() is called. However, for data_width > 1, the driver currently injects a GDMA EOF marker on every cyclic wrap.
With BitScrambler attached, EOF is meaningful hardware metadata (eof_on, trailing bytes, EOF trace/state), so this boundary is observable even though the DMA link itself continues cyclically.
The existing DIG-559 special case for 1-bit loop transmission also suggests EOF handling in cyclic PARLIO mode is already known to require care.
Question / proposed direction
Could Espressif confirm whether suc_eof = 1 is required on the final descriptor for data_width > 1 when loop_transmission = true?
For a true continuous loop, would it be valid to use something equivalent to:
.mark_eof = !t->flags.loop_transmission,for all data widths, or is EOF required internally for buffer switching / another PARLIO feature?
If EOF is only required for loop-buffer switching, perhaps it could be omitted for a steady-state loop that repeatedly transmits the same buffer.
Notes
- PARLIO TX itself is not being software-disabled/re-enabled at each wrap.
- BitScrambler is not explicitly reset by software at each wrap.
- The issue is specifically the hardware EOF marker propagated by the cyclic descriptor.
- We are happy to provide a minimal reproducer or additional register traces if useful.
Related source locations:
components/esp_driver_parlio/src/parlio_tx.ccomponents/esp_driver_dma/src/gdma_link.c- BitScrambler EOF handling / trace registers on ESP32-C5
Source: espressif/esp-idf