Skip to content

Commit 66e7a3c

Browse files
committed
Fix #18 PWM frequency
Get the correct timer freq depending on timer clock source. Signed-off-by: Frederic.Pillon <[email protected]>
1 parent 2fa0645 commit 66e7a3c

File tree

3 files changed

+77
-12
lines changed

3 files changed

+77
-12
lines changed

cores/arduino/stm32/analog.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -711,9 +711,9 @@ void pwm_start(PinName pin, uint32_t clock_freq,
711711
/* Compute the prescaler value to have TIM counter clock equal to clock_freq Hz */
712712
timHandle.Instance = pinmap_peripheral(pin, PinMap_PWM);
713713
if (timHandle.Instance == NC) return 0;
714-
timHandle.Init.Prescaler = (uint32_t)(SystemCoreClock / clock_freq) - 1;
714+
timHandle.Init.Prescaler = (uint32_t)(getTimerClkFreq(timHandle.Instance) / clock_freq) - 1;
715715
timHandle.Init.Period = period;
716-
timHandle.Init.ClockDivision = 0;
716+
timHandle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
717717
timHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
718718
#ifndef STM32L0xx
719719
timHandle.Init.RepetitionCounter = 0;

cores/arduino/stm32/timer.c

+72-10
Original file line numberDiff line numberDiff line change
@@ -414,21 +414,83 @@ void TimerHandleDeinit(stimer_t *obj)
414414
HAL_TIM_Base_Stop_IT(&(obj->handle));
415415
}
416416

417+
/**
418+
* @brief This function return the timer clock source.
419+
* @param tim: timer instance
420+
* @retval 1 = PCLK1 or 2 = PCLK2 or 0 = unknown
421+
*/
422+
uint8_t getTimerClkSrc(TIM_TypeDef* tim)
423+
{
424+
return (uint8_t)timermap_clkSrc(tim, TimerMap_CONFIG);
425+
}
426+
417427
/**
418428
* @brief This function return the timer clock frequency.
419-
* @param clkSrc: 1 = PCLK1 or 2 = PCLK2
429+
* @param tim: timer instance
420430
* @retval frequency in Hz
421431
*/
422-
uint32_t getTimerClkFreq(uint8_t clkSrc)
432+
uint32_t getTimerClkFreq(TIM_TypeDef* tim)
423433
{
424-
if(clkSrc == 1)
425-
return HAL_RCC_GetPCLK1Freq();
426-
#ifdef HAL_RCC_GetPCLK2Freq
427-
else if(clkSrc == 2)
428-
return HAL_RCC_GetPCLK2Freq();
434+
RCC_ClkInitTypeDef clkconfig = {};
435+
uint32_t pFLatency = 0U;
436+
uint32_t uwTimclock, uwAPBxPrescaler = 0U;
437+
438+
/* Get clock configuration */
439+
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
440+
switch(getTimerClkSrc(tim)) {
441+
case 1:
442+
uwAPBxPrescaler = clkconfig.APB1CLKDivider;
443+
uwTimclock = HAL_RCC_GetPCLK1Freq();
444+
break;
445+
#ifndef STM32F0xx
446+
case 2:
447+
uwAPBxPrescaler = clkconfig.APB2CLKDivider;
448+
uwTimclock = HAL_RCC_GetPCLK2Freq();
449+
break;
429450
#endif
451+
default:
452+
case 0:
453+
break;
454+
}
455+
/* When TIMPRE bit of the RCC_DCKCFGR register is reset,
456+
* if APBx prescaler is 1, then TIMxCLK = PCLKx,
457+
* otherwise TIMxCLK = 2x PCLKx.
458+
* When TIMPRE bit in the RCC_DCKCFGR register is set,
459+
* if APBx prescaler is 1,2 or 4, then TIMxCLK =HCLK,
460+
* otherwise TIMxCLK = 4x PCLKx
461+
*/
462+
#if defined(STM32F4xx) || defined(STM32F7xx)
463+
RCC_PeriphCLKInitTypeDef PeriphClkConfig = {};
464+
HAL_RCCEx_GetPeriphCLKConfig(&PeriphClkConfig);
465+
466+
if (PeriphClkConfig.TIMPresSelection == RCC_TIMPRES_ACTIVATED)
467+
switch (uwAPBxPrescaler) {
468+
default:
469+
case RCC_HCLK_DIV1:
470+
case RCC_HCLK_DIV2:
471+
case RCC_HCLK_DIV4:
472+
uwTimclock=HAL_RCC_GetHCLKFreq();
473+
break;
474+
case RCC_HCLK_DIV8:
475+
case RCC_HCLK_DIV16:
476+
uwTimclock*=4;
477+
break;
478+
}
430479
else
431-
return 0;
480+
#endif
481+
switch (uwAPBxPrescaler) {
482+
default:
483+
case RCC_HCLK_DIV1:
484+
// uwTimclock*=1;
485+
break;
486+
case RCC_HCLK_DIV2:
487+
case RCC_HCLK_DIV4:
488+
case RCC_HCLK_DIV8:
489+
case RCC_HCLK_DIV16:
490+
uwTimclock*=2;
491+
break;
492+
}
493+
return uwTimclock;
432494
}
433495

434496
/**
@@ -449,7 +511,7 @@ void TimerPulseInit(stimer_t *obj, uint16_t period, uint16_t pulseWidth, void (*
449511
//min pulse = 1us - max pulse = 65535us
450512
handle->Instance = obj->timer;
451513
handle->Init.Period = period;
452-
handle->Init.Prescaler = (uint32_t)(getTimerClkFreq(timermap_clkSrc(obj->timer, TimerMap_CONFIG)) / (1000000)) - 1;
514+
handle->Init.Prescaler = (uint32_t)(getTimerClkFreq(obj->timer) / (1000000)) - 1;
453515
handle->Init.ClockDivision = 0;
454516
handle->Init.CounterMode = TIM_COUNTERMODE_UP;
455517
#ifndef STM32L0xx
@@ -631,7 +693,7 @@ void TimerPinInit(stimer_t *obj, uint32_t frequency, uint32_t duration)
631693
digital_io_init(obj->pin, GPIO_MODE_OUTPUT_PP, GPIO_NOPULL);
632694

633695
while(end == 0) {
634-
period = ((uint32_t)(getTimerClkFreq(timermap_clkSrc(obj->timer, TimerMap_CONFIG)) / frequency / prescaler)) - 1;
696+
period = ((uint32_t)(getTimerClkFreq(obj->timer) / frequency / prescaler)) - 1;
635697

636698
if((period >= 0xFFFF) && (prescaler < 0xFFFF))
637699
prescaler++; //prescaler *= 2;

cores/arduino/stm32/timer.h

+3
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ void setTimerCounter(stimer_t *obj, uint32_t value);
9595
void setCCRRegister(stimer_t *obj, uint32_t channel, uint32_t value);
9696
uint32_t getCCRRegister(stimer_t *obj, uint32_t channel);
9797

98+
uint8_t getTimerClkSrc(TIM_TypeDef* tim);
99+
uint32_t getTimerClkFreq(TIM_TypeDef* tim);
100+
98101
void attachIntHandle(stimer_t *obj, void (*irqHandle)(stimer_t *));
99102

100103
#ifdef __cplusplus

0 commit comments

Comments
 (0)