Skip to content

i2s_out: Fix i2s_start -> tx rempty -> i2s_done#128

Open
SpComb wants to merge 7 commits into
masterfrom
i2s-out-i2s-start-done-intr
Open

i2s_out: Fix i2s_start -> tx rempty -> i2s_done#128
SpComb wants to merge 7 commits into
masterfrom
i2s-out-i2s-start-done-intr

Conversation

@SpComb

@SpComb SpComb commented Jun 17, 2026

Copy link
Copy Markdown
Member

Fixes #127

Do not enable I2S_TX_REMPTY_INT_ENA on the DMA EOF interrupt before i2s_out_i2s_start(), this can currently lead to on assert failure on the stats_timer_update() call with stats_out_timer_start unset. Observed with a very small [leds] count = 10 config, making this more likely.

Improve the opt-in ISR WARN logging and guard against these kinds of conditions. Drop the missed EOF descr logging to INFO, because this is expected to happen with short descrs.

Tweak the ordering of the state update, ll dev setup and interrupt enable/disable in the critical sections.

// let's hope that the EOF frame is always zeroes, and zero bytes at the start are harmless...
i2s_ll_tx_start(i2s_out->dev);

// can only be enabled once tx is running, will otherwise always fire immediately

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Speculation: the premature tx rempty interrupts before DMA EOF might happen if DMA hasn't had a chance to put anything into the TX FIFO before i2s_out_i2s_start() starts I2S TX?

Testing shows that the i2s_intr_enable() -> i2s_ll_tx_start() ordering will always fire:

W (1522) i2s_intr_tx_rempty_handler: tx rempty i2s_start=1 dma_done=0 i2s_done=0
W (1552) i2s_intr_out_eof_handler: re-enable tx rempty interrupt
W (1552) i2s_intr_tx_rempty_handler: tx rempty i2s_start=1 dma_done=0 i2s_done=0
W (1582) i2s_intr_out_eof_handler: re-enable tx rempty interrupt
W (1582) i2s_intr_tx_rempty_handler: tx rempty i2s_start=1 dma_done=0 i2s_done=0
W (1602) i2s_intr_out_eof_handler: re-enable tx rempty interrupt
W (1602) i2s_intr_tx_rempty_handler: tx rempty i2s_start=1 dma_done=0 i2s_done=0
W (1632) i2s_intr_out_eof_handler: re-enable tx rempty interrupt
W (1632) i2s_intr_tx_rempty_handler: tx rempty i2s_start=1 dma_done=0 i2s_done=0
W (1662) i2s_intr_out_eof_handler: re-enable tx rempty interrupt

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This also happens if calling i2s_out_i2s_start() -> i2s_out_dma_start().

W (1832) i2s_intr_out_eof_handler: re-enable tx rempty interrupt
W (1842) i2s_intr_tx_rempty_handler: tx rempty i2s_start=1 dma_done=0 i2s_done=0
W (1862) i2s_intr_out_eof_handler: re-enable tx rempty interrupt
W (1872) i2s_intr_tx_rempty_handler: tx rempty i2s_start=1 dma_done=0 i2s_done=0
W (1892) i2s_intr_out_eof_handler: re-enable tx rempty interrupt
W (1902) i2s_intr_tx_rempty_handler: tx rempty i2s_start=1 dma_done=0 i2s_done=0
W (1932) i2s_intr_out_eof_handler: re-enable tx rempty interrupt
W (1932) i2s_intr_tx_rempty_handler: tx rempty i2s_start=1 dma_done=0 i2s_done=0
W (1962) i2s_intr_out_eof_handler: re-enable tx rempty interrupt
W (1962) i2s_intr_tx_rempty_handler: tx rempty i2s_start=1 dma_done=0 i2s_done=0

@SpComb SpComb Jun 17, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good thing, because the i2s out TX is likely to harmless at the very start of the transfer. But fixing this race would make the premature tx rempty intr warning more relevant, if some kind of memory contention causes the DMA to stall enough for the TX FIFO to empty during the frame and disrupt the WS2812B timings? Maybe we could even use i2s_ll_tx_stop_on_fifo_empty() / tx_stop_en?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

i2s_out intr stats timer stop assert failed

1 participant