FreeRTOS分析二—任务的启动
上一篇文章我们带着三个问题开始了对 FreeRTOS 代码的探究。
1. FreeRTOS 是如何建立任务的呢?
2. FreeRTOS 是调度和切换任务的呢?
3. FreeRTOS 是如何保证实时性呢?
并且在上一篇文章 FreeRTOS从代码层面进行原理分析(1 任务的建立) 中对任务的创建进行了分析。
这篇文章让我们一起对 FreeRTOS 是如何进行任务的调度和切换从代码的角度进行逻辑分析。
任务的调度
在 FreeRTOS 官方教程中,在创建完成任务之后只要调用 xTaskStartScheduler
函数就可以将创建的任务给执行起来了。
那么在 FreeRTOS 中任务究竟是如何调度起来的呢?现在让我们看一下 xTaskStartScheduler
这个函数的内部。
BaseType_t xPortStartScheduler( void )
{
...
/* Make PendSV and SysTick the lowest priority interrupts. */
portNVIC_SHPR3_REG |= portNVIC_PENDSV_PRI;
portNVIC_SHPR3_REG |= portNVIC_SYSTICK_PRI;
/* Start the timer that generates the tick ISR. Interrupts are disabled
* here already. */
vPortSetupTimerInterrupt();
/* Initialise the critical nesting count ready for the first task. */
uxCriticalNesting = 0;
/* Start the first task. */
prvPortStartFirstTask();
/* Should never get here as the tasks will now be executing! Call the task
* exit error function to prevent compiler warnings about a static function
* not being called in the case that the application writer overrides this
* functionality by defining configTASK_RETURN_ADDRESS. Call
* vTaskSwitchContext() so link time optimisation does not remove the
* symbol. */
vTaskSwitchContext();
prvTaskExitError();
/* Should not get here! */
return 0;
}
配置 SysTick
经过省略,上面的代码中的逻辑已经非常清晰的展现在我们的面前了。先是调整 PendSV & SysTick 的中断优先级。
然后调用 vPortSetupTimerInterrupt
设置 SysTick 中断,对应 FreeRTOS 里面就是设置任务的切换时间颗粒度。这个函数里面的代码也是很简单的。
__attribute__