最近做新项目更新了一下STM32CubeMX到4.16.1,执行生成代码时提示:
WARNINGS:
- When FreeRTOS is used, it is strongly recommanded to use HAL timebase source other than the Systick.
然后按提示设置SYS部分的Timebase Source,除了SysTick可选的就是各个未占用的TIM。
按我之前的理解,SysTick就是为了RTOS准备的专用定时器,这会CubeMX让我选普通的TIM,有点晕了,不知道为什么。
SysTick与TIM做RTOS的timebase,孰优孰劣?
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
刚研究STM32CUBE 产生的 FREERTOS代码,搞清楚它那个提示是怎么回事了,它提示的意思是HAL时基 不要选的和 RTOS的一样,RTOS默认是使用SysTick的中断来调度任务的,但是 HAL库也需要一个周期性的中断,它就建议你这两个周期性的中断不要用一个定时器。具体看摘出来的代码。
1 RTOS port.c里面的代码
/* Constants required to manipulate the core. Registers first... */
#define portNVIC_SYSTICK_CTRL_REG ( * ( ( volatile uint32_t * ) 0xe000e010 ) )
#define portNVIC_SYSTICK_LOAD_REG ( * ( ( volatile uint32_t * ) 0xe000e014 ) )
#define portNVIC_SYSTICK_CURRENT_VALUE_REG ( * ( ( volatile uint32_t * ) 0xe000e018 ) )
#define portNVIC_SYSPRI2_REG ( * ( ( volatile uint32_t * ) 0xe000ed20 ) )
以上宏定义的地址 就是STM32各系列 的 Systick的相关寄存器地址。
void vPortSetupTimerInterrupt( void ) /*该函数在xPortStartScheduler( void )里被调用,也就是系统启动调度的时候,会初始化SysTick来产生定时中断的*/
{
/* Calculate the constants required to configure the tick interrupt. */
#if configUSE_TICKLESS_IDLE == 1
{
ulTimerCountsForOneTick = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ );
xMaximumPossibleSuppressedTicks = portMAX_24_BIT_NUMBER / ulTimerCountsForOneTick;
ulStoppedTimerCompensation = portMISSED_COUNTS_FACTOR / ( configCPU_CLOCK_HZ / configSYSTICK_CLOCK_HZ );
}
#endif /* configUSE_TICKLESS_IDLE */
/* Configure SysTick to interrupt at the requested rate. */
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;
portNVIC_SYSTICK_CTRL_REG = ( portNVIC_SYSTICK_CLK_BIT | portNVIC_SYSTICK_INT_BIT | portNVIC_SYSTICK_ENABLE_BIT );
}
2 再来 找到 #define xPortSysTickHandler SysTick_Handler
在找到 该函数的实现代码 ,实现了RTOS时钟节拍的递增
void xPortSysTickHandler( void )
{
/* The SysTick runs at the lowest interrupt priority, so when this interrupt
executes all interrupts must be unmasked. There is therefore no need to
save and then restore the interrupt mask value as its value is already
known - therefore the slightly faster vPortRaiseBASEPRI() function is used
in place of portSET_INTERRUPT_MASK_FROM_ISR(). */
vPortRaiseBASEPRI();
{
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* A context switch is required. Context switching is performed in
the PendSV interrupt. Pend the PendSV interrupt. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
vPortClearBASEPRIFromISR();
}
3 另外HAL库本身一些函数的操作是需要始终节拍的,所以把这两个时钟节拍独立开来。
一周热门 更多>