FreeRTOS有三种调度算法:带时间片的抢占式调度、不带时间片的抢占式调度、协作式调度。
时间片(Time Slicing)
时间片可以让优先级相等的任务之间获得近似均等的执行事件。


注意:上面的情况是优先级相同的情况,如果优先级不同,按照抢占式调度规则决定。
通过配置文件开关时间片
在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. */ |
| configUSE_PREEMPTION | configUSE_TIME_SLICING | |
|---|---|---|
| 带时间片的抢占式调度 | 1 | 1 |
| 不带时间片的抢占式调度 | 1 | 0 |
| 协作式调度 | 0 | × |
例:在时间片关闭和时间片开启的情况下,分别测试以下程序,看看输出结果有什么区别。
12345678910111213141516171819202122232425262728 | 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次。
再测试打开时间片的状况,把configUSE_TIME_SLICING设置为1,打开时间片。
实验现象是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:
configTICK_RATE_HZ设置为1000:
可以看出,原先每打印6次切换一次任务,现在变成每打印1次切换一次任务。