FreeRTOS 任务管理之时间片

FreeRTOS有三种调度算法:带时间片的抢占式调度、不带时间片的抢占式调度、协作式调度。

时间片(Time Slicing)

时间片可以让优先级相等的任务之间获得近似均等的执行事件。

时间片1

时间片2
注意:上面的情况是优先级相同的情况,如果优先级不同,按照抢占式调度规则决定。

通过配置文件开关时间片

在Core->Inc->FreeRTOSConfig.h中,找到configUSE_TIME_SLICING,配置是否开启时间片,写0代表不带时间片,写1代表带时间片。

123456
/* Set configUSE_TIME_SLICING to 1 to have the scheduler switch between Ready* state tasks of equal priority on every tick interrupt. Set* configUSE_TIME_SLICING to 0 to prevent the scheduler switching between Ready* state tasks just because there was a tick interrupt. See* https://freertos.org/single-core-amp-smp-rtos-scheduling.html. */#define configUSE_TIME_SLICING 1
configUSE_PREEMPTIONconfigUSE_TIME_SLICING
带时间片的抢占式调度11
不带时间片的抢占式调度10
协作式调度0×

例:在时间片关闭和时间片开启的情况下,分别测试以下程序,看看输出结果有什么区别。

12345678910111213141516171819202122232425262728
#include <string.h> const char *task1Str = "Task 1 is running.\n";//Task1要打印的字符串const char *task2Str = "Task 2 is running.\n";//Task2要打印的字符串 //通过串口打印字符串static void PrintString(const char *Str){	vTaskSuspendAll();//暂停调度器	HAL_UART_Transmit(&huart1, (const uint8_t *)Str, strlen(Str), HAL_MAX_DELAY);	xTaskResumeAll();//恢复调度器} //任务1和任务2共用该代码,通过pvParameters传递要打印的字符串//作用是通过串口打印字符串100次void vTaskFunction(void *pvParameters){	const char *str = (const char *)pvParameters;	for(int i = 0; i < 100; i++)	{		PrintString(str);	}	vTaskDelete(NULL);} //以相同优先级创建两个任务,但指定不同的参数xTaskCreate(vTaskFunction, "Task1", 128, (void *)task1Str, 1, NULL);xTaskCreate(vTaskFunction, "Task2", 128, (void *)task2Str, 1, NULL);

先测试关闭时间片的状况,把configUSE_TIME_SLICING设置为0,关闭时间片。
实验现象是Task 1 is running.先打印100次,然后Task 2 is running.再打印100次。
实验现象是`Task 1 is running.`先打印100次,然后`Task 2 is running.`再打印100次。
再测试打开时间片的状况,把configUSE_TIME_SLICING设置为1,打开时间片。
实验现象是Task 1 is running.和Task 2 is running.交替打印。
实验现象是`Task 1 is running.`和`Task 2 is running.`交替打印。

时间片的底层工作原理

SysTick中断产生时间片。
在vTaskStartScheduler()的内部会自动配置并启动SYSTICK
两个SYSTICK中断之间,就是一个时间片。

调整时间片长度

在Core->Inc->FreeRTOSConfig.h中,使用configTICK_RATE_HZ来修改SYSTICK参数,用来设置SYSTICK中断的频率,单位是赫兹。
默认设置是100,意味着每秒钟SYSTICK溢出100次,即每次10ms,因此时间片长度就是10ms。

例:使用上例的程序,测试configTICK_RATE_HZ设置为100和1000时程序的输出结果有何不同。
configTICK_RATE_HZ设置为100:
实验现象是`Task 1 is running.`和`Task 2 is running.`交替打印。
configTICK_RATE_HZ设置为1000:
原先每打印6次切换一次任务,现在变成每打印1次切换一次任务。
可以看出,原先每打印6次切换一次任务,现在变成每打印1次切换一次任务。

🔍 ×