fix(radio): RGB leds signal left floating between frames - #7620
Open
3djc wants to merge 1 commit into
Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary of changes:
The WS2812 data line was left floating between frames, and the frame itself
was refilled from an ISR while the DMA was already running. Both are fixed
here.
1. The line floats between frames
At end of frame
_update_dma_buffer()disabled the timer compare channel(
LL_TIM_CC_DisableChannel). WithOSSR = 0that releases the pad instead ofholding it, so the data line floats until the next
rgbleds_update(). Afloating input on a WS2812 can be read as bit activity, the reset gap is
missed, and the chip keeps counting bits across frames — the visible symptom
is the whole strip shifted by one LED, colours landing on the wrong chip.
The channel is now left enabled with a compare value of 0, so the output is
actively driven low between frames; only the DMA request source is stopped.
The pin also gets a pull-down at init (insurance for boot / de-init, where the
timer does not drive the pad), and the line is driven low from
rgbleds_init()so an idle strip is never left floating before the first frame.That was the heart of the issue. (#6926). In essence, all radio where vulnerable, but only few exhibited the issue because it needs a specific non favorable board layout to be. actually seen.
2. The frame was refilled under an ISR deadline
The DMA buffer held two LEDs and was refilled half-by-half from the HT/TC
interrupts, so every 24 bit-slots the ISR had a hard deadline. Any higher
priority IRQ (SDMMC, USB) that overran it corrupted the frame in flight.
The whole frame is now built up front and sent as a single one-shot DMA
transfer (
LL_DMA_MODE_NORMAL, sized fromLED_STRIP_LENGTH), with only aTC interrupt at the end. There is no refill deadline left, and a late TC IRQ
is harmless because the frame ends with
RGBLEDS_TRAIL_SLOTSzero slots thatkeep the line low.
RGBLEDS_TRAILING_RESETis gone as a result.Since NDTR and the memory address are not reloaded by simply re-enabling the
stream,
rgbleds_update()reprograms both per frame, and a newstm32_dma_clear_flags()helper (both the H7RS and the classic DMA variantsin
stm32_dma.h) clears the pending event flags — a stream cannot bere-enabled while any of them is still set.
This part was found while trying to harden the signal
This fixes #6926