From f8469ae40e0995276f49357155e57028d8e4e3c2 Mon Sep 17 00:00:00 2001 From: Sami Korhonen Date: Thu, 31 Aug 2017 21:01:36 +0300 Subject: [PATCH] TIM_UP --- src/main/drivers/pwm_output.h | 4 ++ src/main/drivers/pwm_output_dshot_hal.c | 90 ++++++++++++++++++++++++- src/main/drivers/timer.h | 6 ++ src/main/drivers/timer_def.h | 21 ++++++ src/main/drivers/timer_hal.c | 6 -- src/main/target/ANYFCF7/target.c | 8 +-- src/main/target/common_fc_pre.h | 1 + 7 files changed, 124 insertions(+), 12 deletions(-) diff --git a/src/main/drivers/pwm_output.h b/src/main/drivers/pwm_output.h index b895fb50be..5e42ea9047 100644 --- a/src/main/drivers/pwm_output.h +++ b/src/main/drivers/pwm_output.h @@ -108,6 +108,9 @@ typedef enum { typedef struct { TIM_TypeDef *timer; uint16_t timerDmaSources; +#ifdef USE_DSHOT_DMAR + uint32_t dmaBurstBuffer[DSHOT_DMA_BUFFER_SIZE * 4]; +#endif } motorDmaTimer_t; typedef struct { @@ -126,6 +129,7 @@ typedef struct { TIM_HandleTypeDef TimHandle; DMA_HandleTypeDef hdma_tim; uint16_t timerDmaIndex; + uint8_t timerIndex; #endif } motorDmaOutput_t; diff --git a/src/main/drivers/pwm_output_dshot_hal.c b/src/main/drivers/pwm_output_dshot_hal.c index 9cb731a4db..868dc96c32 100644 --- a/src/main/drivers/pwm_output_dshot_hal.c +++ b/src/main/drivers/pwm_output_dshot_hal.c @@ -52,29 +52,61 @@ uint8_t getTimerIndex(TIM_TypeDef *timer) void pwmWriteDshotInt(uint8_t index, uint16_t value) { motorDmaOutput_t *const motor = &dmaMotors[index]; - +#ifdef USE_DSHOT_DMAR + if (!motor->timerHardware || !motor->timerHardware->dmaTimUPRef) { + return; + } +#else if (!motor->timerHardware || !motor->timerHardware->dmaRef) { return; } +#endif uint16_t packet = prepareDshotPacket(motor, value); uint8_t bufferSize = loadDmaBuffer(motor, packet); +#ifdef USE_DSHOT_DMAR + STATIC_ASSERT(TIM_CHANNEL_1==0, tim_channel_0_indexing); + uint8_t channel_index = motor->timerHardware->channel / TIM_CHANNEL_2; + // load channel data into burst buffer + for(int i = 0; i < bufferSize; i++) { + dmaMotorTimers[motor->timerIndex].dmaBurstBuffer[channel_index + i * 4] = motor->dmaBuffer[i]; + } + if(HAL_DMA_STATE_READY == motor->TimHandle.hdma[motor->timerDmaIndex]->State) { + HAL_DMA_Start_IT(motor->TimHandle.hdma[motor->timerDmaIndex], (uint32_t)dmaMotorTimers[motor->timerIndex].dmaBurstBuffer, (uint32_t)&motor->TimHandle.Instance->DMAR, bufferSize * 4); + } +#else if (DMA_SetCurrDataCounter(&motor->TimHandle, motor->timerHardware->channel, motor->dmaBuffer, bufferSize) != HAL_OK) { /* DMA set error */ return; } +#endif } void pwmCompleteDshotMotorUpdate(uint8_t motorCount) { UNUSED(motorCount); for (int i = 0; i < dmaMotorTimerCount; i++) { +#ifdef USE_DSHOT_DMAR + /* configure the DMA Burst Mode */ + LL_TIM_ConfigDMABurst(dmaMotorTimers[i].timer, LL_TIM_DMABURST_BASEADDR_CCR1, LL_TIM_DMABURST_LENGTH_4TRANSFERS); + /* Enable the TIM DMA Request */ + LL_TIM_EnableDMAReq_UPDATE(dmaMotorTimers[i].timer); + /* Reset timer counter */ + LL_TIM_SetCounter(dmaMotorTimers[i].timer, 0); + if(IS_TIM_ADVANCED_INSTANCE(dmaMotorTimers[i].timer) != RESET) { + /* Enable the main output */ + LL_TIM_EnableAllOutputs(dmaMotorTimers[i].timer); + } + /* Enable the counter */ + LL_TIM_EnableCounter(dmaMotorTimers[i].timer); +#else /* Reset timer counter */ LL_TIM_SetCounter(dmaMotorTimers[i].timer, 0); /* Enable channel DMA requests */ dmaMotorTimers[i].timer->DIER |= dmaMotorTimers[i].timerDmaSources; +#endif } } @@ -82,8 +114,13 @@ static void motor_DMA_IRQHandler(dmaChannelDescriptor_t* descriptor) { motorDmaOutput_t * const motor = &dmaMotors[descriptor->userParam]; HAL_DMA_IRQHandler(motor->TimHandle.hdma[motor->timerDmaIndex]); +#ifdef USE_DSHOT_DMAR + LL_TIM_DisableCounter(motor->timerHardware->tim); + LL_TIM_DisableDMAReq_UPDATE(motor->timerHardware->tim); +#else __HAL_DMA_DISABLE(&motor->hdma_tim); TIM_DMACmd(&motor->TimHandle, motor->timerHardware->channel, DISABLE); +#endif } void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t motorIndex, motorPwmProtocolTypes_e pwmProtocolType, uint8_t output) @@ -115,6 +152,34 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m return; } +#ifdef USE_DSHOT_DMAR + motor->timerDmaIndex = TIM_DMA_ID_UPDATE; + /* Set the parameters to be configured */ + motor->hdma_tim.Init.Channel = timerHardware->dmaTimUPChannel; + motor->hdma_tim.Init.Direction = DMA_MEMORY_TO_PERIPH; + motor->hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE; + motor->hdma_tim.Init.MemInc = DMA_MINC_ENABLE; + motor->hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + motor->hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + motor->hdma_tim.Init.Mode = DMA_NORMAL; + motor->hdma_tim.Init.Priority = DMA_PRIORITY_HIGH; + motor->hdma_tim.Init.FIFOMode = DMA_FIFOMODE_ENABLE; + motor->hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + motor->hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE; + motor->hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE; + + /* Set hdma_tim instance */ + if (timerHardware->dmaTimUPRef == NULL) { + /* Initialization Error */ + return; + } + motor->hdma_tim.Instance = timerHardware->dmaTimUPRef; + /* Link hdma_tim to hdma[x] (channelx) */ + __HAL_LINKDMA(&motor->TimHandle, hdma[motor->timerDmaIndex], motor->hdma_tim); + + dmaInit(timerHardware->dmaTimUPIrqHandler, OWNER_MOTOR, RESOURCE_INDEX(motorIndex)); + dmaSetHandler(timerHardware->dmaTimUPIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex); +#else motor->timerDmaIndex = timerDmaIndex(timerHardware->channel); motor->timer = &dmaMotorTimers[timerIndex]; dmaMotorTimers[timerIndex].timerDmaSources |= timerDmaSource(timerHardware->channel); @@ -139,12 +204,12 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m return; } motor->hdma_tim.Instance = timerHardware->dmaRef; - /* Link hdma_tim to hdma[x] (channelx) */ __HAL_LINKDMA(&motor->TimHandle, hdma[motor->timerDmaIndex], motor->hdma_tim); dmaInit(timerHardware->dmaIrqHandler, OWNER_MOTOR, RESOURCE_INDEX(motorIndex)); dmaSetHandler(timerHardware->dmaIrqHandler, motor_DMA_IRQHandler, NVIC_BUILD_PRIORITY(1, 2), motorIndex); +#endif /* Initialize TIMx DMA handle */ if (HAL_DMA_Init(motor->TimHandle.hdma[motor->timerDmaIndex]) != HAL_OK) { @@ -167,6 +232,26 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m /* Configuration Error */ return; } +#ifdef USE_DSHOT_DMAR + /* Enable the Output compare channel */ + uint32_t channels = 0; + switch(motor->timerHardware->channel) { + case TIM_CHANNEL_1: + channels = LL_TIM_CHANNEL_CH1; + break; + case TIM_CHANNEL_2: + channels = LL_TIM_CHANNEL_CH2; + break; + case TIM_CHANNEL_3: + channels = LL_TIM_CHANNEL_CH3; + break; + case TIM_CHANNEL_4: + channels = LL_TIM_CHANNEL_CH4; + break; + } + motor->timerIndex = timerIndex; + LL_TIM_CC_EnableChannel(motor->timerHardware->tim, channels); +#else if (output & TIMER_OUTPUT_N_CHANNEL) { if (HAL_TIMEx_PWMN_Start(&motor->TimHandle, motor->timerHardware->channel) != HAL_OK) { /* Starting PWM generation Error */ @@ -178,6 +263,7 @@ void pwmDshotMotorHardwareConfig(const timerHardware_t *timerHardware, uint8_t m return; } } +#endif } #endif diff --git a/src/main/drivers/timer.h b/src/main/drivers/timer.h index 826c530fda..9e3be13aed 100644 --- a/src/main/drivers/timer.h +++ b/src/main/drivers/timer.h @@ -104,6 +104,12 @@ typedef struct timerHardware_s { DMA_Channel_TypeDef *dmaRef; #endif uint8_t dmaIrqHandler; +#if defined(STM32F7) + // TIMUP + DMA_Stream_TypeDef *dmaTimUPRef; + uint32_t dmaTimUPChannel; + uint8_t dmaTimUPIrqHandler; +#endif #endif } timerHardware_t; diff --git a/src/main/drivers/timer_def.h b/src/main/drivers/timer_def.h index f4bc9c1fb7..b3ed6c1172 100644 --- a/src/main/drivers/timer_def.h +++ b/src/main/drivers/timer_def.h @@ -459,6 +459,11 @@ DEF_TIM_DMA_STREAM(dmaopt, TCH_## tim ## _ ## chan), \ DEF_TIM_DMA_CHANNEL(dmaopt, TCH_## tim ## _ ## chan), \ DEF_TIM_DMA_HANDLER(dmaopt, TCH_## tim ## _ ## chan) \ + ), \ + DEF_TIM_DMA_COND( \ + DEF_TIM_DMA_STREAM(0, TCH_## tim ## _UP), \ + DEF_TIM_DMA_CHANNEL(0, TCH_## tim ## _UP), \ + DEF_TIM_DMA_HANDLER(0, TCH_## tim ## _UP) \ ) \ } \ /**/ @@ -531,6 +536,22 @@ #define DEF_TIM_DMA__BTCH_TIM14_CH1 NONE +// TIM_UP table +#define DEF_TIM_DMA__BTCH_TIM1_UP D(2, 5, 6) +#define DEF_TIM_DMA__BTCH_TIM2_UP D(1, 7, 3) +#define DEF_TIM_DMA__BTCH_TIM3_UP D(1, 2, 5) +#define DEF_TIM_DMA__BTCH_TIM4_UP D(1, 6, 2) +#define DEF_TIM_DMA__BTCH_TIM5_UP D(1, 0, 6) +#define DEF_TIM_DMA__BTCH_TIM6_UP D(1, 1, 7) +#define DEF_TIM_DMA__BTCH_TIM7_UP D(1, 4, 1) +#define DEF_TIM_DMA__BTCH_TIM8_UP D(2, 1, 7) +#define DEF_TIM_DMA__BTCH_TIM9_UP NONE +#define DEF_TIM_DMA__BTCH_TIM10_UP NONE +#define DEF_TIM_DMA__BTCH_TIM11_UP NONE +#define DEF_TIM_DMA__BTCH_TIM12_UP NONE +#define DEF_TIM_DMA__BTCH_TIM13_UP NONE +#define DEF_TIM_DMA__BTCH_TIM14_UP NONE + // AF table //PORTA diff --git a/src/main/drivers/timer_hal.c b/src/main/drivers/timer_hal.c index c26bcf68c2..ea73996995 100644 --- a/src/main/drivers/timer_hal.c +++ b/src/main/drivers/timer_hal.c @@ -929,9 +929,6 @@ uint16_t timerGetPrescalerByDesiredHertz(TIM_TypeDef *tim, uint32_t hz) HAL_StatusTypeDef TIM_DMACmd(TIM_HandleTypeDef *htim, uint32_t Channel, FunctionalState NewState) { - /* Check the parameters */ - assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel)); - switch (Channel) { case TIM_CHANNEL_1: { if (NewState != DISABLE) { @@ -988,9 +985,6 @@ HAL_StatusTypeDef TIM_DMACmd(TIM_HandleTypeDef *htim, uint32_t Channel, Function HAL_StatusTypeDef DMA_SetCurrDataCounter(TIM_HandleTypeDef *htim, uint32_t Channel, uint32_t *pData, uint16_t Length) { - /* Check the parameters */ - assert_param(IS_TIM_CCX_INSTANCE(htim->Instance, Channel)); - if ((htim->State == HAL_TIM_STATE_BUSY)) { return HAL_BUSY; } else if ((htim->State == HAL_TIM_STATE_READY)) { diff --git a/src/main/target/ANYFCF7/target.c b/src/main/target/ANYFCF7/target.c index 34f931a9d3..39885eebd9 100644 --- a/src/main/target/ANYFCF7/target.c +++ b/src/main/target/ANYFCF7/target.c @@ -33,13 +33,13 @@ const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { DEF_TIM(TIM8, CH4, PC9, TIM_USE_PWM, TIMER_INPUT_ENABLED, 0 ), // S6_IN DMA2_ST7 DEF_TIM(TIM4, CH3, PB8, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S10_OUT 1 DMA1_ST7 - DEF_TIM(TIM2, CH3, PA2, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S6_OUT 2 DMA1_ST1 + DEF_TIM(TIM5, CH3, PA2, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S6_OUT 2 DMA1_ST0 DEF_TIM(TIM5, CH2, PA1, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S2_OUT 3 DMA1_ST4 - DEF_TIM(TIM2, CH4, PA3, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 1 ), // S1_OUT 4 DMA1_ST7 DMA1_ST6 - DEF_TIM(TIM3, CH2, PB5, TIM_USE_MOTOR | TIM_USE_LED, TIMER_OUTPUT_ENABLED, 0 ), // S4_OUT DMA1_ST5 + DEF_TIM(TIM5, CH4, PA3, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S1_OUT 4 DMA1_ST1 DMA1_ST3 + DEF_TIM(TIM3, CH2, PB5, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S4_OUT DMA1_ST5 DEF_TIM(TIM5, CH1, PA0, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S7_OUT DMA1_ST2 DEF_TIM(TIM4, CH4, PB9, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S5_OUT DEF_TIM(TIM9, CH2, PE6, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S3_OUT - DEF_TIM(TIM2, CH2, PB3, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S8_OUT DMA1_ST6 + DEF_TIM(TIM2, CH2, PB3, TIM_USE_MOTOR | TIM_USE_LED, TIMER_OUTPUT_ENABLED, 0 ), // S8_OUT DMA1_ST6 DEF_TIM(TIM3, CH1, PB4, TIM_USE_MOTOR, TIMER_OUTPUT_ENABLED, 0 ), // S9_OUT DMA1_ST4 }; diff --git a/src/main/target/common_fc_pre.h b/src/main/target/common_fc_pre.h index 4a64f3ecc7..c801d79205 100644 --- a/src/main/target/common_fc_pre.h +++ b/src/main/target/common_fc_pre.h @@ -54,6 +54,7 @@ #ifdef STM32F7 #define USE_DSHOT +#define USE_DSHOT_DMAR #define USE_ESC_SENSOR #define I2C3_OVERCLOCK true #define I2C4_OVERCLOCK true