(RTOS笔记2)Timebase source 时基解释
一.软硬件版本信息:
STM32Cube Mx 5.30
Keil 5.29.0.0
STM32H750XB
二.时基
裸机运行时只需要维护一个时基就可以了,在加上操作系统时我们需要提供第二个时基来保证hal库和操作系统同时运行
运行需要的时基:
1.HAL的时基:Timebase Source
2.OS的时基: 使用操作系统时
1.为什么要有时基
时基就是为运行程序时提供一个时间,比如延时函数,在HAL库和操作系统都有,还有其他需要提供时钟的函数,而时基就是为这些需要时钟的函数提供一个时间线(说简单点就是给他一个表,让他计时)。要明白这个不是RCC。
2.裸机运行
裸机运行时时基的配置:
这是默认配置,也就是CubeMX在裸机运行时推荐使用滴答定时器来作为时钟源,当然也可以选用定时器TIM1或者其他。
(1)默认配置SysTick
在生成的工程中stm32h7xx_hal.c中的初始化HAL库的函数 HAL_Init(void);
下面展示一些 内联代码片
。
HAL_StatusTypeDef HAL_Init(void)
{
#if defined(DUAL_CORE) && defined(CORE_CM4)
/* Configure Cortex-M4 Instruction cache through ART accelerator */
__HAL_RCC_ART_CLK_ENABLE(); /* Enable the Cortex-M4 ART Clock */
__HAL_ART_CONFIG_BASE_ADDRESS(0x08100000UL); /* Configure the Cortex-M4 ART Base address to the Flash Bank 2 : */
__HAL_ART_ENABLE(); /* Enable the Cortex-M4 ART */
#endif /* DUAL_CORE && CORE_CM4 */
/* Set Interrupt Group Priority */
HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);
/* Update the SystemCoreClock global variable */
SystemCoreClock = HAL_RCC_GetSysClockFreq() >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_D1CPRE)>> RCC_D1CFGR_D1CPRE_Pos]) & 0x1FU);
/* Update the SystemD2Clock global variable */
SystemD2Clock = (SystemCoreClock >> ((D1CorePrescTable[(RCC->D1CFGR & RCC_D1CFGR_HPRE)>> RCC_D1CFGR_HPRE_Pos]) & 0x1FU));
/* Use systick as time base source and configure 1ms tick (default clock after Reset is HSI) */
if(HAL_InitTick(TICK_INT_PRIORITY) != HAL_OK)
{
return HAL_ERROR;
}
/* Init the low level hardware */
HAL_MspInit();
/* Return function status */
return HAL_OK;
}
其中HAL_InitTick()解释为:Use systick as time base source and configure 1ms tick
使用systick作为时基源来配置1ms的tick;
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* Check uwTickFreq for MisraC 2012 (even if uwTickFreq is a enum type that don't take the value zero)*/
if((uint32_t)uwTickFreq == 0UL)
{
return HAL_ERROR;
}
该函数是一个弱化函数
(2)使用TIM1配置
生成工程:
这时User中会多生成一个stm32h7xx_hal_timebase_tim.c文件,该文件中对函数HAL_InitTick()进行了定义
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
RCC_ClkInitTypeDef clkconfig;
uint32_t uwTimclock = 0;
uint32_t uwPrescalerValue = 0;
uint32_t pFLatency;
/*Configure the TIM1 IRQ priority */
HAL_NVIC_SetPriority(TIM1_UP_IRQn, TickPriority ,0);
/* Enable the TIM1 global Interrupt */
HAL_NVIC_EnableIRQ(TIM1_UP_IRQn);
/* Enable TIM1 clock */
__HAL_RCC_TIM1_CLK_ENABLE();
/* Get clock configuration */
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
/* Compute TIM1 clock */
uwTimclock = 2*HAL_RCC_GetPCLK2Freq();
/* Compute the prescaler value to have TIM1 counter clock equal to 1MHz */
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000) - 1);
/* Initialize TIM1 */
htim1.Instance = TIM1;
/* Initialize TIMx peripheral as follow:
+ Period = [(TIM1CLK/1000) - 1]. to have a (1/1000) s time base.
+ Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
+ ClockDivision = 0
+ Counter direction = Up
*/
htim1.Init.Period = (1000000 / 1000) - 1;
htim1.Init.Prescaler = uwPrescalerValue;
htim1.Init.ClockDivision = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
if(HAL_TIM_Base_Init(&htim1) == HAL_OK)
{
/* Start the TIM time Base generation in interrupt mode */
return HAL_TIM_Base_Start_IT(&htim1);
}
/* Return function status */
return HAL_ERROR;
}
这里将TIM1作为时基
同时在stm32h7xx_hal.c中还有HAL_InitTick()的定义,和默认状态下的一样
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* Check uwTickFreq for MisraC 2012 (even if uwTickFreq is a enum type that don't take the value zero)*/
if((uint32_t)uwTickFreq == 0UL)
{
return HAL_ERROR;
}
因为这里是弱化的函数所以有了stm32h7xx_hal_timebase_tim.c文件中对HAL_InitTick()的定义,系统默认的这个软化函数就不使用了,相当于被注释掉,同样stm32h7xx_hal_timebase_tim.c文件中的HAL——InitTick()函数也是起到提给一个1ms的tick;
这样无论是使用Systick作为时基或者TIMx作为时基对于HAL库的运行是没有问题的,也是必要的。
3。有操作系统
有操作系统运行时,在FreeRTOSConfig.h中定义了为操作系统提供时钟的时基:
/* IMPORTANT: This define is commented when used with STM32Cube firmware, when the timebase source is SysTick,
to prevent overwriting SysTick_Handler defined within STM32Cube HAL */
#define xPortSysTickHandler SysTick_Handler
同时 HAL库作为底层也是需要进行运行的,操作系统设计中时将systick作为时基来运行的,那么现在只能更改为HAL库提供时钟的时基了,现在就需要选用TIMx来作为HAL库的运行时基。
两个时基相同时可能会出现程序卡死的情况或者运行出错
我个人认为是HAL库和RTOS在公用一个时基时会出现计时混乱使得HAL库的延时和超时函数与操作系统的延时函数会冲突导致的!
三.总结
使用RTOS时我们需要配置两个不同的时基分别来为HAL库和RTOS提供时钟,说实话,这个H7的资源还是比较充足的不需要为了节省一个定时器使得整个工程存在隐患,虽然同用一个时基有些情况也是可以的但是复杂的工程一旦出错就是一个非常麻烦的事情了!