FreeRTOS调度器开启分析

前言:
FreeRTOS 我们应用程序在创建一系列任务之后,需开启任务调度(vTaskStartSchedulerd)任务才能得到运行,开启任务调度后,开始运行第一个任务,随后在内核调度下按照抢占式或者时间片轮转等规则运行其他任务。下面分析一下,开启任务调度的时候,操作系统做了什么?

一. vTaskStartScheduler函数
下图中为vTaskStartScheduler()函数的主要内容:
1.创建idle任务,idle任务是优先级最低的任务,当系统中没有其他任务被调度运行的时候,idle会得到运行(必须保证系统中有一个任务在运行),idle任务可用于删除其他任务或者回收系统资源;
2.创建软件定时器任务;
3.关闭中断,避免在开启调度器过程中被系统中断打断,已经被创建的任务的任务栈中包含打开中断的字节,在调度器开启后,第一个任务运行的时候将中断打开;
4.初始化一些全局变量
xNextTaskUnblockTime = portMAX_DELAY ,表示最近需要被解锁任务的时刻,此时初始化为最大值;
xTickCount = 0 ,系统时钟节拍器,启动调度器时清0,系统节拍时钟发生中断后加1;
xSchedulerRunning = pdTRUE ,表示调度器已经开始运行;
5. 配置定时器时基,该定时器用于统计任务运行时间,用于定位问题,调试使用
portCONFIGURE_TIMER_FOR_RUN_TIME_STATS();
6. xPortStartScheduler(), 开始系统调度,开始调度后,后面的代码不会运行了, 开始第一个任务便不再返回,除非系统发生异常。
FreeRTOS调度器开启分析_第1张图片
二. xPortStartScheduler函数
在该函数中开启第一个任务,主要包括以下几部分:
①. 设置PendSV和SYSTick中断优先级为最低,PendSV中断用于切换任务,优先级设为最低,避免任务在执行一些其他应用中断业务的时候被切换走,提高了系统的实时性;
②. 设置滴答定时器周期以及使能滴答定时器中断,滴答定时器周期为1ms, 根据configTICK_RATE_HZ计算
③. 启动第一个任务 prvStartFirstTask(),该函数通过SVC指令启动SVC中断,在该中断服务函数中开启第一个任务, SVC中断只在开启第一个任务时调用一次,任务调度器开始以后,后续任务的切换都是通过PendSV中断处理的。
FreeRTOS调度器开启分析_第2张图片
以下为上面两个函数的源代码

void vTaskStartScheduler( void )
{
   
BaseType_t xReturn;

	/* Add the idle task at the lowest priority. */
	#if( configSUPPORT_STATIC_ALLOCATION == 1 )
	{
   
		StaticTask_t *pxIdleTaskTCBBuffer = NULL;
		StackType_t *pxIdleTaskStackBuffer = NULL;
		uint32_t ulIdleTaskStackSize;

		/* The Idle task is created using user provided RAM - obtain the
		address of the RAM then create the idle task. */
		vApplicationGetIdleTaskMemory( &pxIdleTaskTCBBuffer, &pxIdleTaskStackBuffer, &ulIdleTaskStackSize );
		xIdleTaskHandle = xTaskCreateStatic(	prvIdleTask,
												configIDLE_TASK_NAME,
												ulIdleTaskStackSize,
												( void * ) NULL, 

你可能感兴趣的:(FreeRTOS,操作系统)