本帖最后由 铁血丹心LLLL 于 2022-2-28 16:28 编辑
在使用STM32CubeMX生成对应的STM32工程时,很多时候在配置SYS的时候,会直接忽略掉时基源的选择,而STM32CubeMX默认选择的是Systick,作为HAL库的时基,用于一些超时操作,像I2C\USART等,都会用到。
而在实际的应用中,如果不跑裸机,就会用到Systick,作为RTOS的时基。许多人使用HAL库的时候,都会很习惯使用HAL_Delay作为毫秒级的延时(当然也可以作为us级别的,需要去改)。但上了RTOS,由于systick被HAL占用了,如果在Systick的中断中,继续添加RTOS的计数,不是不行,在使用STM32CubeMX 加上FreeRTOS的时候,就会有这样的提示:
其实你可以忽略掉这个,直接生成,得到的FreeRTOS的工程也是能用的,但是如果使用DWT作为时间戳进行时间测量(时间足够长),你会发现对比出来有时间差。并且官方也是极力不推荐的。
当然,面对这种尴尬的情况,也是有解决方案的
1 、在杰杰的博客中有提到,使用Cortex-M内核中的一个调试追踪器----DWT,DWT有计数器寄存器,可以代替SYSTICK进行足够时间的计数。具体可看他的博客:https://blog.csdn.net/jiejiemcu/article/details/83932913
2、使用一个TIM来代替systick进行延时。具体在使用STM32CubeMX生成的时候,将Systick换
成一个自己不常用的基本定时器:
配置出来的工程中,会出现一个文件,
这里就已经将你的TIM6(或者别的,自己选择的)初始化并配置好了,基本上不需要自己配置,当然也可以自己配置初始化,将原本放在Systick中断中的
这个函数,放在TIM6的中断服务函数中,也是可以的。
而也可以学官方的来改,
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
RCC_ClkInitTypeDef clkconfig;
uint32_t uwTimclock = 0;
uint32_t uwPrescalerValue = 0;
uint32_t pFLatency;
/*Configure the TIM6 IRQ priority */
HAL_NVIC_SetPriority(TIM6_DAC_IRQn, TickPriority ,0);
/* Enable the TIM6 global Interrupt */
HAL_NVIC_EnableIRQ(TIM6_DAC_IRQn);
/* Enable TIM6 clock */
__HAL_RCC_TIM6_CLK_ENABLE();
/* Get clock configuration */
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
/* Compute TIM6 clock */
uwTimclock = 2*HAL_RCC_GetPCLK1Freq();
/* Compute the prescaler value to have TIM6 counter clock equal to 1MHz */
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000) - 1);
/* Initialize TIM6 */
htim6.Instance = TIM6;
/* Initialize TIMx peripheral as follow:
+ Period = [(TIM6CLK/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
*/
htim6.Init.Period = (1000000 / 1000) - 1;
htim6.Init.Prescaler = uwPrescalerValue;
htim6.Init.ClockDivision = 0;
htim6.Init.CounterMode = TIM_COUNTERMODE_UP;
if(HAL_TIM_Base_Init(&htim6) == HAL_OK)
{
/* Start the TIM time Base generation in interrupt mode */
return HAL_TIM_Base_Start_IT(&htim6);
}
/* Return function status */
return HAL_ERROR;
}
改好之后,在上RTOS的时候,记得在TIM6中断中,加入临界段保护(或进入中断保护),否则会出现意想不到的结果,反正我第一次这样做的时候,运行了5分钟左右就死机了,当时也不明白为啥。。。现在也不明白,后来发现中断那里写少了东西,加上之后就好了。
|