diff --git a/cores/arduino/stm32/timer.c b/cores/arduino/stm32/timer.c index 98291db36c..91cf2a352d 100644 --- a/cores/arduino/stm32/timer.c +++ b/cores/arduino/stm32/timer.c @@ -786,6 +786,7 @@ uint32_t getTimerClkFreq(TIM_TypeDef *tim) return uwTimclock; } + /** * @brief This function will set the timer to generate pulse in interrupt mode with a particular duty cycle * @param timer_id : timer_id_e @@ -799,7 +800,9 @@ void TimerPulseInit(stimer_t *obj, uint16_t period, uint16_t pulseWidth, void (* TIM_OC_InitTypeDef sConfig = {}; TIM_HandleTypeDef *handle = &(obj->handle); - obj->timer = TIMER_SERVO; + if (obj->timer == 0x00) { + obj->timer = TIMER_SERVO; + } //min pulse = 1us - max pulse = 65535us handle->Instance = obj->timer; @@ -836,6 +839,80 @@ void TimerPulseInit(stimer_t *obj, uint16_t period, uint16_t pulseWidth, void (* } } +/** + * @brief This function will attach timer interrupt to with a particular duty cycle on channel x + * @param timer_id : timer_id_e + * @param irqHandle : interrupt routine to call + * @param timChannel : timer channel + * @param pulseWidth : phase of the timer where the callback will happen + * @retval None + */ +void attachIntHandleOC(stimer_t *obj, void (*irqHandle)(void), uint16_t timChannel, uint16_t pulseWidth) +{ + TIM_OC_InitTypeDef sConfig = {}; + TIM_HandleTypeDef *handle = &(obj->handle); + + sConfig.OCMode = TIM_OCMODE_TIMING; + sConfig.Pulse = pulseWidth; + sConfig.OCPolarity = TIM_OCPOLARITY_HIGH; + sConfig.OCFastMode = TIM_OCFAST_DISABLE; +#if !defined(STM32L0xx) && !defined(STM32L1xx) + sConfig.OCNPolarity = TIM_OCNPOLARITY_HIGH; + sConfig.OCIdleState = TIM_OCIDLESTATE_RESET; + sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET; +#endif + //HAL_NVIC_SetPriority(getTimerIrq(obj->timer), 14, 0); + //HAL_NVIC_EnableIRQ(getTimerIrq(obj->timer)); + + if (HAL_TIM_OC_Init(handle) != HAL_OK) { + return; + } + switch (timChannel) { + case 1: + obj->irqHandleOC_CH1 = irqHandle; + if (HAL_TIM_OC_Start_IT(handle, TIM_CHANNEL_1) != HAL_OK) { + return; + } + if (HAL_TIM_OC_ConfigChannel(handle, &sConfig, TIM_CHANNEL_1) != HAL_OK) { + return; + } + break; + case 2: + obj->irqHandleOC_CH2 = irqHandle; + if (HAL_TIM_OC_Start_IT(handle, TIM_CHANNEL_2) != HAL_OK) { + return; + } + if (HAL_TIM_OC_ConfigChannel(handle, &sConfig, TIM_CHANNEL_2) != HAL_OK) { + return; + } + break; + case 3: + obj->irqHandleOC_CH3 = irqHandle; + if (HAL_TIM_OC_Start_IT(handle, TIM_CHANNEL_3) != HAL_OK) { + return; + } + if (HAL_TIM_OC_ConfigChannel(handle, &sConfig, TIM_CHANNEL_3) != HAL_OK) { + return; + } + break; + case 4: + obj->irqHandleOC_CH4 = irqHandle; + if (HAL_TIM_OC_Start_IT(handle, TIM_CHANNEL_4) != HAL_OK) { + return; + } + if (HAL_TIM_OC_ConfigChannel(handle, &sConfig, TIM_CHANNEL_4) != HAL_OK) { + return; + } + break; + default: + return; + break; + } + return; +} + + + /** * @brief This function will reset the pulse generation * @param timer_id : timer_id_e @@ -844,8 +921,11 @@ void TimerPulseInit(stimer_t *obj, uint16_t period, uint16_t pulseWidth, void (* void TimerPulseDeinit(stimer_t *obj) { TIM_HandleTypeDef *handle = &(obj->handle); - obj->irqHandleOC = NULL; + obj->irqHandleOC_CH1 = NULL; + obj->irqHandleOC_CH2 = NULL; + obj->irqHandleOC_CH3 = NULL; + obj->irqHandleOC_CH4 = NULL; HAL_NVIC_DisableIRQ(getTimerIrq(obj->timer)); @@ -900,18 +980,41 @@ void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) { uint32_t channel = 0; stimer_t *obj = get_timer_obj(htim); + switch (htim->Channel) { + case HAL_TIM_ACTIVE_CHANNEL_1: + channel = TIM_CHANNEL_1 / 4; + if (obj->irqHandleOC_CH1 != NULL) { + obj->irqHandleOC_CH1(); + } + break; + case HAL_TIM_ACTIVE_CHANNEL_2: + channel = TIM_CHANNEL_2 / 4; + if (obj->irqHandleOC_CH2 != NULL) { + obj->irqHandleOC_CH2(); + } + break; + case HAL_TIM_ACTIVE_CHANNEL_3: + if (obj->irqHandleOC_CH3 != NULL) { + obj->irqHandleOC_CH3(); + } + channel = TIM_CHANNEL_3 / 4; + break; + case HAL_TIM_ACTIVE_CHANNEL_4: + if (obj->irqHandleOC_CH4 != NULL) { + obj->irqHandleOC_CH4(); + } + channel = TIM_CHANNEL_4 / 4; + break; + default: + return; + break; + } + //make it compatible with older versions if (obj->irqHandleOC != NULL) { - switch (htim->Channel) { - case HAL_TIM_ACTIVE_CHANNEL_1: - channel = TIM_CHANNEL_1 / 4; - break; - default: - return; - break; - } obj->irqHandleOC(obj, channel); } + } /** @@ -1058,6 +1161,19 @@ void setCCRRegister(stimer_t *obj, uint32_t channel, uint32_t value) __HAL_TIM_SET_COMPARE(&(obj->handle), channel * 4, value); } + +/** + * @brief Set the TIM Capture Compare Register value. + * @param timer_id : id of the timer + * @param prescaler : prescaler value to set for this timer. + * @retval None + */ +void setTimerPrescalerRegister(stimer_t *obj, uint32_t prescaler) +{ + __HAL_TIM_SET_PRESCALER(&(obj->handle), prescaler); +} + + /** * @brief Set the TIM Capture Compare Register value. * @param timer_id : id of the timer diff --git a/cores/arduino/stm32/timer.h b/cores/arduino/stm32/timer.h index 7ede8518ca..9dcaa775f0 100644 --- a/cores/arduino/stm32/timer.h +++ b/cores/arduino/stm32/timer.h @@ -68,6 +68,10 @@ struct timer_s { uint8_t idx; void (*irqHandle)(stimer_t *); void (*irqHandleOC)(stimer_t *, uint32_t); + void (*irqHandleOC_CH1)(void); + void (*irqHandleOC_CH2)(void); + void (*irqHandleOC_CH3)(void); + void (*irqHandleOC_CH4)(void); PinName pin; volatile timerPinInfo_t pinInfo; }; @@ -200,6 +204,7 @@ void TimerPulseDeinit(stimer_t *obj); uint32_t getTimerCounter(stimer_t *obj); void setTimerCounter(stimer_t *obj, uint32_t value); void setCCRRegister(stimer_t *obj, uint32_t channel, uint32_t value); +void setTimerPrescalerRegister(stimer_t *obj, uint32_t prescaler); uint32_t getCCRRegister(stimer_t *obj, uint32_t channel); uint32_t getTimerIrq(TIM_TypeDef *tim); @@ -207,6 +212,7 @@ uint8_t getTimerClkSrc(TIM_TypeDef *tim); uint32_t getTimerClkFreq(TIM_TypeDef *tim); void attachIntHandle(stimer_t *obj, void (*irqHandle)(stimer_t *)); +void attachIntHandleOC(stimer_t *obj, void (*irqHandle)(void), uint16_t timChannel, uint16_t pulseWidth); #ifdef __cplusplus }