-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Fix ESC spinup during settings save using circular DMA #11260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
sensei-hacker
wants to merge
8
commits into
iNavFlight:maintenance-9.x
Choose a base branch
from
sensei-hacker:fix/esc-spinup-circular-dshot
base: maintenance-9.x
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Fix ESC spinup during settings save using circular DMA #11260
sensei-hacker
wants to merge
8
commits into
iNavFlight:maintenance-9.x
from
sensei-hacker:fix/esc-spinup-circular-dshot
+163
−0
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
This approach doesn't prevent DShot interruption during EEPROM writes. Committing for potential future refinement. Changes: - Added impl_timerPWMSetDMACircular() to switch DMA mode at runtime - Modified processDelayedSave() to use circular mode during writeEEPROM() - Called pwmCompleteMotorUpdate() 3x to latch DShot 0 packets Issue: DShot still shows gaps during settings save on oscilloscope. Next approach: Test with simple GPIO high instead of DShot.
Move circular DShot DMA code from processDelayedSave() to writeConfigToEEPROM(). This ensures the fix works for MSP_EEPROM_WRITE commands, not just delayed saves. The MSP call path is: MSP_EEPROM_WRITE → writeEEPROM() → writeConfigToEEPROM() → writeSettingsToEEPROM() The previous commit (a6ba116) had circular DMA in processDelayedSave(), which is only called for delayed saves (on disarm), not MSP commands. Changes: - Move circular DMA setup to writeConfigToEEPROM() in config_eeprom.c - Remove unused pwmSetMotorPinsHigh() function - Add pwm_output.h include to config_eeprom.c Test method: - MSP_EEPROM_WRITE command sent once per second - DShot signal monitored on oscilloscope - Confirmed: DShot no longer interrupted during settings save Issue: iNavFlight#10913 Related: iNavFlight#9441
Based on code-reviewer agent feedback: 1. Add missing AT32 platform implementation - Implement impl_timerPWMSetDMACircular() for AT32F43x targets - Uses AT32 loop_mode (ctrl_bit.lm) instead of DMA_SxCR_CIRC 2. Remove duplicate circular DMA code from config.c - processDelayedSave() calls writeEEPROM() which calls writeConfigToEEPROM() - writeConfigToEEPROM() already has circular DMA protection - Removed redundant nested enable/disable from config.c 3. Add ATOMIC_BLOCK protection to DMA mode switch - Consistent with existing impl_timerPWMStopDMA() pattern - Prevents interrupt interference during DMA reconfiguration - Applied to HAL, StdPeriph, and AT32 implementations Issue: iNavFlight#10913
Critical fixes for STM32H7 DMA circular mode: - Wait for EN bit to actually clear before changing mode (was the primary bug) - Disable/re-enable timer DMA requests during reconfiguration - Reload DMA transfer count after mode change - Clear pending DMA flags Without these changes, the mode change was being ignored because the DMA stream was still active when we tried to modify the configuration.
Contributor
PR Compliance Guide 🔍All compliance sections have been disabled in the configurations. |
SITL doesn't have real PWM/motor hardware, so pwmSetMotorDMACircular() and pwmCompleteMotorUpdate() don't exist in SITL builds. Wrap these calls with #if \!defined(SITL_BUILD) to allow SITL builds to compile while preserving the ESC spinup fix for hardware builds.
Address qodo-code-review feedback: Add defensive timeout checks when waiting for DMA streams/channels to disable before reconfiguring. Changes: - H7 (timer_impl_hal.c): Check if timeout expired and abort if DMA still enabled - F4/F7 (timer_impl_stdperiph.c): Add wait loop for EN bit to clear with timeout check - AT32 (timer_impl_stdperiph_at32.c): Add wait loop for chen bit to clear with timeout check This prevents potential race conditions where DMA configuration could be modified while the stream is still active, which could cause unstable behavior.
Some hardware targets don't compile DShot support, causing linker errors when trying to call pwmSetMotorDMACircular() and pwmCompleteMotorUpdate(). Change guard from: #if \!defined(SITL_BUILD) To: #if \!defined(SITL_BUILD) && defined(USE_DSHOT) This ensures the functions are only called on targets that actually have DShot compiled in, fixing build failures on targets like BEEROTORF4.
- config.c: Remove comment about circular DMA protection location (obvious from context) - timer_impl_stdperiph_at32.c: Remove redundant comment about loop mode (already clear from 'Enable loop mode' / 'Disable loop mode' comments)
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.
User description
Summary
Fixes ESC spinup/reboot when saving settings via configurator by enabling DMA circular mode during flash write operations.
Problem
Internal flash writes block CPU core execution for 20-200ms on STM32F4/F7/AT32F43x and STM32H7. This interrupts DShot signal transmission, causing ESCs to timeout and spin up motors.
Solution
Enable DMA circular mode before flash writes to allow DMA hardware to automatically repeat the last DShot packet (zero throttle) without CPU intervention.
Implementation:
DMA_SxCR_CIRCbitLL_DMA_MODE_CIRCULARwith proper synchronization (wait for EN bit clear)ctrl_bit.lm(loop mode)Testing
Tested with oscilloscope monitoring DShot signal during settings save:
Related Issues
Fixes #10913
Note: While related to Betaflight PR #12544, this addresses a different scenario:
INAV does not have the DShot beacon issue - motor values persist during beacon gaps.
PR Type
Bug fix
Description
Prevents ESC spinup during settings save by enabling DMA circular mode
Allows DMA to automatically repeat zero-throttle DShot packets during flash writes
Implements platform-specific circular DMA support for STM32F4/F7/H7 and AT32F43x
Protects DMA reconfiguration with atomic blocks and proper synchronization
Diagram Walkthrough
File Walkthrough
config_eeprom.c
Enable circular DMA during EEPROM writessrc/main/config/config_eeprom.c
pwm_output.hinclude for DMA circular mode controlpwmSetMotorDMACircular(true)before flash writes to enablecircular DMA
pwmCompleteMotorUpdate()calls with delays to latchzero throttle
pwmSetMotorDMACircular(false)after flash writes to restorenormal mode
config.c
Clarify circular DMA protection in delayed savesrc/main/fc/config.c
processDelayedSave()to clarify circular DMAprotection location
function
pwm_output.c
Add motor DMA circular mode control functionsrc/main/drivers/pwm_output.c
pwmSetMotorDMACircular()function to control DMA circularmode
implementation
USE_DSHOTpreprocessor checkpwm_output.h
Export DMA circular mode control functionsrc/main/drivers/pwm_output.h
pwmSetMotorDMACircular()function for public APItimer_impl.h
Add DMA circular mode interface declarationsrc/main/drivers/timer_impl.h
impl_timerPWMSetDMACircular()interfacetimer_impl_hal.c
Implement circular DMA for STM32H7 platformsrc/main/drivers/timer_impl_hal.c
impl_timerPWMSetDMACircular()for STM32H7 using LL driversLL_DMA_MODE_CIRCULARandLL_DMA_MODE_NORMALtimer_impl_stdperiph.c
Implement circular DMA for STM32F4/F7 platformsrc/main/drivers/timer_impl_stdperiph.c
impl_timerPWMSetDMACircular()for STM32F4/F7 usingStdPeriph drivers
DMA_SxCR_CIRCbit based on circular parametertimer_impl_stdperiph_at32.c
Implement circular DMA for AT32F43x platformsrc/main/drivers/timer_impl_stdperiph_at32.c
impl_timerPWMSetDMACircular()for AT32F43x platformctrl_bit.lm(loop mode) based on circular parameter