Skip to content

Fix DSHOT circular DMA - #11970

Open
error414 wants to merge 2 commits into
iNavFlight:maintenance-10.xfrom
error414:error414/fix/circular-dma-dshot
Open

error414 wants to merge 2 commits into
iNavFlight:maintenance-10.xfrom
error414:error414/fix/circular-dma-dshot

Conversation

@error414

Copy link
Copy Markdown
Contributor

The PR is connected to #11954

Problems:

  1. time between dshot frames if dshot is driven by circular dshot is 4.5us, it's too short time
  2. switching from DMA driven by CPU to circular DSHOT and vice versa does not wait to finish dshot frame, so there was a posibility to create invalid dshot frame

Time to tight:
image

Broken frame:
image

This PR solves both issue, time between dshot frames is set to 40us for circular DMA.

Time space issue solved:
STM32H7
image

STM32F4
image

Broken dshot frame solved (channel 2 is used as marker when is what happend):

STM32H7
image

STM32F4
image

…until dshot frame end to start/end circular dma to avoid brake dshot frame
@qodo-code-review

Copy link
Copy Markdown
Contributor

ⓘ Qodo reviews are paused because the subscription is no longer active. Ask your workspace admin to reactivate the subscription to resume reviews. Manage billing

@qodo-free-for-open-source-projects

Copy link
Copy Markdown

PR Summary by Qodo

Fix DSHOT circular DMA frame spacing and transitions

🐞 Bug fix 🕐 40+ Minutes

Grey Divider

AI Description

• Adds a 40 µs low gap between circular DSHOT keep-alive frames.
• Synchronizes DMA mode transitions to completed frames, preventing malformed DSHOT output.
• Restores normal buffers and stopped DMA state across STM32 and AT32 backends.
Diagram

sequenceDiagram
    participant CPU as Motor Control
    participant Buffer as Keepalive Buffer
    participant DMA as DMA Backend
    participant Timer as PWM Timer
    participant ESC
    CPU->>CPU: Wait for active frame
    CPU->>Buffer: Build zero frame and gap
    CPU->>DMA: Select circular buffer
    DMA->>Timer: Replay frame and padding
    Timer->>ESC: Send zero throttle
    CPU->>Timer: Detect idle padding
    CPU->>DMA: Restore normal buffer
    DMA-->>CPU: Await next motor frame
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Expand each motor DMA buffer
  • ➕ Keeps circular data owned by each motor output.
  • ➕ Avoids switching DMA memory addresses during mode changes.
  • ➖ Increases DMA-safe memory usage for every motor.
  • ➖ Duplicates identical zero-throttle keep-alive data.
  • ➖ Still requires safe synchronization at mode transitions.
2. Interrupt-driven transition state machine
  • ➕ Avoids fixed delays and polling during transitions.
  • ➕ Can switch modes precisely at DMA completion boundaries.
  • ➖ Adds ISR and lifecycle complexity across DMA backends.
  • ➖ Requires careful coordination between burst and per-channel modes.
  • ➖ Raises regression risk in timing-critical motor output code.

Recommendation: Use the PR’s shared padded buffer and bounded transition waits. It minimizes scarce DMA-safe memory and applies consistently to burst and per-channel implementations; an interrupt-driven state machine would only be preferable if transition latency becomes performance-critical. The malformed nemvoid declaration in the HAL burst implementation must be corrected before merge.

Files changed (6) +141 / -33

Bug fix (6) +141 / -33
light_ws2811strip.cPass the WS2811 buffer when enabling circular DMA +1/-1

Pass the WS2811 buffer when enabling circular DMA

• Updates the LED-strip caller for the expanded circular-DMA API by supplying its DMA buffer explicitly.

src/main/drivers/light_ws2811strip.c

pwm_output.cAdd padded DSHOT keep-alives and synchronized DMA transitions +82/-9

Add padded DSHOT keep-alives and synchronized DMA transitions

• Introduces a shared zero-throttle keep-alive buffer sized for a 40 µs low gap at each supported DSHOT rate. Waits for active frames or keep-alive data to finish before switching modes, restores normal buffers on exit, and forces motor outputs low after stopping circular DMA.

src/main/drivers/pwm_output.c

timer_impl.hExtend circular-DMA APIs with explicit buffers +2/-2

Extend circular-DMA APIs with explicit buffers

• Adds DMA buffer pointers to the per-channel and burst circular-mode interfaces so callers can switch between normal and keep-alive storage.

src/main/drivers/timer_impl.h

timer_impl_hal.cSwitch HAL DMA buffers safely between operating modes +23/-9

Switch HAL DMA buffers safely between operating modes

• Reconfigures memory addresses and transfer lengths while streams are disabled, and only restarts streams when entering circular mode. The displayed burst function declaration contains a malformed 'nemvoid' token that must be corrected to 'void'.

src/main/drivers/timer_impl_hal.c

timer_impl_stdperiph.cSwitch STM32 StdPeriph DMA buffers safely +22/-8

Switch STM32 StdPeriph DMA buffers safely

• Updates burst and per-channel STM32 DMA implementations to install the requested buffer while disabled. Returning to normal mode now leaves DMA stopped until the next frame is explicitly prepared and started.

src/main/drivers/timer_impl_stdperiph.c

timer_impl_stdperiph_at32.cSwitch AT32 DMA buffers safely +11/-4

Switch AT32 DMA buffers safely

• Programs the requested memory address and transfer count while the AT32 DMA channel is disabled. Normal mode remains stopped until the regular motor-frame start path runs.

src/main/drivers/timer_impl_stdperiph_at32.c

@qodo-free-for-open-source-projects

qodo-free-for-open-source-projects Bot commented Sep 18, 2026

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (0) 📎 Requirement gaps (0) 🎨 UX issues (0) 🔗 Cross-repo conflicts (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Some motor firmware fails to compile ✓ Resolved 🐞 Bug ≡ Correctness
Description
impl_pwmBurstDMASetCircular is defined with the invalid return-type token nemvoid instead of
void. Any HAL target enabling burst DMA compiles this section, so compilation stops before the
motor output code can be linked.
Code

src/main/drivers/timer_impl_hal.c[543]

+nemvoid impl_pwmBurstDMASetCircular(burstDmaTimer_t * burstDmaTimer, TCH_t * tch, bool circular, void * dmaBuffer, uint32_t dmaBufferSize)
Evidence
The implementation contains the invalid token while the public declaration requires a void return
type. AXISFLYINGH743PRO explicitly enables the build condition that includes this implementation,
demonstrating that a supported target is affected.

src/main/drivers/timer_impl_hal.c[543-544]
src/main/drivers/timer_impl.h[90-93]
src/main/target/AXISFLYINGH743PRO/target.h[59-63]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The burst-DMA implementation uses `nemvoid`, which is not a valid C return type and causes affected HAL firmware builds to fail.
## Fix Focus Areas
- src/main/drivers/timer_impl_hal.c[543-543]
## Recommended Fix
Replace `nemvoid` with `void` so the implementation matches the declaration in `timer_impl.h` and compiles for HAL targets using burst DMA.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Tip of the day
💡 Did you know, you can type 'qodo, fix this' on a finding and the fix lands right on your PR

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread src/main/drivers/timer_impl_hal.c Outdated
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.

1 participant