Sitelet https://github.com/betaflight/betaflight/pull/15419
Skip to content

STM32H5: ADC circular GPDMA so battery/current track live values - #15419

Merged
haslinghuis merged 1 commit into
betaflight:masterfrom
haslinghuis:fix/stm32h5-gpdma-adc-ledstrip
Jul 16, 2026
Merged

haslinghuis merged 1 commit into
betaflight:masterfrom
haslinghuis:fix/stm32h5-gpdma-adc-ledstrip

Conversation

@haslinghuis

@haslinghuis haslinghuis commented Jul 14, 2026 •

Copy link
Copy Markdown
Member

Scope change: the WS2811 LED-strip fix has been split out to #15438 — a deep review against RM0481 found an additional bug there (TIM handle state latch-up freezing the strip after the first frame) that needs an on-hardware retest, while this ADC fix is already hardware-verified. This PR now carries only the ADC change. A comment-only follow-up for the DShot driver's GPDMA rationale is #15439.


On STM32H5 the ADC DMA channel was configured as a one-shot linear transfer (DMA_NORMAL). H5's GPDMA has no plain circular mode, so HAL_ADC_Start_DMA() took its one-shot branch and transferred a single scan: the conversion buffer was filled once at boot and then frozen forever, so VBAT/current/RSSI never tracked the real inputs.

Rebuild the ADC DMA as a circular linked-list queue (HAL_DMAEx_List_* with DMA_LINKEDLIST_CIRCULAR, one static node/queue per ADC device) so HAL_ADC_Start_DMA() takes the linked-list branch and continuously refreshes the buffer.

The conversion buffer (destination) is allocated to GPDMA master PORT1. Note the rationale was corrected during review: both GPDMA master ports reach all memories on H5 (RM0481 §2.1.5, fig. 1) — PORT1 simply has the zero-latency fast bus multiplexer to SRAM, matching the DShot/WS2811 port allocation. The linked-list construction was verified against the vendored H5 HAL: HAL_ADC_Start_DMA() overwrites the head node's source/destination/length (converting samples to bytes itself), and the circular CLLR update mask refetches CTR1/CTR2/CBR1/CSAR/CDAR on every loop, so the buffer genuinely refreshes each scan.

Verified working on hardware: VBAT/current/RSSI track live values. make STM32H563 builds clean with zero warnings.

@haslinghuis haslinghuis added this to the 2026.6 milestone Jul 14, 2026
@haslinghuis haslinghuis self-assigned this Jul 14, 2026
@github-actions

Copy link
Copy Markdown

Do you want to test this code? You can flash it directly from the Betaflight App:

  • Simply put #15419 (this pull request number) in the Select commit field in the Firmware Flasher tab (you need to Enable expert mode, Show release candidates and Development).

WARNING: It may be unstable. Use only for testing!

@coderabbitai

coderabbitai Bot commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

STM32H5 ADC initialization now stores per-device GPDMA nodes and queues, builds an ADC-to-buffer transfer node, enables circular linked-list mode, and attaches the queue through the HAL linked-list APIs.

Changes

STM32H5 ADC DMA

Layer / File(s) Summary
ADC circular linked-list configuration
src/platform/STM32/adc_stm32h5xx.c
Per-device DMA nodes and queues are added, and adcInit replaces direct DMA initialization with circular GPDMA linked-list construction and attachment.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: blckmn, sugaark

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly describes the main change: STM32H5 ADC DMA switched to circular GPDMA for live values.
Description check ✅ Passed The description explains the ADC fix, scope split, rationale, and hardware/build verification; missing template-style admin details are non-critical.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@haslinghuis

Copy link
Copy Markdown
Member Author

@coderabbitai full review - for reference see also datasheet and reference manual

@coderabbitai

coderabbitai Bot commented Jul 15, 2026 •

Copy link
Copy Markdown
Contributor

@haslinghuis Got it — I'll perform a full review of the PR, taking into account the STM32H5 datasheet and reference manual you linked for the GPDMA/ADC/timer behavior details.

✅ Action performed

Full review finished.

@haslinghuis
haslinghuis force-pushed the fix/stm32h5-gpdma-adc-ledstrip branch from 9634951 to b7b2e3c Compare July 15, 2026 18:32
@haslinghuis haslinghuis changed the title STM32H5: fix ADC battery/current and WS2811 LED strip on GPDMA STM32H5/N6: fix WS2811 LED strip GPDMA and STM32H5 ADC battery/current Jul 15, 2026
On STM32H5 the ADC DMA channel was configured as a one-shot linear
transfer (DMA_NORMAL). H5's GPDMA has no plain circular mode, so
HAL_ADC_Start_DMA() took its one-shot branch and transferred a single
scan: the conversion buffer was filled once at boot and then frozen
forever, so VBAT/current/RSSI never tracked the real inputs.

Rebuild the ADC DMA as a circular linked-list queue (HAL_DMAEx_List_*
with DMA_LINKEDLIST_CIRCULAR, one static node/queue per ADC device) so
HAL_ADC_Start_DMA() takes the linked-list branch and continuously
refreshes the buffer. The conversion buffer (destination) is allocated
to GPDMA master PORT1: both ports reach all memories on H5, PORT1 just
has the zero-latency fast bus multiplexer to SRAM (RM0481 fig. 1),
matching the DShot/WS2811 port allocation.
@haslinghuis
haslinghuis force-pushed the fix/stm32h5-gpdma-adc-ledstrip branch from b7b2e3c to 94297e0 Compare July 16, 2026 15:16
@haslinghuis haslinghuis changed the title STM32H5/N6: fix WS2811 LED strip GPDMA and STM32H5 ADC battery/current STM32H5: ADC circular GPDMA so battery/current track live values Jul 16, 2026
@haslinghuis
haslinghuis merged commit a4b1bc0 into betaflight:master Jul 16, 2026
53 checks passed
@github-project-automation github-project-automation Bot moved this from Bugfix to Done in 2026.6.0 Jul 16, 2026
@haslinghuis
haslinghuis deleted the fix/stm32h5-gpdma-adc-ledstrip branch July 16, 2026 15:21
gwlim pushed a commit to gwlim/betaflight that referenced this pull request Jul 25, 2026
…aflight#15419)

fix(STM32H5): ADC circular GPDMA so battery/current track live values

On STM32H5 the ADC DMA channel was configured as a one-shot linear
transfer (DMA_NORMAL). H5's GPDMA has no plain circular mode, so
HAL_ADC_Start_DMA() took its one-shot branch and transferred a single
scan: the conversion buffer was filled once at boot and then frozen
forever, so VBAT/current/RSSI never tracked the real inputs.

Rebuild the ADC DMA as a circular linked-list queue (HAL_DMAEx_List_*
with DMA_LINKEDLIST_CIRCULAR, one static node/queue per ADC device) so
HAL_ADC_Start_DMA() takes the linked-list branch and continuously
refreshes the buffer. The conversion buffer (destination) is allocated
to GPDMA master PORT1: both ports reach all memories on H5, PORT1 just
has the zero-latency fast bus multiplexer to SRAM (RM0481 fig. 1),
matching the DShot/WS2811 port allocation.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants