#19091·esp-idf

PARLIO 8-bit loop transmission emits GDMA EOF on every ring wrap with BitScrambler on ESP32-C5 (IDFGH-18286)

Author: TwotozCreated Sep 16, 2026Updated Sep 18, 2026
LabelsStatus: In Progress

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_eof loop-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:

c
.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 = 1

Result:

periodic visible stream seams / sync corruption

Patched cyclic descriptors:

all cyclic descriptors: suc_eof = 0

Live 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: 0

Result:

visible raster artifacts disappeared
black-band / layer-shift events disappeared
continuous stream remained stable

This 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:

c
.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.c
  • components/esp_driver_dma/src/gdma_link.c
  • BitScrambler EOF handling / trace registers on ESP32-C5