From 0ad4b5a53549800cc136abd7586884ad6e50bce2 Mon Sep 17 00:00:00 2001 From: hoogendijkta Date: Mon, 18 Feb 2019 20:40:31 +0100 Subject: [PATCH 1/3] [Timer] Add channels support --- cores/arduino/stm32/timer.c | 132 ++++++++++++++++++++++++++---------- cores/arduino/stm32/timer.h | 5 ++ 2 files changed, 101 insertions(+), 36 deletions(-) diff --git a/cores/arduino/stm32/timer.c b/cores/arduino/stm32/timer.c index b4583d6cb4..9fd1fc910f 100644 --- a/cores/arduino/stm32/timer.c +++ b/cores/arduino/stm32/timer.c @@ -811,10 +811,11 @@ uint32_t getTimerClkFreq(TIM_TypeDef *tim) */ void TimerPulseInit(stimer_t *obj, uint16_t period, uint16_t pulseWidth, void (*irqHandle)(stimer_t *, uint32_t)) { - TIM_OC_InitTypeDef sConfig = {}; TIM_HandleTypeDef *handle = &(obj->handle); - obj->timer = TIMER_SERVO; + if (obj->timer == NULL) { + obj->timer = TIMER_SERVO; + } //min pulse = 1us - max pulse = 65535us handle->Instance = obj->timer; @@ -827,28 +828,7 @@ void TimerPulseInit(stimer_t *obj, uint16_t period, uint16_t pulseWidth, void (* #endif obj->irqHandleOC = irqHandle; - 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; - } - - if (HAL_TIM_OC_ConfigChannel(handle, &sConfig, TIM_CHANNEL_1) != HAL_OK) { - return; - } - if (HAL_TIM_OC_Start_IT(handle, TIM_CHANNEL_1) != HAL_OK) { - return; - } + attachIntHandleOC(obj, NULL, 1, pulseWidth); } /** @@ -859,8 +839,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)); @@ -915,17 +898,36 @@ void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim) { uint32_t channel = 0; stimer_t *obj = get_timer_obj(htim); - - 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); + switch (htim->Channel) { + case HAL_TIM_ACTIVE_CHANNEL_1: + channel = TIM_CHANNEL_1 / 4; + if (obj->irqHandleOC_CH1 != NULL) { + obj->irqHandleOC_CH1(); + } + if (obj->irqHandleOC != NULL) { + obj->irqHandleOC(obj, channel); + } + 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: + break; } } @@ -1095,6 +1097,64 @@ void attachIntHandle(stimer_t *obj, void (*irqHandle)(stimer_t *)) obj->irqHandle = irqHandle; } +/** + * @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_ConfigChannel(handle, &sConfig, TIM_CHANNEL_1) == HAL_OK) { + HAL_TIM_OC_Start_IT(handle, TIM_CHANNEL_1); + } + break; + case 2: + obj->irqHandleOC_CH2 = irqHandle; + if (HAL_TIM_OC_ConfigChannel(handle, &sConfig, TIM_CHANNEL_2) != HAL_OK) { + HAL_TIM_OC_Start_IT(handle, TIM_CHANNEL_2); + } + break; + case 3: + obj->irqHandleOC_CH3 = irqHandle; + if (HAL_TIM_OC_ConfigChannel(handle, &sConfig, TIM_CHANNEL_3) != HAL_OK) { + HAL_TIM_OC_Start_IT(handle, TIM_CHANNEL_3); + } + break; + case 4: + obj->irqHandleOC_CH4 = irqHandle; + if (HAL_TIM_OC_ConfigChannel(handle, &sConfig, TIM_CHANNEL_4) != HAL_OK) { + HAL_TIM_OC_Start_IT(handle, TIM_CHANNEL_4); + } + break; + default: + break; + } + return; +} /******************************************************************************/ /* TIMx IRQ HANDLER */ diff --git a/cores/arduino/stm32/timer.h b/cores/arduino/stm32/timer.h index 6592feb2e5..fce2e78239 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; }; @@ -216,6 +220,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 } From afe4d858f125cbcb7f3f723be2257e862c747147 Mon Sep 17 00:00:00 2001 From: hoogendijkta Date: Sun, 24 Feb 2019 11:56:35 +0100 Subject: [PATCH 2/3] [Timer] Add set prescaler register function Signed-off-by: Frederic.Pillon --- cores/arduino/stm32/timer.c | 11 +++++++++++ cores/arduino/stm32/timer.h | 1 + 2 files changed, 12 insertions(+) diff --git a/cores/arduino/stm32/timer.c b/cores/arduino/stm32/timer.c index 9fd1fc910f..90e5dde69c 100644 --- a/cores/arduino/stm32/timer.c +++ b/cores/arduino/stm32/timer.c @@ -1086,6 +1086,17 @@ uint32_t getCCRRegister(stimer_t *obj, uint32_t channel) return __HAL_TIM_GET_COMPARE(&(obj->handle), channel); } +/** + * @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 Attached an interrupt handler * @param timer_id : id of the timer diff --git a/cores/arduino/stm32/timer.h b/cores/arduino/stm32/timer.h index fce2e78239..942489fda2 100644 --- a/cores/arduino/stm32/timer.h +++ b/cores/arduino/stm32/timer.h @@ -214,6 +214,7 @@ 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); uint32_t getCCRRegister(stimer_t *obj, uint32_t channel); +void setTimerPrescalerRegister(stimer_t *obj, uint32_t prescaler); uint32_t getTimerIrq(TIM_TypeDef *tim); uint8_t getTimerClkSrc(TIM_TypeDef *tim); From 9fb6bcc2bd244de2e546b1d52296db52fea5afc3 Mon Sep 17 00:00:00 2001 From: "Frederic.Pillon" Date: Fri, 15 Mar 2019 17:08:10 +0100 Subject: [PATCH 3/3] [Timer] Reorder functions Signed-off-by: Frederic.Pillon --- cores/arduino/stm32/timer.c | 927 ++++++++++++++++++------------------ cores/arduino/stm32/timer.h | 2 +- 2 files changed, 465 insertions(+), 464 deletions(-) diff --git a/cores/arduino/stm32/timer.c b/cores/arduino/stm32/timer.c index 90e5dde69c..ffb550c918 100644 --- a/cores/arduino/stm32/timer.c +++ b/cores/arduino/stm32/timer.c @@ -43,9 +43,6 @@ extern "C" { #endif -/* Private Functions */ -static void HAL_TIMx_PeriodElapsedCallback(stimer_t *obj); - /* Private Variables */ typedef enum { #if defined(TIM1_BASE) @@ -119,6 +116,146 @@ typedef enum { static TIM_HandleTypeDef *timer_handles[TIMER_NUM] = {NULL}; +/* Private Functions */ +static void HAL_TIMx_PeriodElapsedCallback(stimer_t *obj); + +/* Aim of the function is to get timer_s pointer using htim pointer */ +/* Highly inspired from magical linux kernel's "container_of" */ +/* (which was not directly used since not compatible with IAR toolchain) */ +stimer_t *get_timer_obj(TIM_HandleTypeDef *htim) +{ + struct timer_s *obj_s; + stimer_t *obj; + + obj_s = (struct timer_s *)((char *)htim - offsetof(struct timer_s, handle)); + obj = (stimer_t *)((char *)obj_s - offsetof(stimer_t, timer)); + + return (obj); +} + +/** + * @brief TIMER Initialization - clock init and nvic init + * @param htim_base : one of the defined timer + * @retval None + */ +void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim_base) +{ + timer_enable_clock(htim_base); + + HAL_NVIC_SetPriority(getTimerIrq(htim_base->Instance), 15, 0); + HAL_NVIC_EnableIRQ(getTimerIrq(htim_base->Instance)); +} + +/** + * @brief TIMER Deinitialization - clock and nvic + * @param htim_base : one of the defined timer + * @retval None + */ +void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim_base) +{ + timer_disable_clock(htim_base); + HAL_NVIC_DisableIRQ(getTimerIrq(htim_base->Instance)); +} + +/** + * @brief Initializes the TIM Output Compare MSP. + * @param htim: TIM handle + * @retval None + */ +void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim) +{ + timer_enable_clock(htim); +} + +/** + * @brief DeInitialize TIM Output Compare MSP. + * @param htim: TIM handle + * @retval None + */ +void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *htim) +{ + timer_disable_clock(htim); +} + +/** + * @brief Output Compare callback in non-blocking mode + * @param htim : TIM OC handle + * @retval None + */ +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(); + } + if (obj->irqHandleOC != NULL) { + obj->irqHandleOC(obj, channel); + } + 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: + break; + } +} + +/** + * @brief Period elapsed callback in non-blocking mode + * @param timer_id : id of the timer + * @retval None + */ +void HAL_TIMx_PeriodElapsedCallback(stimer_t *obj) +{ + GPIO_TypeDef *port = get_GPIO_Port(STM_PORT(obj->pin)); + + if (port != NULL) { + if (obj->pinInfo.count != 0) { + if (obj->pinInfo.count > 0) { + obj->pinInfo.count--; + } + obj->pinInfo.state = (obj->pinInfo.state == 0) ? 1 : 0; + digital_io_write(port, STM_LL_GPIO_PIN(obj->pin), obj->pinInfo.state); + } else { + digital_io_write(port, STM_LL_GPIO_PIN(obj->pin), 0); + } + } +} + +/** + * @brief Period elapsed callback in non-blocking mode + * @param htim : TIM handle + * @retval None + */ +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + stimer_t *obj = get_timer_obj(htim); + + if (obj->irqHandle != NULL) { + obj->irqHandle(obj); + } +} + +/* Exported functions */ /** * @brief Enable the timer clock * @param htim : one of the defined timer @@ -381,30 +518,6 @@ void timer_disable_clock(TIM_HandleTypeDef *htim) #endif } -/** - * @brief TIMER Initialization - clock init and nvic init - * @param htim_base : one of the defined timer - * @retval None - */ -void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim_base) -{ - timer_enable_clock(htim_base); - - HAL_NVIC_SetPriority(getTimerIrq(htim_base->Instance), 15, 0); - HAL_NVIC_EnableIRQ(getTimerIrq(htim_base->Instance)); -} - -/** - * @brief TIMER Deinitialization - clock and nvic - * @param htim_base : one of the defined timer - * @retval None - */ -void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef *htim_base) -{ - timer_disable_clock(htim_base); - HAL_NVIC_DisableIRQ(getTimerIrq(htim_base->Instance)); -} - /** * @brief This function will set the timer to the required value * @param timer_id : timer_id_e @@ -438,188 +551,372 @@ void TimerHandleInit(stimer_t *obj, uint16_t period, uint16_t prescaler) } /** - * @brief This function return the timer clock source. - * @param tim: timer instance - * @retval 1 = PCLK1 or 2 = PCLK2 or 0 = unknown + * @brief This function will reset the timer + * @param timer_id : timer_id_e + * @retval None */ -uint32_t getTimerIrq(TIM_TypeDef *tim) +void TimerHandleDeinit(stimer_t *obj) { - uint32_t IRQn = 0; + if (obj != NULL) { + HAL_TIM_Base_DeInit(&(obj->handle)); + HAL_TIM_Base_Stop_IT(&(obj->handle)); + } +} - if (tim != (TIM_TypeDef *)NC) { - /* Get IRQn depending on TIM instance */ - switch ((uint32_t)tim) { -#if defined(TIM1_BASE) - case (uint32_t)TIM1: - IRQn = TIM1_IRQn; - break; -#endif -#if defined(TIM2_BASE) - case (uint32_t)TIM2: - IRQn = TIM2_IRQn; - break; -#endif -#if defined(TIM3_BASE) - case (uint32_t)TIM3: - IRQn = TIM3_IRQn; - break; -#endif -#if defined(TIM4_BASE) - case (uint32_t)TIM4: - IRQn = TIM4_IRQn; - break; -#endif -#if defined(TIM5_BASE) - case (uint32_t)TIM5: - IRQn = TIM5_IRQn; - break; -#endif -#if defined(TIM6_BASE) - case (uint32_t)TIM6: - IRQn = TIM6_IRQn; - break; -#endif -#if defined(TIM7_BASE) - case (uint32_t)TIM7: - IRQn = TIM7_IRQn; - break; -#endif -#if defined(TIM8_BASE) - case (uint32_t)TIM8: - IRQn = TIM8_IRQn; - break; -#endif -#if defined(TIM9_BASE) - case (uint32_t)TIM9: - IRQn = TIM9_IRQn; - break; -#endif -#if defined(TIM10_BASE) - case (uint32_t)TIM10: - IRQn = TIM10_IRQn; - break; -#endif -#if defined(TIM11_BASE) - case (uint32_t)TIM11: - IRQn = TIM11_IRQn; - break; -#endif -#if defined(TIM12_BASE) - case (uint32_t)TIM12: - IRQn = TIM12_IRQn; - break; -#endif -#if defined(TIM13_BASE) - case (uint32_t)TIM13: - IRQn = TIM13_IRQn; - break; -#endif -#if defined(TIM14_BASE) - case (uint32_t)TIM14: - IRQn = TIM14_IRQn; - break; -#endif -#if defined(TIM15_BASE) - case (uint32_t)TIM15: - IRQn = TIM15_IRQn; - break; -#endif -#if defined(TIM16_BASE) - case (uint32_t)TIM16: - IRQn = TIM16_IRQn; - break; -#endif -#if defined(TIM17_BASE) - case (uint32_t)TIM17: - IRQn = TIM17_IRQn; - break; -#endif -#if defined(TIM18_BASE) - case (uint32_t)TIM18: - IRQn = TIM18_IRQn; - break; -#endif -#if defined(TIM19_BASE) - case (uint32_t)TIM19: - IRQn = TIM19_IRQn; - break; -#endif -#if defined(TIM20_BASE) - case (uint32_t)TIM20: - IRQn = TIM20_IRQn; - break; -#endif -#if defined(TIM21_BASE) - case (uint32_t)TIM21: - IRQn = TIM21_IRQn; - break; -#endif -#if defined(TIM22_BASE) - case (uint32_t)TIM22: - IRQn = TIM22_IRQn; - break; -#endif - break; - default: - core_debug("TIM: Unknown timer IRQn"); - break; +/** + * @brief This function will set the tone timer to the required value and + * configure the pin to toggle. + * @param port : pointer to GPIO_TypeDef + * @param pin : pin number to toggle + * @param frequency : toggle frequency (in hertz) + * @param duration : toggle time + * @retval None + */ +void TimerPinInit(stimer_t *obj, uint32_t frequency, uint32_t duration) +{ + uint8_t end = 0; + uint32_t timClkFreq = 0; + // TIMER_TONE freq is twice frequency + uint32_t timFreq = 2 * frequency; + uint32_t prescaler = 1; + uint32_t period = 0; + uint32_t scale = 0; + + if (frequency > MAX_FREQ) { + return; + } + + obj->timer = TIMER_TONE; + obj->pinInfo.state = 0; + + if (frequency == 0) { + TimerPinDeinit(obj); + return; + } + + //Calculate the toggle count + if (duration > 0) { + obj->pinInfo.count = ((timFreq * duration) / 1000); + } else { + obj->pinInfo.count = -1; + } + + pin_function(obj->pin, STM_PIN_DATA(STM_MODE_OUTPUT_PP, GPIO_NOPULL, 0)); + timClkFreq = getTimerClkFreq(obj->timer); + + // Do this once + scale = timClkFreq / timFreq; + while (end == 0) { + period = ((uint32_t)(scale / prescaler)) - 1; + + if ((period >= 0xFFFF) && (prescaler < 0xFFFF)) { + prescaler++; //prescaler *= 2; + } + + else { + end = 1; } } - return IRQn; + + if ((period < 0xFFFF) && (prescaler < 0xFFFF)) { + obj->irqHandle = HAL_TIMx_PeriodElapsedCallback; + TimerHandleInit(obj, period, prescaler - 1); + } else { + TimerHandleDeinit(obj); + } } /** - * @brief This function will reset the timer + * @brief This function will reset the tone timer + * @param port : pointer to port + * @param pin : pin number to toggle + * @retval None + */ +void TimerPinDeinit(stimer_t *obj) +{ + TimerHandleDeinit(obj); + pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); +} + +/** + * @brief This function will set the timer to generate pulse in interrupt mode with a particular duty cycle * @param timer_id : timer_id_e + * @param period : timer period in microseconds + * @param pulseWidth : pulse width in microseconds + * @param irqHandle : interrupt routine to call * @retval None */ -void TimerHandleDeinit(stimer_t *obj) +void TimerPulseInit(stimer_t *obj, uint16_t period, uint16_t pulseWidth, void (*irqHandle)(stimer_t *, uint32_t)) { - if (obj != NULL) { - HAL_TIM_Base_DeInit(&(obj->handle)); - HAL_TIM_Base_Stop_IT(&(obj->handle)); + TIM_HandleTypeDef *handle = &(obj->handle); + + if (obj->timer == NULL) { + obj->timer = TIMER_SERVO; + } + + //min pulse = 1us - max pulse = 65535us + handle->Instance = obj->timer; + handle->Init.Period = period; + handle->Init.Prescaler = (uint32_t)(getTimerClkFreq(obj->timer) / (1000000)) - 1; + handle->Init.ClockDivision = 0; + handle->Init.CounterMode = TIM_COUNTERMODE_UP; +#if !defined(STM32L0xx) && !defined(STM32L1xx) + handle->Init.RepetitionCounter = 0; +#endif + obj->irqHandleOC = irqHandle; + + attachIntHandleOC(obj, NULL, 1, pulseWidth); +} + +/** + * @brief This function will reset the pulse generation + * @param timer_id : timer_id_e + * @retval None + */ +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)); + + if (HAL_TIM_OC_DeInit(handle) != HAL_OK) { + return; + } + if (HAL_TIM_OC_Stop_IT(handle, TIM_CHANNEL_1) != HAL_OK) { + return; } } +/** + * @brief Get the counter value. + * @param timer_id : id of the timer + * @retval Counter value + */ +uint32_t getTimerCounter(stimer_t *obj) +{ + return __HAL_TIM_GET_COUNTER(&(obj->handle)); +} + +/** + * @brief Set the counter value. + * @param timer_id : id of the timer + * @param value : counter value + * @retval None + */ +void setTimerCounter(stimer_t *obj, uint32_t value) +{ + __HAL_TIM_SET_COUNTER(&(obj->handle), value); +} + +/** + * @brief Set the TIM Capture Compare Register value. + * @param timer_id : id of the timer + * @param channel : TIM Channels to be configured. + * @retval CRR value. + */ +uint32_t getCCRRegister(stimer_t *obj, uint32_t channel) +{ + return __HAL_TIM_GET_COMPARE(&(obj->handle), channel); +} + +/** + * @brief Set the TIM Capture Compare Register value. + * @param timer_id : id of the timer + * @param channel : TIM Channels to be configured. + * @param value : register new register. + * @retval None + */ +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 This function return the timer clock source. * @param tim: timer instance * @retval 1 = PCLK1 or 2 = PCLK2 or 0 = unknown */ -uint8_t getTimerClkSrc(TIM_TypeDef *tim) +uint32_t getTimerIrq(TIM_TypeDef *tim) { - uint8_t clkSrc = 0; + uint32_t IRQn = 0; - if (tim != (TIM_TypeDef *)NC) -#ifdef STM32F0xx - /* TIMx source CLK is PCKL1 */ - clkSrc = 1; -#else - { - /* Get source clock depending on TIM instance */ + if (tim != (TIM_TypeDef *)NC) { + /* Get IRQn depending on TIM instance */ switch ((uint32_t)tim) { +#if defined(TIM1_BASE) + case (uint32_t)TIM1: + IRQn = TIM1_IRQn; + break; +#endif #if defined(TIM2_BASE) case (uint32_t)TIM2: + IRQn = TIM2_IRQn; + break; #endif #if defined(TIM3_BASE) case (uint32_t)TIM3: + IRQn = TIM3_IRQn; + break; #endif #if defined(TIM4_BASE) case (uint32_t)TIM4: + IRQn = TIM4_IRQn; + break; #endif #if defined(TIM5_BASE) case (uint32_t)TIM5: + IRQn = TIM5_IRQn; + break; #endif #if defined(TIM6_BASE) case (uint32_t)TIM6: + IRQn = TIM6_IRQn; + break; #endif #if defined(TIM7_BASE) case (uint32_t)TIM7: + IRQn = TIM7_IRQn; + break; #endif -#if defined(TIM12_BASE) - case (uint32_t)TIM12: +#if defined(TIM8_BASE) + case (uint32_t)TIM8: + IRQn = TIM8_IRQn; + break; #endif -#if defined(TIM13_BASE) +#if defined(TIM9_BASE) + case (uint32_t)TIM9: + IRQn = TIM9_IRQn; + break; +#endif +#if defined(TIM10_BASE) + case (uint32_t)TIM10: + IRQn = TIM10_IRQn; + break; +#endif +#if defined(TIM11_BASE) + case (uint32_t)TIM11: + IRQn = TIM11_IRQn; + break; +#endif +#if defined(TIM12_BASE) + case (uint32_t)TIM12: + IRQn = TIM12_IRQn; + break; +#endif +#if defined(TIM13_BASE) + case (uint32_t)TIM13: + IRQn = TIM13_IRQn; + break; +#endif +#if defined(TIM14_BASE) + case (uint32_t)TIM14: + IRQn = TIM14_IRQn; + break; +#endif +#if defined(TIM15_BASE) + case (uint32_t)TIM15: + IRQn = TIM15_IRQn; + break; +#endif +#if defined(TIM16_BASE) + case (uint32_t)TIM16: + IRQn = TIM16_IRQn; + break; +#endif +#if defined(TIM17_BASE) + case (uint32_t)TIM17: + IRQn = TIM17_IRQn; + break; +#endif +#if defined(TIM18_BASE) + case (uint32_t)TIM18: + IRQn = TIM18_IRQn; + break; +#endif +#if defined(TIM19_BASE) + case (uint32_t)TIM19: + IRQn = TIM19_IRQn; + break; +#endif +#if defined(TIM20_BASE) + case (uint32_t)TIM20: + IRQn = TIM20_IRQn; + break; +#endif +#if defined(TIM21_BASE) + case (uint32_t)TIM21: + IRQn = TIM21_IRQn; + break; +#endif +#if defined(TIM22_BASE) + case (uint32_t)TIM22: + IRQn = TIM22_IRQn; + break; +#endif + break; + default: + core_debug("TIM: Unknown timer IRQn"); + break; + } + } + return IRQn; +} + +/** + * @brief This function return the timer clock source. + * @param tim: timer instance + * @retval 1 = PCLK1 or 2 = PCLK2 or 0 = unknown + */ +uint8_t getTimerClkSrc(TIM_TypeDef *tim) +{ + uint8_t clkSrc = 0; + + if (tim != (TIM_TypeDef *)NC) +#ifdef STM32F0xx + /* TIMx source CLK is PCKL1 */ + clkSrc = 1; +#else + { + /* Get source clock depending on TIM instance */ + switch ((uint32_t)tim) { +#if defined(TIM2_BASE) + case (uint32_t)TIM2: +#endif +#if defined(TIM3_BASE) + case (uint32_t)TIM3: +#endif +#if defined(TIM4_BASE) + case (uint32_t)TIM4: +#endif +#if defined(TIM5_BASE) + case (uint32_t)TIM5: +#endif +#if defined(TIM6_BASE) + case (uint32_t)TIM6: +#endif +#if defined(TIM7_BASE) + case (uint32_t)TIM7: +#endif +#if defined(TIM12_BASE) + case (uint32_t)TIM12: +#endif +#if defined(TIM13_BASE) case (uint32_t)TIM13: #endif #if defined(TIM14_BASE) @@ -801,302 +1098,6 @@ 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 - * @param period : timer period in microseconds - * @param pulseWidth : pulse width in microseconds - * @param irqHandle : interrupt routine to call - * @retval None - */ -void TimerPulseInit(stimer_t *obj, uint16_t period, uint16_t pulseWidth, void (*irqHandle)(stimer_t *, uint32_t)) -{ - TIM_HandleTypeDef *handle = &(obj->handle); - - if (obj->timer == NULL) { - obj->timer = TIMER_SERVO; - } - - //min pulse = 1us - max pulse = 65535us - handle->Instance = obj->timer; - handle->Init.Period = period; - handle->Init.Prescaler = (uint32_t)(getTimerClkFreq(obj->timer) / (1000000)) - 1; - handle->Init.ClockDivision = 0; - handle->Init.CounterMode = TIM_COUNTERMODE_UP; -#if !defined(STM32L0xx) && !defined(STM32L1xx) - handle->Init.RepetitionCounter = 0; -#endif - obj->irqHandleOC = irqHandle; - - attachIntHandleOC(obj, NULL, 1, pulseWidth); -} - -/** - * @brief This function will reset the pulse generation - * @param timer_id : timer_id_e - * @retval None - */ -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)); - - if (HAL_TIM_OC_DeInit(handle) != HAL_OK) { - return; - } - if (HAL_TIM_OC_Stop_IT(handle, TIM_CHANNEL_1) != HAL_OK) { - return; - } -} - -/** - * @brief Initializes the TIM Output Compare MSP. - * @param htim: TIM handle - * @retval None - */ -void HAL_TIM_OC_MspInit(TIM_HandleTypeDef *htim) -{ - timer_enable_clock(htim); -} - -/** - * @brief DeInitialize TIM Output Compare MSP. - * @param htim: TIM handle - * @retval None - */ -void HAL_TIM_OC_MspDeInit(TIM_HandleTypeDef *htim) -{ - timer_disable_clock(htim); -} - -/* Aim of the function is to get timer_s pointer using htim pointer */ -/* Highly inspired from magical linux kernel's "container_of" */ -/* (which was not directly used since not compatible with IAR toolchain) */ -stimer_t *get_timer_obj(TIM_HandleTypeDef *htim) -{ - struct timer_s *obj_s; - stimer_t *obj; - - obj_s = (struct timer_s *)((char *)htim - offsetof(struct timer_s, handle)); - obj = (stimer_t *)((char *)obj_s - offsetof(stimer_t, timer)); - - return (obj); -} - -/** - * @brief Output Compare callback in non-blocking mode - * @param htim : TIM OC handle - * @retval None - */ -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(); - } - if (obj->irqHandleOC != NULL) { - obj->irqHandleOC(obj, channel); - } - 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: - break; - } -} - -/** - * @brief Period elapsed callback in non-blocking mode - * @param timer_id : id of the timer - * @retval None - */ -void HAL_TIMx_PeriodElapsedCallback(stimer_t *obj) -{ - GPIO_TypeDef *port = get_GPIO_Port(STM_PORT(obj->pin)); - - if (port != NULL) { - if (obj->pinInfo.count != 0) { - if (obj->pinInfo.count > 0) { - obj->pinInfo.count--; - } - obj->pinInfo.state = (obj->pinInfo.state == 0) ? 1 : 0; - digital_io_write(port, STM_LL_GPIO_PIN(obj->pin), obj->pinInfo.state); - } else { - digital_io_write(port, STM_LL_GPIO_PIN(obj->pin), 0); - } - } -} - -/** - * @brief Period elapsed callback in non-blocking mode - * @param htim : TIM handle - * @retval None - */ -void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) -{ - stimer_t *obj = get_timer_obj(htim); - - if (obj->irqHandle != NULL) { - obj->irqHandle(obj); - } -} - -/** - * @brief This function will set the tone timer to the required value and - * configure the pin to toggle. - * @param port : pointer to GPIO_TypeDef - * @param pin : pin number to toggle - * @param frequency : toggle frequency (in hertz) - * @param duration : toggle time - * @retval None - */ -void TimerPinInit(stimer_t *obj, uint32_t frequency, uint32_t duration) -{ - uint8_t end = 0; - uint32_t timClkFreq = 0; - // TIMER_TONE freq is twice frequency - uint32_t timFreq = 2 * frequency; - uint32_t prescaler = 1; - uint32_t period = 0; - uint32_t scale = 0; - - if (frequency > MAX_FREQ) { - return; - } - - obj->timer = TIMER_TONE; - obj->pinInfo.state = 0; - - if (frequency == 0) { - TimerPinDeinit(obj); - return; - } - - //Calculate the toggle count - if (duration > 0) { - obj->pinInfo.count = ((timFreq * duration) / 1000); - } else { - obj->pinInfo.count = -1; - } - - pin_function(obj->pin, STM_PIN_DATA(STM_MODE_OUTPUT_PP, GPIO_NOPULL, 0)); - timClkFreq = getTimerClkFreq(obj->timer); - - // Do this once - scale = timClkFreq / timFreq; - while (end == 0) { - period = ((uint32_t)(scale / prescaler)) - 1; - - if ((period >= 0xFFFF) && (prescaler < 0xFFFF)) { - prescaler++; //prescaler *= 2; - } - - else { - end = 1; - } - } - - if ((period < 0xFFFF) && (prescaler < 0xFFFF)) { - obj->irqHandle = HAL_TIMx_PeriodElapsedCallback; - TimerHandleInit(obj, period, prescaler - 1); - } else { - TimerHandleDeinit(obj); - } -} - -/** - * @brief This function will reset the tone timer - * @param port : pointer to port - * @param pin : pin number to toggle - * @retval None - */ -void TimerPinDeinit(stimer_t *obj) -{ - TimerHandleDeinit(obj); - pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); -} - -/** - * @brief Get the counter value. - * @param timer_id : id of the timer - * @retval Counter value - */ -uint32_t getTimerCounter(stimer_t *obj) -{ - return __HAL_TIM_GET_COUNTER(&(obj->handle)); -} - -/** - * @brief Set the counter value. - * @param timer_id : id of the timer - * @param value : counter value - * @retval None - */ -void setTimerCounter(stimer_t *obj, uint32_t value) -{ - __HAL_TIM_SET_COUNTER(&(obj->handle), value); -} - -/** - * @brief Set the TIM Capture Compare Register value. - * @param timer_id : id of the timer - * @param channel : TIM Channels to be configured. - * @param value : register new register. - * @retval None - */ -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 channel : TIM Channels to be configured. - * @retval CRR value. - */ -uint32_t getCCRRegister(stimer_t *obj, uint32_t channel) -{ - return __HAL_TIM_GET_COMPARE(&(obj->handle), channel); -} - -/** - * @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 Attached an interrupt handler * @param timer_id : id of the timer diff --git a/cores/arduino/stm32/timer.h b/cores/arduino/stm32/timer.h index 942489fda2..f14016916f 100644 --- a/cores/arduino/stm32/timer.h +++ b/cores/arduino/stm32/timer.h @@ -212,8 +212,8 @@ 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); uint32_t getCCRRegister(stimer_t *obj, uint32_t channel); +void setCCRRegister(stimer_t *obj, uint32_t channel, uint32_t value); void setTimerPrescalerRegister(stimer_t *obj, uint32_t prescaler); uint32_t getTimerIrq(TIM_TypeDef *tim);