diff --git a/src/main/drivers/light_ws2811strip_hal.c b/src/main/drivers/light_ws2811strip_hal.c index 2a950330f..b4bf97196 100644 --- a/src/main/drivers/light_ws2811strip_hal.c +++ b/src/main/drivers/light_ws2811strip_hal.c @@ -68,7 +68,7 @@ void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim) ws2811IO = IOGetByTag(IO_TAG(WS2811_PIN)); /* GPIOA Configuration: TIM5 Channel 1 as alternate function push-pull */ IOInit(ws2811IO, OWNER_LED_STRIP, RESOURCE_OUTPUT, 0); - IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP), timerGPIOAF(WS2811_TIMER)); + //IOConfigGPIOAF(ws2811IO, IO_CONFIG(GPIO_MODE_AF_PP, GPIO_SPEED_FREQ_VERY_HIGH, GPIO_PULLUP), timerGPIOAF(WS2811_TIMER)); __TIM5_CLK_ENABLE(); __DMA1_CLK_ENABLE(); diff --git a/src/main/drivers/pwm_output_hal.c b/src/main/drivers/pwm_output_hal.c index 94bddfb12..290b38600 100644 --- a/src/main/drivers/pwm_output_hal.c +++ b/src/main/drivers/pwm_output_hal.c @@ -29,6 +29,7 @@ #define MULTISHOT_20US_MULT (MULTISHOT_TIMER_MHZ * 20 / 1000.0f) static pwmOutputPort_t motors[MAX_SUPPORTED_MOTORS]; +static pwmCompleteWriteFuncPtr pwmCompleteWritePtr = NULL; #ifdef USE_SERVOS static pwmOutputPort_t servos[MAX_SUPPORTED_SERVOS]; @@ -139,7 +140,7 @@ void pwmEnableMotors(void) pwmMotorsEnabled = true; } -void pwmCompleteOneshotMotorUpdate(uint8_t motorCount) +static void pwmCompleteOneshotMotorUpdate(uint8_t motorCount) { for (int index = 0; index < motorCount; index++) { bool overflowed = false; @@ -159,40 +160,59 @@ void pwmCompleteOneshotMotorUpdate(uint8_t motorCount) } } +void pwmCompleteMotorUpdate(uint8_t motorCount) +{ + if (pwmCompleteWritePtr) { + pwmCompleteWritePtr(motorCount); + } +} + void motorInit(const motorConfig_t *motorConfig, uint16_t idlePulse, uint8_t motorCount) { uint32_t timerMhzCounter; pwmWriteFuncPtr pwmWritePtr; bool useUnsyncedPwm = motorConfig->useUnsyncedPwm; - + bool isDigital = false; + switch (motorConfig->motorPwmProtocol) { default: - case (PWM_TYPE_ONESHOT125): + case PWM_TYPE_ONESHOT125: timerMhzCounter = ONESHOT125_TIMER_MHZ; pwmWritePtr = pwmWriteOneShot125; break; - case (PWM_TYPE_ONESHOT42): + case PWM_TYPE_ONESHOT42: timerMhzCounter = ONESHOT42_TIMER_MHZ; pwmWritePtr = pwmWriteOneShot42; break; - case (PWM_TYPE_MULTISHOT): + case PWM_TYPE_MULTISHOT: timerMhzCounter = MULTISHOT_TIMER_MHZ; pwmWritePtr = pwmWriteMultiShot; break; - case (PWM_TYPE_BRUSHED): + case PWM_TYPE_BRUSHED: timerMhzCounter = PWM_BRUSHED_TIMER_MHZ; pwmWritePtr = pwmWriteBrushed; useUnsyncedPwm = true; idlePulse = 0; break; - case (PWM_TYPE_STANDARD): + case PWM_TYPE_STANDARD: timerMhzCounter = PWM_TIMER_MHZ; pwmWritePtr = pwmWriteStandard; useUnsyncedPwm = true; idlePulse = 0; break; +#ifdef USE_DSHOT + case PWM_TYPE_DSHOT600: + case PWM_TYPE_DSHOT150: + pwmCompleteWritePtr = pwmCompleteDigitalMotorUpdate; + isDigital = true; + break; +#endif } + if (!useUnsyncedPwm && !isDigital) { + pwmCompleteWritePtr = pwmCompleteOneshotMotorUpdate; + } + for (int motorIndex = 0; motorIndex < MAX_SUPPORTED_MOTORS && motorIndex < motorCount; motorIndex++) { const ioTag_t tag = motorConfig->ioTags[motorIndex]; @@ -200,31 +220,44 @@ void motorInit(const motorConfig_t *motorConfig, uint16_t idlePulse, uint8_t mot break; } - motors[motorIndex].io = IOGetByTag(tag); + const timerHardware_t *timerHardware = timerGetByTag(tag, TIMER_OUTPUT_ENABLED); - IOInit(motors[motorIndex].io, OWNER_MOTOR, RESOURCE_OUTPUT, RESOURCE_INDEX(motorIndex)); - - const timerHardware_t *timer = timerGetByTag(tag, TIMER_OUTPUT_ENABLED); - - IOConfigGPIOAF(motors[motorIndex].io, IOCFG_AF_PP, timerGPIOAF(timer->tim)); - - if (timer == NULL) { + if (timerHardware == NULL) { /* flag failure and disable ability to arm */ break; } + +#ifdef USE_DSHOT + if (isDigital) { + pwmDigitalMotorHardwareConfig(timerHardware, motorIndex, motorConfig->motorPwmProtocol); + motors[motorIndex].pwmWritePtr = pwmWriteDigital; + motors[motorIndex].enabled = true; + continue; + } +#endif + motors[motorIndex].io = IOGetByTag(tag); + + IOInit(motors[motorIndex].io, OWNER_MOTOR, RESOURCE_OUTPUT, RESOURCE_INDEX(motorIndex)); + //IOConfigGPIO(motors[motorIndex].io, IOCFG_AF_PP); + IOConfigGPIOAF(motors[motorIndex].io, IOCFG_AF_PP, timerHardware->alternateFunction); motors[motorIndex].pwmWritePtr = pwmWritePtr; if (useUnsyncedPwm) { const uint32_t hz = timerMhzCounter * 1000000; - pwmOutConfig(&motors[motorIndex], timer, timerMhzCounter, hz / motorConfig->motorPwmProtocol, idlePulse); + pwmOutConfig(&motors[motorIndex], timerHardware, timerMhzCounter, hz / motorConfig->motorPwmProtocol, idlePulse); } else { - pwmOutConfig(&motors[motorIndex], timer, timerMhzCounter, 0xFFFF, 0); + pwmOutConfig(&motors[motorIndex], timerHardware, timerMhzCounter, 0xFFFF, 0); } motors[motorIndex].enabled = true; } } -pwmOutputPort_t *pwmGetMotors() +bool pwmIsSynced(void) +{ + return pwmCompleteWritePtr != NULL; +} + +pwmOutputPort_t *pwmGetMotors(void) { return motors; } @@ -249,11 +282,11 @@ void servoInit(const servoConfig_t *servoConfig) servos[servoIndex].io = IOGetByTag(tag); IOInit(servos[servoIndex].io, OWNER_SERVO, RESOURCE_OUTPUT, RESOURCE_INDEX(servoIndex)); + //IOConfigGPIO(servos[servoIndex].io, IOCFG_AF_PP); const timerHardware_t *timer = timerGetByTag(tag, TIMER_OUTPUT_ENABLED); + IOConfigGPIOAF(servos[servoIndex].io, IOCFG_AF_PP, timer->alternateFunction); - IOConfigGPIOAF(servos[servoIndex].io, IOCFG_AF_PP, timerGPIOAF(timer->tim)); - if (timer == NULL) { /* flag failure and disable ability to arm */ break; diff --git a/src/main/drivers/timer_hal.c b/src/main/drivers/timer_hal.c index 1c8ac7435..05c01a521 100644 --- a/src/main/drivers/timer_hal.c +++ b/src/main/drivers/timer_hal.c @@ -56,7 +56,7 @@ typedef struct timerConfig_s { timerCCHandlerRec_t *edgeCallback[CC_CHANNELS_PER_TIMER]; timerOvrHandlerRec_t *overflowCallback[CC_CHANNELS_PER_TIMER]; timerOvrHandlerRec_t *overflowCallbackActive; // null-terminated linkded list of active overflow callbacks - uint32_t forcedOverflowTimerValue; + uint32_t forcedOverflowTimerValue; } timerConfig_t; timerConfig_t timerConfig[USED_TIMER_COUNT+1]; @@ -74,7 +74,7 @@ typedef struct { TIM_HandleTypeDef Handle; } timerHandle_t; -timerHandle_t timeHandle[USED_TIMER_COUNT+1]; +timerHandle_t timerHandle[USED_TIMER_COUNT+1]; // return index of timer in timer table. Lowest timer has index 0 #define TIMER_INDEX(i) BITCOUNT((TIM_N(i) - 1) & USED_TIMERS) @@ -216,19 +216,6 @@ rccPeriphTag_t timerRCC(TIM_TypeDef *tim) return 0; } -#if defined(STM32F7) -uint8_t timerGPIOAF(TIM_TypeDef *tim) -{ - for (uint8_t i = 0; i < HARDWARE_TIMER_DEFINITION_COUNT; i++) { - if (timerDefinitions[i].TIMx == tim) { - return timerDefinitions[i].alternateFunction; - } - } - return 0; -} -#endif - - void timerNVICConfigure(uint8_t irq) { HAL_NVIC_SetPriority(irq, NVIC_PRIORITY_BASE(NVIC_PRIO_TIMER), NVIC_PRIORITY_SUB(NVIC_PRIO_TIMER)); @@ -241,7 +228,7 @@ TIM_HandleTypeDef* timerFindTimerHandle(TIM_TypeDef *tim) if (timerIndex >= USED_TIMER_COUNT) return NULL; - return &timeHandle[timerIndex].Handle; + return &timerHandle[timerIndex].Handle; } void configTimeBase(TIM_TypeDef *tim, uint16_t period, uint8_t mhz) @@ -250,30 +237,27 @@ void configTimeBase(TIM_TypeDef *tim, uint16_t period, uint8_t mhz) if (timerIndex >= USED_TIMER_COUNT) { return; } - if(timeHandle[timerIndex].Handle.Instance == tim) + if(timerHandle[timerIndex].Handle.Instance == tim) { // already configured return; } - timeHandle[timerIndex].Handle.Instance = tim; + timerHandle[timerIndex].Handle.Instance = tim; - timeHandle[timerIndex].Handle.Init.Period = (period - 1) & 0xffff; // AKA TIMx_ARR - if(tim == TIM1 || tim == TIM8 || tim == TIM9 || tim == TIM10 || tim == TIM11) - timeHandle[timerIndex].Handle.Init.Prescaler = (HAL_RCC_GetPCLK2Freq() * 2 / ((uint32_t)mhz * 1000000)) - 1; - else - timeHandle[timerIndex].Handle.Init.Prescaler = (HAL_RCC_GetPCLK1Freq() * 2 * 2 / ((uint32_t)mhz * 1000000)) - 1; + timerHandle[timerIndex].Handle.Init.Period = (period - 1) & 0xffff; // AKA TIMx_ARR + timerHandle[timerIndex].Handle.Init.Prescaler = (SystemCoreClock / timerClockDivisor(tim) / ((uint32_t)mhz * 1000000)) - 1; - timeHandle[timerIndex].Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; - timeHandle[timerIndex].Handle.Init.CounterMode = TIM_COUNTERMODE_UP; - timeHandle[timerIndex].Handle.Init.RepetitionCounter = 0x0000; + timerHandle[timerIndex].Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + timerHandle[timerIndex].Handle.Init.CounterMode = TIM_COUNTERMODE_UP; + timerHandle[timerIndex].Handle.Init.RepetitionCounter = 0x0000; - HAL_TIM_Base_Init(&timeHandle[timerIndex].Handle); + HAL_TIM_Base_Init(&timerHandle[timerIndex].Handle); if(tim == TIM1 || tim == TIM2 || tim == TIM3 || tim == TIM4 || tim == TIM5 || tim == TIM8 || tim == TIM9) { TIM_ClockConfigTypeDef sClockSourceConfig; sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL; - if (HAL_TIM_ConfigClockSource(&timeHandle[timerIndex].Handle, &sClockSourceConfig) != HAL_OK) + if (HAL_TIM_ConfigClockSource(&timerHandle[timerIndex].Handle, &sClockSourceConfig) != HAL_OK) { return; } @@ -283,7 +267,7 @@ void configTimeBase(TIM_TypeDef *tim, uint16_t period, uint8_t mhz) TIM_MasterConfigTypeDef sMasterConfig; sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; - if (HAL_TIMEx_MasterConfigSynchronization(&timeHandle[timerIndex].Handle, &sMasterConfig) != HAL_OK) + if (HAL_TIMEx_MasterConfigSynchronization(&timerHandle[timerIndex].Handle, &sMasterConfig) != HAL_OK) { return; } @@ -300,7 +284,7 @@ void timerConfigure(const timerHardware_t *timerHardwarePtr, uint16_t period, ui } configTimeBase(timerHardwarePtr->tim, period, mhz); - HAL_TIM_Base_Start(&timeHandle[timerIndex].Handle); + HAL_TIM_Base_Start(&timerHandle[timerIndex].Handle); timerNVICConfigure(timerHardwarePtr->irq); // HACK - enable second IRQ on timers that need it switch(timerHardwarePtr->irq) { @@ -333,7 +317,7 @@ void timerChInit(const timerHardware_t *timHw, channelType_t type, int irqPriori if(irqPriority < timerInfo[timer].priority) { // it would be better to set priority in the end, but current startup sequence is not ready configTimeBase(usedTimers[timer], 0, 1); - HAL_TIM_Base_Start(&timeHandle[timerIndex].Handle); + HAL_TIM_Base_Start(&timerHandle[timerIndex].Handle); HAL_NVIC_SetPriority(timHw->irq, NVIC_PRIORITY_BASE(irqPriority), NVIC_PRIORITY_SUB(irqPriority)); @@ -373,9 +357,9 @@ static void timerChConfig_UpdateOverflow(timerConfig_t *cfg, TIM_TypeDef *tim) { } // enable or disable IRQ if(cfg->overflowCallbackActive) - __HAL_TIM_ENABLE_IT(&timeHandle[timerIndex].Handle, TIM_IT_UPDATE); + __HAL_TIM_ENABLE_IT(&timerHandle[timerIndex].Handle, TIM_IT_UPDATE); else - __HAL_TIM_DISABLE_IT(&timeHandle[timerIndex].Handle, TIM_IT_UPDATE); + __HAL_TIM_DISABLE_IT(&timerHandle[timerIndex].Handle, TIM_IT_UPDATE); } // config edge and overflow callback for channel. Try to avoid overflowCallback, it is a bit expensive @@ -387,13 +371,13 @@ void timerChConfigCallbacks(const timerHardware_t *timHw, timerCCHandlerRec_t *e } uint8_t channelIndex = lookupChannelIndex(timHw->channel); if(edgeCallback == NULL) // disable irq before changing callback to NULL - __HAL_TIM_DISABLE_IT(&timeHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel)); + __HAL_TIM_DISABLE_IT(&timerHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel)); // setup callback info timerConfig[timerIndex].edgeCallback[channelIndex] = edgeCallback; timerConfig[timerIndex].overflowCallback[channelIndex] = overflowCallback; // enable channel IRQ if(edgeCallback) - __HAL_TIM_ENABLE_IT(&timeHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel)); + __HAL_TIM_ENABLE_IT(&timerHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel)); timerChConfig_UpdateOverflow(&timerConfig[timerIndex], timHw->tim); } @@ -412,9 +396,9 @@ void timerChConfigCallbacksDual(const timerHardware_t *timHw, timerCCHandlerRec_ uint8_t channelIndex = lookupChannelIndex(chLo); // get index of lower channel if(edgeCallbackLo == NULL) // disable irq before changing setting callback to NULL - __HAL_TIM_DISABLE_IT(&timeHandle[timerIndex].Handle, TIM_IT_CCx(chLo)); + __HAL_TIM_DISABLE_IT(&timerHandle[timerIndex].Handle, TIM_IT_CCx(chLo)); if(edgeCallbackHi == NULL) // disable irq before changing setting callback to NULL - __HAL_TIM_DISABLE_IT(&timeHandle[timerIndex].Handle, TIM_IT_CCx(chHi)); + __HAL_TIM_DISABLE_IT(&timerHandle[timerIndex].Handle, TIM_IT_CCx(chHi)); // setup callback info timerConfig[timerIndex].edgeCallback[channelIndex] = edgeCallbackLo; @@ -424,12 +408,12 @@ void timerChConfigCallbacksDual(const timerHardware_t *timHw, timerCCHandlerRec_ // enable channel IRQs if(edgeCallbackLo) { - __HAL_TIM_CLEAR_FLAG(&timeHandle[timerIndex].Handle, TIM_IT_CCx(chLo)); - __HAL_TIM_ENABLE_IT(&timeHandle[timerIndex].Handle, TIM_IT_CCx(chLo)); + __HAL_TIM_CLEAR_FLAG(&timerHandle[timerIndex].Handle, TIM_IT_CCx(chLo)); + __HAL_TIM_ENABLE_IT(&timerHandle[timerIndex].Handle, TIM_IT_CCx(chLo)); } if(edgeCallbackHi) { - __HAL_TIM_CLEAR_FLAG(&timeHandle[timerIndex].Handle, TIM_IT_CCx(chHi)); - __HAL_TIM_ENABLE_IT(&timeHandle[timerIndex].Handle, TIM_IT_CCx(chHi)); + __HAL_TIM_CLEAR_FLAG(&timerHandle[timerIndex].Handle, TIM_IT_CCx(chHi)); + __HAL_TIM_ENABLE_IT(&timerHandle[timerIndex].Handle, TIM_IT_CCx(chHi)); } timerChConfig_UpdateOverflow(&timerConfig[timerIndex], timHw->tim); @@ -447,9 +431,9 @@ void timerChITConfigDualLo(const timerHardware_t *timHw, FunctionalState newStat } if(newState) - __HAL_TIM_ENABLE_IT(&timeHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel&~TIM_CHANNEL_2)); + __HAL_TIM_ENABLE_IT(&timerHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel&~TIM_CHANNEL_2)); else - __HAL_TIM_DISABLE_IT(&timeHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel&~TIM_CHANNEL_2)); + __HAL_TIM_DISABLE_IT(&timerHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel&~TIM_CHANNEL_2)); } //// enable or disable IRQ @@ -466,9 +450,9 @@ void timerChITConfig(const timerHardware_t *timHw, FunctionalState newState) } if(newState) - __HAL_TIM_ENABLE_IT(&timeHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel)); + __HAL_TIM_ENABLE_IT(&timerHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel)); else - __HAL_TIM_DISABLE_IT(&timeHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel)); + __HAL_TIM_DISABLE_IT(&timerHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel)); } // clear Compare/Capture flag for channel @@ -484,7 +468,7 @@ void timerChClearCCFlag(const timerHardware_t *timHw) return; } - __HAL_TIM_CLEAR_FLAG(&timeHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel)); + __HAL_TIM_CLEAR_FLAG(&timerHandle[timerIndex].Handle, TIM_IT_CCx(timHw->channel)); } // configure timer channel GPIO mode @@ -527,7 +511,7 @@ void timerChConfigIC(const timerHardware_t *timHw, bool polarityRising, unsigned TIM_ICInitStructure.ICSelection = TIM_ICSELECTION_DIRECTTI; TIM_ICInitStructure.ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.ICFilter = getFilter(inputFilterTicks); - HAL_TIM_IC_ConfigChannel(&timeHandle[timer].Handle,&TIM_ICInitStructure, timHw->channel); + HAL_TIM_IC_ConfigChannel(&timerHandle[timer].Handle,&TIM_ICInitStructure, timHw->channel); } // configure dual channel input channel for capture @@ -546,12 +530,12 @@ void timerChConfigICDual(const timerHardware_t *timHw, bool polarityRising, unsi TIM_ICInitStructure.ICSelection = TIM_ICSELECTION_DIRECTTI; TIM_ICInitStructure.ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.ICFilter = getFilter(inputFilterTicks); - HAL_TIM_IC_ConfigChannel(&timeHandle[timer].Handle,&TIM_ICInitStructure, timHw->channel); + HAL_TIM_IC_ConfigChannel(&timerHandle[timer].Handle,&TIM_ICInitStructure, timHw->channel); // configure indirect channel TIM_ICInitStructure.ICPolarity = directRising ? TIM_ICPOLARITY_FALLING : TIM_ICPOLARITY_RISING; TIM_ICInitStructure.ICSelection = TIM_ICSELECTION_INDIRECTTI; - HAL_TIM_IC_ConfigChannel(&timeHandle[timer].Handle,&TIM_ICInitStructure, timHw->channel ^ TIM_CHANNEL_2); + HAL_TIM_IC_ConfigChannel(&timerHandle[timer].Handle,&TIM_ICInitStructure, timHw->channel ^ TIM_CHANNEL_2); } void timerChICPolarity(const timerHardware_t *timHw, bool polarityRising) @@ -594,16 +578,16 @@ void timerChConfigOC(const timerHardware_t* timHw, bool outEnable, bool stateHig TIM_OCInitStructure.OCIdleState = TIM_OCIDLESTATE_RESET; TIM_OCInitStructure.OCNIdleState = TIM_OCNIDLESTATE_RESET; - HAL_TIM_OC_ConfigChannel(&timeHandle[timer].Handle, &TIM_OCInitStructure, timHw->channel); + HAL_TIM_OC_ConfigChannel(&timerHandle[timer].Handle, &TIM_OCInitStructure, timHw->channel); if(outEnable) { TIM_OCInitStructure.OCMode = TIM_OCMODE_INACTIVE; - HAL_TIM_OC_ConfigChannel(&timeHandle[timer].Handle, &TIM_OCInitStructure, timHw->channel); - HAL_TIM_OC_Start(&timeHandle[timer].Handle, timHw->channel); + HAL_TIM_OC_ConfigChannel(&timerHandle[timer].Handle, &TIM_OCInitStructure, timHw->channel); + HAL_TIM_OC_Start(&timerHandle[timer].Handle, timHw->channel); } else { TIM_OCInitStructure.OCMode = TIM_OCMODE_TIMING; - HAL_TIM_OC_ConfigChannel(&timeHandle[timer].Handle, &TIM_OCInitStructure, timHw->channel); - HAL_TIM_OC_Start_IT(&timeHandle[timer].Handle, timHw->channel); + HAL_TIM_OC_ConfigChannel(&timerHandle[timer].Handle, &TIM_OCInitStructure, timHw->channel); + HAL_TIM_OC_Start_IT(&timerHandle[timer].Handle, timHw->channel); } } @@ -680,7 +664,6 @@ static void timCCxHandler(TIM_TypeDef *tim, timerConfig_t *timerConfig) #endif } - // handler for shared interrupts when both timers need to check status bits #define _TIM_IRQ_HANDLER2(name, i, j) \ void name(void) \ @@ -698,7 +681,7 @@ static void timCCxHandler(TIM_TypeDef *tim, timerConfig_t *timerConfig) #if USED_TIMERS & TIM_N(1) _TIM_IRQ_HANDLER(TIM1_CC_IRQHandler, 1); # if USED_TIMERS & TIM_N(10) -_TIM_IRQ_HANDLER2(TIM1_UP_TIM10_IRQHandler, 1,10); // both timers are in use +_TIM_IRQ_HANDLER2(TIM1_UP_TIM10_IRQHandler, 1, 10); // both timers are in use # else _TIM_IRQ_HANDLER(TIM1_UP_TIM10_IRQHandler, 1); // timer10 is not used # endif @@ -721,7 +704,7 @@ _TIM_IRQ_HANDLER(TIM5_IRQHandler, 5); _TIM_IRQ_HANDLER(TIM8_CC_IRQHandler, 8); # if USED_TIMERS & TIM_N(13) -_TIM_IRQ_HANDLER2(TIM8_UP_TIM13_IRQHandler, 8,13); // both timers are in use +_TIM_IRQ_HANDLER2(TIM8_UP_TIM13_IRQHandler, 8, 13); // both timers are in use # else _TIM_IRQ_HANDLER(TIM8_UP_TIM13_IRQHandler, 8); // timer13 is not used # endif @@ -803,10 +786,15 @@ void timerInit(void) __HAL_RCC_TIM17_CLK_ENABLE(); #endif + /* enable the timer peripherals */ + for (uint8_t i = 0; i < USABLE_TIMER_CHANNEL_COUNT; i++) { + RCC_ClockCmd(timerRCC(timerHardware[i].tim), ENABLE); + } + #if defined(STM32F3) || defined(STM32F4) || defined(STM32F7) for (uint8_t timerIndex = 0; timerIndex < USABLE_TIMER_CHANNEL_COUNT; timerIndex++) { const timerHardware_t *timerHardwarePtr = &timerHardware[timerIndex]; - IOConfigGPIOAF(IOGetByTag(timerHardwarePtr->tag), timerHardwarePtr->ioMode, timerGPIOAF(timerHardwarePtr->tim)); + IOConfigGPIOAF(IOGetByTag(timerHardwarePtr->tag), timerHardwarePtr->ioMode, timerHardwarePtr->alternateFunction); } #endif @@ -874,7 +862,7 @@ const timerHardware_t *timerGetByTag(ioTag_t tag, timerFlag_e flag) if (timerHardware[i].tag == tag) { if (flag && (timerHardware[i].output & flag) == flag) { return &timerHardware[i]; - } else if (!flag && timerHardware[i].output == flag) { + } else if (!flag && timerHardware[i].output == flag) { // TODO: shift flag by one so not to be 0 return &timerHardware[i]; } diff --git a/src/main/drivers/timer_stm32f7xx.c b/src/main/drivers/timer_stm32f7xx.c index 22379733c..180116c0f 100644 --- a/src/main/drivers/timer_stm32f7xx.c +++ b/src/main/drivers/timer_stm32f7xx.c @@ -13,8 +13,8 @@ #include "common/utils.h" #include "stm32f7xx.h" -#include "timer.h" #include "rcc.h" +#include "timer.h" /** * @brief Selects the TIM Output Compare Mode. @@ -42,22 +42,63 @@ #define CCMR_Offset ((uint16_t)0x0018) const timerDef_t timerDefinitions[HARDWARE_TIMER_DEFINITION_COUNT] = { - { .TIMx = TIM1, .rcc = RCC_APB2(TIM1), GPIO_AF1_TIM1 }, - { .TIMx = TIM2, .rcc = RCC_APB1(TIM2), GPIO_AF1_TIM2 }, - { .TIMx = TIM3, .rcc = RCC_APB1(TIM3), GPIO_AF2_TIM3 }, - { .TIMx = TIM4, .rcc = RCC_APB1(TIM4), GPIO_AF2_TIM4 }, - { .TIMx = TIM5, .rcc = RCC_APB1(TIM5), GPIO_AF2_TIM5 }, - { .TIMx = TIM6, .rcc = RCC_APB1(TIM6), 0 }, - { .TIMx = TIM7, .rcc = RCC_APB1(TIM7), 0 }, - { .TIMx = TIM8, .rcc = RCC_APB2(TIM8), GPIO_AF3_TIM8 }, - { .TIMx = TIM9, .rcc = RCC_APB2(TIM9), GPIO_AF3_TIM9 }, - { .TIMx = TIM10, .rcc = RCC_APB2(TIM10), GPIO_AF3_TIM10 }, - { .TIMx = TIM11, .rcc = RCC_APB2(TIM11), GPIO_AF3_TIM11 }, - { .TIMx = TIM12, .rcc = RCC_APB1(TIM12), GPIO_AF9_TIM12 }, - { .TIMx = TIM13, .rcc = RCC_APB1(TIM13), GPIO_AF9_TIM13 }, - { .TIMx = TIM14, .rcc = RCC_APB1(TIM14), GPIO_AF9_TIM14 }, + { .TIMx = TIM1, .rcc = RCC_APB2(TIM1) }, + { .TIMx = TIM2, .rcc = RCC_APB1(TIM2) }, + { .TIMx = TIM3, .rcc = RCC_APB1(TIM3) }, + { .TIMx = TIM4, .rcc = RCC_APB1(TIM4) }, + { .TIMx = TIM5, .rcc = RCC_APB1(TIM5) }, + { .TIMx = TIM6, .rcc = RCC_APB1(TIM6) }, + { .TIMx = TIM7, .rcc = RCC_APB1(TIM7) }, + { .TIMx = TIM8, .rcc = RCC_APB2(TIM8) }, + { .TIMx = TIM9, .rcc = RCC_APB2(TIM9) }, + { .TIMx = TIM10, .rcc = RCC_APB2(TIM10) }, + { .TIMx = TIM11, .rcc = RCC_APB2(TIM11) }, + { .TIMx = TIM12, .rcc = RCC_APB1(TIM12) }, + { .TIMx = TIM13, .rcc = RCC_APB1(TIM13) }, + { .TIMx = TIM14, .rcc = RCC_APB1(TIM14) }, }; +/* + need a mapping from dma and timers to pins, and the values should all be set here to the dmaMotors array. + this mapping could be used for both these motors and for led strip. + + only certain pins have OC output (already used in normal PWM et al) but then + there are only certain DMA streams/channels available for certain timers and channels. + *** (this may highlight some hardware limitations on some targets) *** + + DMA1 + + Channel Stream0 Stream1 Stream2 Stream3 Stream4 Stream5 Stream6 Stream7 + 0 + 1 + 2 TIM4_CH1 TIM4_CH2 TIM4_CH3 + 3 TIM2_CH3 TIM2_CH1 TIM2_CH1 TIM2_CH4 + TIM2_CH4 + 4 + 5 TIM3_CH4 TIM3_CH1 TIM3_CH2 TIM3_CH3 + 6 TIM5_CH3 TIM5_CH4 TIM5_CH1 TIM5_CH4 TIM5_CH2 + 7 + + DMA2 + + Channel Stream0 Stream1 Stream2 Stream3 Stream4 Stream5 Stream6 Stream7 + 0 TIM8_CH1 TIM1_CH1 + TIM8_CH2 TIM1_CH2 + TIM8_CH3 TIM1_CH3 + 1 + 2 + 3 + 4 + 5 + 6 TIM1_CH1 TIM1_CH2 TIM1_CH1 TIM1_CH4 TIM1_CH3 + 7 TIM8_CH1 TIM8_CH2 TIM8_CH3 TIM8_CH4 +*/ + +uint8_t timerClockDivisor(TIM_TypeDef *tim) +{ + return 1; +} + void TIM_SelectOCxM_NoDisable(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode) { uint32_t tmp = 0; diff --git a/src/main/target/ANYFCF7/target.c b/src/main/target/ANYFCF7/target.c index 7d820e2fe..fff44aba9 100644 --- a/src/main/target/ANYFCF7/target.c +++ b/src/main/target/ANYFCF7/target.c @@ -23,42 +23,42 @@ #include "drivers/timer.h" const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { - { TIM12, IO_TAG(PB14), TIM_CHANNEL_1, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP }, // S1_IN - { TIM12, IO_TAG(PB15), TIM_CHANNEL_2, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP }, // S2_IN - { TIM8, IO_TAG(PC6), TIM_CHANNEL_1, TIM8_CC_IRQn, 0, IOCFG_AF_PP }, // S3_IN - { TIM8, IO_TAG(PC7), TIM_CHANNEL_2, TIM8_CC_IRQn, 0, IOCFG_AF_PP }, // S4_IN - { TIM8, IO_TAG(PC9), TIM_CHANNEL_4, TIM8_CC_IRQn, 0, IOCFG_AF_PP }, // S5_IN - { TIM8, IO_TAG(PC8), TIM_CHANNEL_3, TIM8_CC_IRQn, 0, IOCFG_AF_PP }, // S6_IN + { TIM12, IO_TAG(PB14), TIM_CHANNEL_1, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP , GPIO_AF9_TIM12}, // S1_IN + { TIM12, IO_TAG(PB15), TIM_CHANNEL_2, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP , GPIO_AF9_TIM12}, // S2_IN + { TIM8, IO_TAG(PC6), TIM_CHANNEL_1, TIM8_CC_IRQn, 0, IOCFG_AF_PP , GPIO_AF3_TIM8}, // S3_IN + { TIM8, IO_TAG(PC7), TIM_CHANNEL_2, TIM8_CC_IRQn, 0, IOCFG_AF_PP , GPIO_AF3_TIM8}, // S4_IN + { TIM8, IO_TAG(PC9), TIM_CHANNEL_4, TIM8_CC_IRQn, 0, IOCFG_AF_PP , GPIO_AF3_TIM8}, // S5_IN + { TIM8, IO_TAG(PC8), TIM_CHANNEL_3, TIM8_CC_IRQn, 0, IOCFG_AF_PP , GPIO_AF3_TIM8}, // S6_IN - { TIM4, IO_TAG(PB8), TIM_CHANNEL_3, TIM4_IRQn, 1, IOCFG_AF_PP }, // S10_OUT 1 - { TIM2, IO_TAG(PA2), TIM_CHANNEL_3, TIM2_IRQn, 1, IOCFG_AF_PP }, // S6_OUT 2 - { TIM4, IO_TAG(PB9), TIM_CHANNEL_4, TIM4_IRQn, 1, IOCFG_AF_PP }, // S5_OUT 3 - { TIM2, IO_TAG(PA3), TIM_CHANNEL_4, TIM2_IRQn, 1, IOCFG_AF_PP }, // S1_OUT 4 - { TIM5, IO_TAG(PA1), TIM_CHANNEL_2, TIM5_IRQn, 1, IOCFG_AF_PP }, // S2_OUT - { TIM9, IO_TAG(PE6), TIM_CHANNEL_2, TIM1_BRK_TIM9_IRQn, 1, IOCFG_AF_PP }, // S3_OUT - { TIM3, IO_TAG(PB5), TIM_CHANNEL_2, TIM3_IRQn, 1, IOCFG_AF_PP }, // S4_OUT - { TIM5, IO_TAG(PA0), TIM_CHANNEL_1, TIM5_IRQn, 1, IOCFG_AF_PP }, // S7_OUT - { TIM2, IO_TAG(PB3), TIM_CHANNEL_2, TIM2_IRQn, 1, IOCFG_AF_PP }, // S8_OUT - { TIM3, IO_TAG(PB4), TIM_CHANNEL_1, TIM3_IRQn, 1, IOCFG_AF_PP }, // S9_OUT + { TIM4, IO_TAG(PB8), TIM_CHANNEL_3, TIM4_IRQn, 1, IOCFG_AF_PP , GPIO_AF2_TIM4}, // S10_OUT 1 + { TIM2, IO_TAG(PA2), TIM_CHANNEL_3, TIM2_IRQn, 1, IOCFG_AF_PP , GPIO_AF1_TIM2}, // S6_OUT 2 + { TIM4, IO_TAG(PB9), TIM_CHANNEL_4, TIM4_IRQn, 1, IOCFG_AF_PP , GPIO_AF2_TIM4}, // S5_OUT 3 + { TIM2, IO_TAG(PA3), TIM_CHANNEL_4, TIM2_IRQn, 1, IOCFG_AF_PP , GPIO_AF1_TIM2}, // S1_OUT 4 + { TIM5, IO_TAG(PA1), TIM_CHANNEL_2, TIM5_IRQn, 1, IOCFG_AF_PP , GPIO_AF2_TIM5}, // S2_OUT + { TIM9, IO_TAG(PE6), TIM_CHANNEL_2, TIM1_BRK_TIM9_IRQn, 1, IOCFG_AF_PP , GPIO_AF3_TIM9}, // S3_OUT + { TIM3, IO_TAG(PB5), TIM_CHANNEL_2, TIM3_IRQn, 1, IOCFG_AF_PP , GPIO_AF2_TIM3}, // S4_OUT + { TIM5, IO_TAG(PA0), TIM_CHANNEL_1, TIM5_IRQn, 1, IOCFG_AF_PP , GPIO_AF2_TIM5}, // S7_OUT + { TIM2, IO_TAG(PB3), TIM_CHANNEL_2, TIM2_IRQn, 1, IOCFG_AF_PP , GPIO_AF1_TIM2}, // S8_OUT + { TIM3, IO_TAG(PB4), TIM_CHANNEL_1, TIM3_IRQn, 1, IOCFG_AF_PP , GPIO_AF2_TIM3}, // S9_OUT }; // ALTERNATE LAYOUT //const timerHardware_t timerHardware[USABLE_TIMER_CHANNEL_COUNT] = { -// { TIM12, IO_TAG(PB14), TIM_CHANNEL_1, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP }, // S1_IN -// { TIM12, IO_TAG(PB15), TIM_CHANNEL_2, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP }, // S2_IN -// { TIM8, IO_TAG(PC6), TIM_CHANNEL_1, TIM8_CC_IRQn, 0, IOCFG_AF_PP }, // S3_IN -// { TIM8, IO_TAG(PC7), TIM_CHANNEL_2, TIM8_CC_IRQn, 0, IOCFG_AF_PP }, // S4_IN -// { TIM8, IO_TAG(PC9), TIM_CHANNEL_4, TIM8_CC_IRQn, 0, IOCFG_AF_PP }, // S5_IN -// { TIM8, IO_TAG(PC8), TIM_CHANNEL_3, TIM8_CC_IRQn, 0, IOCFG_AF_PP }, // S6_IN +// { TIM12, IO_TAG(PB14), TIM_CHANNEL_1, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP , GPIO_AF9_TIM12}, // S1_IN +// { TIM12, IO_TAG(PB15), TIM_CHANNEL_2, TIM8_BRK_TIM12_IRQn, 0, IOCFG_AF_PP , GPIO_AF9_TIM12}, // S2_IN +// { TIM8, IO_TAG(PC6), TIM_CHANNEL_1, TIM8_CC_IRQn, 0, IOCFG_AF_PP , GPIO_AF3_TIM8}, // S3_IN +// { TIM8, IO_TAG(PC7), TIM_CHANNEL_2, TIM8_CC_IRQn, 0, IOCFG_AF_PP , GPIO_AF3_TIM8}, // S4_IN +// { TIM8, IO_TAG(PC9), TIM_CHANNEL_4, TIM8_CC_IRQn, 0, IOCFG_AF_PP , GPIO_AF3_TIM8}, // S5_IN +// { TIM8, IO_TAG(PC8), TIM_CHANNEL_3, TIM8_CC_IRQn, 0, IOCFG_AF_PP , GPIO_AF3_TIM8}, // S6_IN // -// { TIM10, IO_TAG(PB8), TIM_CHANNEL_1, TIM1_UP_TIM10_IRQn, 1, IOCFG_AF_PP }, // S10_OUT -// { TIM9, IO_TAG(PA2), TIM_CHANNEL_1, TIM1_BRK_TIM9_IRQn, 1, IOCFG_AF_PP }, // S6_OUT -// { TIM2, IO_TAG(PA3), TIM_CHANNEL_4, TIM2_IRQn, 1, IOCFG_AF_PP }, // S1_OUT -// { TIM11, IO_TAG(PB9), TIM_CHANNEL_1, TIM1_TRG_COM_TIM11_IRQn, 1, IOCFG_AF_PP }, // S5_OUT -// { TIM5, IO_TAG(PA1), TIM_CHANNEL_2, TIM5_IRQn, 1, IOCFG_AF_PP }, // S2_OUT -// { TIM9, IO_TAG(PE6), TIM_CHANNEL_2, TIM1_BRK_TIM9_IRQn, 1, IOCFG_AF_PP }, // S3_OUT -// { TIM3, IO_TAG(PB5), TIM_CHANNEL_2, TIM3_IRQn, 1, IOCFG_AF_PP }, // S4_OUT -// { TIM5, IO_TAG(PA0), TIM_CHANNEL_1, TIM5_IRQn, 1, IOCFG_AF_PP }, // S7_OUT -// { TIM2, IO_TAG(PB3), TIM_CHANNEL_2, TIM2_IRQn, 1, IOCFG_AF_PP }, // S8_OUT -// { TIM3, IO_TAG(PB4), TIM_CHANNEL_1, TIM3_IRQn, 1, IOCFG_AF_PP }, // S9_OUT +// { TIM10, IO_TAG(PB8), TIM_CHANNEL_1, TIM1_UP_TIM10_IRQn, 1, IOCFG_AF_PP , GPIO_AF3_TIM10}, // S10_OUT +// { TIM9, IO_TAG(PA2), TIM_CHANNEL_1, TIM1_BRK_TIM9_IRQn, 1, IOCFG_AF_PP , GPIO_AF3_TIM9}, // S6_OUT +// { TIM2, IO_TAG(PA3), TIM_CHANNEL_4, TIM2_IRQn, 1, IOCFG_AF_PP , GPIO_AF1_TIM2}, // S1_OUT +// { TIM11, IO_TAG(PB9), TIM_CHANNEL_1, TIM1_TRG_COM_TIM11_IRQn, 1, IOCFG_AF_PP , GPIO_AF3_TIM11}, // S5_OUT +// { TIM5, IO_TAG(PA1), TIM_CHANNEL_2, TIM5_IRQn, 1, IOCFG_AF_PP , GPIO_AF2_TIM5}, // S2_OUT +// { TIM9, IO_TAG(PE6), TIM_CHANNEL_2, TIM1_BRK_TIM9_IRQn, 1, IOCFG_AF_PP , GPIO_AF3_TIM9}, // S3_OUT +// { TIM3, IO_TAG(PB5), TIM_CHANNEL_2, TIM3_IRQn, 1, IOCFG_AF_PP , GPIO_AF2_TIM3}, // S4_OUT +// { TIM5, IO_TAG(PA0), TIM_CHANNEL_1, TIM5_IRQn, 1, IOCFG_AF_PP , GPIO_AF2_TIM5}, // S7_OUT +// { TIM2, IO_TAG(PB3), TIM_CHANNEL_2, TIM2_IRQn, 1, IOCFG_AF_PP , GPIO_AF1_TIM2}, // S8_OUT +// { TIM3, IO_TAG(PB4), TIM_CHANNEL_1, TIM3_IRQn, 1, IOCFG_AF_PP , GPIO_AF2_TIM3}, // S9_OUT //};