diff --git a/src/main/drivers/pwm_output.c b/src/main/drivers/pwm_output.c index 0f15a467f4..94925f941f 100644 --- a/src/main/drivers/pwm_output.c +++ b/src/main/drivers/pwm_output.c @@ -266,8 +266,11 @@ static uint16_t prepareDshotPacket(const uint16_t value, bool requestTelemetry) return packet; } -void pwmCompleteDshotUpdate(uint8_t motorCount, timeUs_t currentTimeUs) +void pwmCompleteDshotUpdate(uint8_t motorCount) { + // Get latest REAL time + timeUs_t currentTimeUs = micros(); + // Enforce motor update rate if (!isProtocolDshot || (dshotMotorUpdateIntervalUs == 0) || ((currentTimeUs - dshotMotorLastUpdateUs) <= dshotMotorUpdateIntervalUs)) { return; diff --git a/src/main/drivers/pwm_output.h b/src/main/drivers/pwm_output.h index 68d7f68160..a7b6adfbf4 100644 --- a/src/main/drivers/pwm_output.h +++ b/src/main/drivers/pwm_output.h @@ -34,7 +34,7 @@ typedef enum { void pwmWriteMotor(uint8_t index, uint16_t value); void pwmShutdownPulsesForAllMotors(uint8_t motorCount); -void pwmCompleteDshotUpdate(uint8_t motorCount, timeUs_t currentTimeUs); +void pwmCompleteDshotUpdate(uint8_t motorCount); bool isMotorProtocolDshot(void); void pwmWriteServo(uint8_t index, uint16_t value); diff --git a/src/main/drivers/timer_impl_hal.c b/src/main/drivers/timer_impl_hal.c index 14f785ac99..1834d84c74 100644 --- a/src/main/drivers/timer_impl_hal.c +++ b/src/main/drivers/timer_impl_hal.c @@ -306,7 +306,11 @@ static void impl_timerDMA_IRQHandler(DMA_t descriptor) { if (DMA_GET_FLAG_STATUS(descriptor, DMA_IT_TCIF)) { TCH_t * tch = (TCH_t *)descriptor->userParam; - tch->dmaState = TCH_DMA_IDLE; + + // If it was ACTIVE - switch to IDLE + if (tch->dmaState == TCH_DMA_ACTIVE) { + tch->dmaState = TCH_DMA_IDLE; + } LL_DMA_DisableStream(tch->dma->dma, lookupDMALLStreamTable[DMATAG_GET_STREAM(tch->timHw->dmaTag)]); LL_TIM_DisableDMAReq_CCx(tch->timHw->tim, lookupDMASourceTable[tch->timHw->channelIndex]); @@ -376,15 +380,20 @@ void impl_timerPWMPrepareDMA(TCH_t * tch, uint32_t dmaBufferSize) const uint32_t streamLL = lookupDMALLStreamTable[DMATAG_GET_STREAM(tch->timHw->dmaTag)]; DMA_TypeDef * dmaBase = tch->dma->dma; - tch->dmaState = TCH_DMA_READY; + // Make sure we terminate any DMA transaction currently in progress + // Clear the flag as well, so even if DMA transfer finishes while within ATOMIC_BLOCK + // the resulting IRQ won't mess up the DMA state + ATOMIC_BLOCK(NVIC_PRIO_MAX) { + LL_TIM_DisableDMAReq_CCx(tch->timHw->tim, lookupDMASourceTable[tch->timHw->channelIndex]); + LL_DMA_DisableStream(dmaBase, streamLL); + DMA_CLEAR_FLAG(tch->dma, DMA_IT_TCIF); + } - LL_TIM_DisableDMAReq_CCx(tch->timHw->tim, lookupDMASourceTable[tch->timHw->channelIndex]); - - LL_DMA_DisableStream(dmaBase, streamLL); LL_DMA_SetDataLength(dmaBase, streamLL, dmaBufferSize); LL_DMA_ConfigAddresses(dmaBase, streamLL, (uint32_t)tch->dmaBuffer, (uint32_t)impl_timerCCR(tch), LL_DMA_DIRECTION_MEMORY_TO_PERIPH); LL_DMA_EnableIT_TC(dmaBase, streamLL); LL_DMA_EnableStream(dmaBase, streamLL); + tch->dmaState = TCH_DMA_READY; } void impl_timerPWMStartDMA(TCH_t * tch) diff --git a/src/main/drivers/timer_impl_stdperiph.c b/src/main/drivers/timer_impl_stdperiph.c index 0c232ffe9f..17ccae91c2 100644 --- a/src/main/drivers/timer_impl_stdperiph.c +++ b/src/main/drivers/timer_impl_stdperiph.c @@ -347,9 +347,18 @@ bool impl_timerPWMConfigChannelDMA(TCH_t * tch, void * dmaBuffer, uint32_t dmaBu void impl_timerPWMPrepareDMA(TCH_t * tch, uint32_t dmaBufferSize) { - tch->dmaState = TCH_DMA_READY; + // Make sure we terminate any DMA transaction currently in progress + // Clear the flag as well, so even if DMA transfer finishes while within ATOMIC_BLOCK + // the resulting IRQ won't mess up the DMA state + ATOMIC_BLOCK(NVIC_PRIO_MAX) { + DMA_Cmd(tch->dma->ref, DISABLE); + TIM_DMACmd(tch->timHw->tim, lookupDMASourceTable[tch->timHw->channelIndex], DISABLE); + DMA_CLEAR_FLAG(tch->dma, DMA_IT_TCIF); + } + DMA_SetCurrDataCounter(tch->dma->ref, dmaBufferSize); DMA_Cmd(tch->dma->ref, ENABLE); + tch->dmaState = TCH_DMA_READY; } void impl_timerPWMStartDMA(TCH_t * tch) diff --git a/src/main/fc/fc_core.c b/src/main/fc/fc_core.c index c2da7bf6d2..a9ce120e2d 100755 --- a/src/main/fc/fc_core.c +++ b/src/main/fc/fc_core.c @@ -784,7 +784,7 @@ void taskRunRealtimeCallbacks(timeUs_t currentTimeUs) #endif #ifdef USE_DSHOT - pwmCompleteDshotUpdate(getMotorCount(), currentTimeUs); + pwmCompleteDshotUpdate(getMotorCount()); #endif }