1
0
Fork 0
mirror of https://github.com/iNavFlight/inav.git synced 2025-07-24 16:55:29 +03:00

Merge pull request #4235 from iNavFlight/de_timer_fixes

Fixes to timer DMA and DSHOT code
This commit is contained in:
Konstantin Sharlaimov 2019-01-19 21:23:14 +01:00 committed by GitHub
commit 0d0d256073
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 30 additions and 9 deletions

View file

@ -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;

View file

@ -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);

View file

@ -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)

View file

@ -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)

View file

@ -784,7 +784,7 @@ void taskRunRealtimeCallbacks(timeUs_t currentTimeUs)
#endif
#ifdef USE_DSHOT
pwmCompleteDshotUpdate(getMotorCount(), currentTimeUs);
pwmCompleteDshotUpdate(getMotorCount());
#endif
}