77 * Date Author Notes
88 * 2018-12-10 zylx first version
99 * 2020-06-16 thread-liu Porting for stm32mp1
10+ * 2020-08-25 linyongkang Fix the timer clock frequency doubling problem
1011 */
1112
1213#include <board.h>
@@ -152,9 +153,35 @@ static struct stm32_hwtimer stm32_hwtimer_obj[] =
152153#endif
153154};
154155
156+ /* APBx timer clocks frequency doubler state related to APB1CLKDivider value */
157+ static void pclkx_doubler_get (uint32_t * pclk1_doubler , uint32_t * pclk2_doubler )
158+ {
159+ uint32_t flatency = 0 ;
160+ RCC_ClkInitTypeDef RCC_ClkInitStruct ;
161+
162+ RT_ASSERT (pclk1_doubler != RT_NULL );
163+ RT_ASSERT (pclk1_doubler != RT_NULL );
164+
165+ HAL_RCC_GetClockConfig (& RCC_ClkInitStruct , & flatency );
166+
167+ * pclk1_doubler = 1 ;
168+ * pclk2_doubler = 1 ;
169+
170+ if (RCC_ClkInitStruct .APB1CLKDivider != RCC_HCLK_DIV1 )
171+ {
172+ * pclk1_doubler = 2 ;
173+ }
174+
175+ if (RCC_ClkInitStruct .APB2CLKDivider != RCC_HCLK_DIV1 )
176+ {
177+ * pclk2_doubler = 2 ;
178+ }
179+ }
180+
155181static void timer_init (struct rt_hwtimer_device * timer , rt_uint32_t state )
156182{
157183 uint32_t prescaler_value = 0 ;
184+ uint32_t pclk1_doubler , pclk2_doubler ;
158185 TIM_HandleTypeDef * tim = RT_NULL ;
159186 struct stm32_hwtimer * tim_device = RT_NULL ;
160187
@@ -164,6 +191,8 @@ static void timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
164191 tim = (TIM_HandleTypeDef * )timer -> parent .user_data ;
165192 tim_device = (struct stm32_hwtimer * )timer ;
166193
194+ pclkx_doubler_get (& pclk1_doubler , & pclk2_doubler );
195+
167196 /* time init */
168197#if defined(SOC_SERIES_STM32F2 ) || defined(SOC_SERIES_STM32F4 ) || defined(SOC_SERIES_STM32F7 )
169198 if (tim -> Instance == TIM9 || tim -> Instance == TIM10 || tim -> Instance == TIM11 )
@@ -176,12 +205,12 @@ static void timer_init(struct rt_hwtimer_device *timer, rt_uint32_t state)
176205#endif
177206 {
178207#if !defined(SOC_SERIES_STM32F0 ) && !defined(SOC_SERIES_STM32G0 )
179- prescaler_value = (uint32_t )(HAL_RCC_GetPCLK2Freq () * 2 / 10000 ) - 1 ;
208+ prescaler_value = (uint32_t )(HAL_RCC_GetPCLK2Freq () * pclk2_doubler / 10000 ) - 1 ;
180209#endif
181210 }
182211 else
183212 {
184- prescaler_value = (uint32_t )(HAL_RCC_GetPCLK1Freq () * 2 / 10000 ) - 1 ;
213+ prescaler_value = (uint32_t )(HAL_RCC_GetPCLK1Freq () * pclk1_doubler / 10000 ) - 1 ;
185214 }
186215 tim -> Init .Period = 10000 - 1 ;
187216 tim -> Init .Prescaler = prescaler_value ;
@@ -274,6 +303,7 @@ static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
274303{
275304 TIM_HandleTypeDef * tim = RT_NULL ;
276305 rt_err_t result = RT_EOK ;
306+ uint32_t pclk1_doubler , pclk2_doubler ;
277307
278308 RT_ASSERT (timer != RT_NULL );
279309 RT_ASSERT (arg != RT_NULL );
@@ -290,6 +320,8 @@ static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
290320 /* set timer frequence */
291321 freq = * ((rt_uint32_t * )arg );
292322
323+ pclkx_doubler_get (& pclk1_doubler , & pclk2_doubler );
324+
293325#if defined(SOC_SERIES_STM32F2 ) || defined(SOC_SERIES_STM32F4 ) || defined(SOC_SERIES_STM32F7 )
294326 if (tim -> Instance == TIM9 || tim -> Instance == TIM10 || tim -> Instance == TIM11 )
295327#elif defined(SOC_SERIES_STM32L4 )
@@ -300,19 +332,13 @@ static rt_err_t timer_ctrl(rt_hwtimer_t *timer, rt_uint32_t cmd, void *arg)
300332 if (0 )
301333#endif
302334 {
303- #if defined(SOC_SERIES_STM32L4 )
304- val = HAL_RCC_GetPCLK2Freq () / freq ;
305- #elif defined(SOC_SERIES_STM32F1 ) || defined(SOC_SERIES_STM32F2 ) || defined(SOC_SERIES_STM32F4 ) || defined(SOC_SERIES_STM32F7 ) || defined(SOC_SERIES_STM32MP1 )
306- val = HAL_RCC_GetPCLK2Freq () * 2 / freq ;
335+ #if !defined(SOC_SERIES_STM32F0 ) && !defined(SOC_SERIES_STM32G0 )
336+ val = HAL_RCC_GetPCLK2Freq () * pclk2_doubler / freq ;
307337#endif
308338 }
309339 else
310340 {
311- #if defined(SOC_SERIES_STM32F1 ) || defined(SOC_SERIES_STM32F2 ) || defined(SOC_SERIES_STM32F4 ) || defined(SOC_SERIES_STM32F7 ) || defined(SOC_SERIES_STM32MP1 )
312- val = HAL_RCC_GetPCLK1Freq () * 2 / freq ;
313- #elif defined(SOC_SERIES_STM32F0 ) || defined(SOC_SERIES_STM32G0 )
314- val = HAL_RCC_GetPCLK1Freq () / freq ;
315- #endif
341+ val = HAL_RCC_GetPCLK1Freq () * pclk1_doubler / freq ;
316342 }
317343 __HAL_TIM_SET_PRESCALER (tim , val - 1 );
318344
0 commit comments