本文是FreeRTOS复习笔记的第五节,时间片调度。
上一篇文章: 【复习笔记】reeRTOS(四) 列表项的插入和删除
文章目录
- 1.时间片调度简介
- 1.1. 运行过程
- 二、实验设计
- 三、测试例程
- 四、实验效果
1.时间片调度简介
FreeRTOS支持多个任务同时拥有一个优先级,这些任务的调度就可以使用时间片来进行调度。在FreeRTOS中允许一个任务允许一个时间片(一个时钟节拍的长度)后让出CPU的使用权,让拥有同优先级的下个任务运行。
同等优先级任务轮流地享有相同的 CPU 时间(可设置), 叫时间片。在FreeRTOS中,一个时间片就等于SysTick 中断周期,这个SysTick中断周期可以自己设置。在SysTick中断服务函数中,一个时间片就是1ms。
1.1. 运行过程
1、首先Task1运行完一个时间片后,切换至Task2运行,不管Task1是否运行完成,只运行一个时间片(默认1ms)Task1
2、Task2运行完一个时间片后,切换至Task3运行
3、Task3运行过程中(还不到一个时间片),Task3阻塞了(系统延时或等待信号量等,下次轮到Task3时还是只允许一个时间片,上次阻塞剩余的时间片,不会再被补回来),此时直接切换到下一个任务Task1
4、Task1运行完一个时间片后,切换至Task2运行
二、实验设计
实验目的:学会对FreeRTOS 时间片调度使用
实验设计:设计两个任务: task1 task 和 task2 task ,其中 task1 task 和 task2 task的任务优先级相同,都为 2,这两个任务的任务功能如下:
- task1 task :控制 LED灯闪烁,并且通过串口打印 taskl task 的运行次数
- task2 task :通过串口打印 task2 task 的运行次数
三、测试例程
主函数 main.c代码如下:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"//在FreeRTOSConfig.h 把configTICK_RATE_HZ改成20,也就是每50ms切换一次任务
void task1_task(void *p); //任务函数
void task2_task(void *p); //任务函数int main(void)
{ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4delay_init(168); //初始化延时函数uart_init(115200); //初始化串口LED_Init(); //初始化LED端口xTaskCreate(task1_task,"task1_task",128,NULL,2,NULL); //任务1 xTaskCreate(task2_task,"task2_task",128,NULL,2,NULL); //任务2 vTaskStartScheduler(); //开启任务调度
}//任务1函数
void task1_task(void *p)
{u8 task1_num=0;while(1){task1_num++; //任务1执行次数加1 注意task1_num1加到255的时候会清零!!LED0=!LED0;taskENTER_CRITICAL(); //进入临界区,如果不加临界区,任务执行一半就会跳出printf("任务1已经执行:%d次\r\n",task1_num);taskEXIT_CRITICAL(); //退出临界区delay_xms(10); //延时10ms,模拟任务运行10ms,此函数不会引起任务调度}
} //任务2函数
void task2_task(void *p)
{u8 task2_num=0;while(1){task2_num++; //任务2执行次数加1 注意task2_num1加到255的时候会清零!!taskENTER_CRITICAL(); //进入临界区printf("任务2已经执行:%d次\r\n",task2_num);taskEXIT_CRITICAL(); //退出临界区delay_xms(10); //延时10ms,模拟任务运行10ms,此函数不会引起任务调度}
}
在任务程序的printf函数前后分别添加临界区进入和退出目的是:防止prinf打印到一半字符,就被暂停,切换到了另一个任务。临界区包护可以让prinf执行完再切换任务。
此外,还要在在FreeRTOSConfig.h 把configTICK_RATE_HZ把原来的1000改成20,也就是每50ms切换一次任务。
#define configTICK_RATE_HZ (20) //时钟节拍频率,这里设置为20,周期就是50ms
调用函数 delay_xms()延时 10ms。在一个时间片内如果任务不主动放弃 CPU 使用权的话那么就会一直运行这一个任务,直到时间片耗尽。在 task1_task 任务中我们通过串口打印字符串的方式提示 task1_task 在运行,但是这个过程对于 CPU 来说执行速度很快,不利于观察,所以这里通过调用函数 delay_xms()来默认任务占用 10ms 的 CPU。函数 delay_xms()不会引起务调度,这样的话相当于 task1 task 的执行周期>10s,基本可以看作等于 10ms,因为其他的函数执行速度还是很快的。一个时间片的长度是50ms,任务执行所需的时间以 10ms 算,理论上在一个时间片内 task1_task 可以执行 5 次,但是事实上很少能执行 5 次,基本上是4次。
四、实验效果
实验效果如下:
接上串口,会打印任务1和任务2的运行次数。
我们设置任务运行周期是50ms,然后每个任务里面有10ms的延时,由于单片机执行printf打印函数时间会长一些,任务1里还有LED控制的函数,所以,每次执行本任务最多只能打印5次数据。有时执行了4次printf,还没来得及执行第5次,但50ms时间到了就会强制切换到了另一个任务。
本节主要是学习和掌握任务创建以及 vTaskDelete() 任务删除函数的使用。
完整程序放在gitee仓库上:程序下载。