前言
记录一下,在使用CubeMx生成的裸机模版移植完STemWin后,想再移植官方下载FreeRTOS的时候,遇到的一些问题。主要现象是编译没有错误,然后下载程序后,没办法运行对应程序,调试后发现进入HardFault_Handler,经过排查发现是FreeRTOS的心跳时钟与SysTick心跳有冲突。即SysTick没选择其他方式作为心跳源。
一、STM32CubeMX生成模版代码中的Systick的配置
1、Systick的初始化位于 HAL_Init() 中
2、具体位于HAL_InitTick( TICK_INT_PRIORITY ); 中
3、HAL_InitTick 中的详细代码
- __weak 关键字:若两个或两个以上全局符号(函数或变量名)名字一样,而其中之一声明为weak属性,则这些全局符号不会引发重定义错误。链接器会忽略弱符号,去使用普通的全局符号来解析所有对这些符号的引用,但当普通的全局符号不可用时,链接器会使用弱符号。当有函数或变量名可能被用户覆盖时,该函数或变量名可以声明为一个弱符号
- 我们所需要做的就是重新写一个HAL_InitTick( ) ,然后在里面配置我们定时器,然后在定时器中断服务函数中添加HAL_IncTick() 就行了。
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
/* Configure the SysTick to have interrupt in 1ms time basis*/
if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
{
return HAL_ERROR;
}
/* Configure the SysTick IRQ priority */
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
{
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
uwTickPrio = TickPriority;
}
else
{
return HAL_ERROR;
}
/* Return function status */
return HAL_OK;
}
二、STM32CubeMX生成的TIM2作为Systick心跳的模版代码
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
{
RCC_ClkInitTypeDef clkconfig;
uint32_t uwTimclock = 0;
uint32_t uwPrescalerValue = 0;
uint32_t pFLatency;
/*Configure the TIM2 IRQ priority */
HAL_NVIC_SetPriority(TIM2_IRQn, TickPriority ,0);
/* Enable the TIM2 global Interrupt */
HAL_NVIC_EnableIRQ(TIM2_IRQn);
/* Enable TIM2 clock */
__HAL_RCC_TIM2_CLK_ENABLE();
/* Get clock configuration */
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
/* Compute TIM2 clock */
uwTimclock = 2*HAL_RCC_GetPCLK1Freq();
/* Compute the prescaler value to have TIM2 counter clock equal to 1MHz */
uwPrescalerValue = (uint32_t) ((uwTimclock / 1000000) - 1);
/* Initialize TIM2 */
htim2.Instance = TIM2;
/* Initialize TIMx peripheral as follow:
+ Period = [(TIM2CLK/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
*/
htim2.Init.Period = (1000000 / 1000) - 1;
htim2.Init.Prescaler = uwPrescalerValue;
htim2.Init.ClockDivision = 0;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
if(HAL_TIM_Base_Init(&htim2) == HAL_OK)
{
/* Start the TIM time Base generation in interrupt mode */
return HAL_TIM_Base_Start_IT(&htim2);
}
/* Return function status */
return HAL_ERROR;
}
//TIM2中断服务函数
void TIM2_IRQHandler(void)
{
HAL_TIM_IRQHandler(&htim2);
}
//TIM中断回调函
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
if(htim->Instance == TIM2)
{
HAL_IncTick(); //Systick的心跳
}
}
三、步骤总结
- 重写 HAL_InitTick
- 在 HAL_InitTick 中配置对应定时器、使能定时器基本功能与中断功能
- 在中断服务函数中使用HAL提供的统一回调函数(会自动清除对应标志位),然后在里面添加HAL_IncTick()