FreeRTOS学习——接口宏portmacro.h,仅用于记录自己阅读与学习源码
FreeRTOS Kernel V10.5.1
port :GCC/ARM_CM7
Systick
源码
在Systick中断xPortSysTickHandler中,只做了一件事,那就是挂起PendSV中断。
所以其实切换任务是在PendSV中断执行的。
void xPortSysTickHandler( void )
{
/* SysTick以最低的中断优先级运行 */
portDISABLE_INTERRUPTS();
{
/* Increment the RTOS tick. */
if( xTaskIncrementTick() != pdFALSE )
{
/* 上下文切换在 PendSV 中断 中执行
* 挂起 PendSV 中断. */
portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT;
}
}
portENABLE_INTERRUPTS();
}
触发方式
在开启调度器时,会调用定时器中断设置函数vPortSetupTimerInterrupt,以生成 tick 中断,如下:
vTaskStartScheduler →
xPortStartScheduler →
vPortSetupTimerInterrupt
配置系统的滴答定时器,以允许操作系统根据配置的频率生成定时中断,从而支持任务的调度和管理
__attribute__( ( weak ) ) void vPortSetupTimerInterrupt( void )
{
/* 低功耗模式,这里先不做分析. */
#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 */
/* 停止和清除SysTick. */
portNVIC_SYSTICK_CTRL_REG = 0UL;/*将控制寄存器设置为0,停止SysTick*/
portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;/*将当前值寄存器清零。*/
/* 配置SysTick. */
/* 设置加载寄存器,将SysTick的计数重加载为目标计数值*/
portNVIC_SYSTICK_LOAD_REG = ( configSYSTICK_CLOCK_HZ / configTICK_RATE_HZ ) - 1UL;