RTOS学习笔记–时间片调度
本文基于正点原子RTOS开发指南,笔记自用,获取详细信息请关注正点原子官方账号
介绍:在RTOS中,除了按优先级调度之外,还可以按照时间片调度,也就是给每个任务分配一个时间片,在该时间片中执行任务。时间片可以设置,由SystemStick决定
其结构如下所示
- 首先Task1运行完一个时间片后,切换至Task2运行
- Task2运行完一个时间片后,切换至Task3运行
- Task3运行过程中(还不到一个时间片),Task3阻塞了(系统延时或等待信号量等),此时直接切换到下一个任务Task1
- Task1运行完一个时间片后,切换至Task2运行
注意:
- 同等优先级任务,轮流执行;时间片流转
- 一个时间片大小,取决为滴答定时器中断频率
- 注意没有用完的时间片不会再使用,下次任务Task3得到执行还是按照一个时间片的时钟节拍运行
如果在一个时间片内,任务没有执行完毕,那么将会等到下一个时间片在继续该任务剩下的代码。
代码实现
开启时间片调度,以及设置时间片
/*FreeRTOSConfig.h*/
#define configUSE_PREEMPTION 1
/*FreeRTOS.h*/
#ifndef configUSE_TIME_SLICING
#define configUSE_TIME_SLICING 1
#endif
设置时间片周期
/*FreeRTOSConfig.h*/
#define configTICK_RATE_HZ ((TickType_t)20)/*1000/20 = 50ms*/
/*设置的是频率 频率为20HZ 周期为1/20=0.05s =50ms*/
设置要按时间片调度任务优先级相同
/*任务2*/
#define TASK2_PRIO 2
/*任务3*/
#define TASK3_PRIO 2
任务实现
/*任务2*/
void task2(void *argv)
{
uint32_t task2_times=0;
while(1)
{
/*进去临界区,保护数据*/
taskENTER_CRITICAL();
printf("Task2 Run times:%d\r\n",task2_times++);
/*退出临界区*/
taskEXIT_CRITICAL();
HAL_Delay(10);
}
}
/*任务3*/
void task3(void *argv)
{
uint32_t task3_times=0;
while(1)
{
taskENTER_CRITICAL();
printf("Task3 Run times:%d\r\n",task3_times++);
taskEXIT_CRITICAL();
HAL_Delay(10);
}
}
分析:
- 没有采用阻塞延时vTaskDelay(n) 使其进入阻塞态,说明其一直处于就绪态
- 按照一个时间片运行时间是50ms
运行结果
Task2 Run times:0
Task2 Run times:1
Task2 Run times:2
Task2 Run times:3
Task2 Run times:4
Task3 Run times:0
Task3 Run times:1
Task3 Run times:2
Task3 Run times:3
Task3 Run times:4
Task2 Run times:5
Task2 Run times:6
Task2 Run times:7
Task2 Run times:8
Task3 Run times:5
Task3 Run times:6
Task3 Run times:7
Task3 Run times:8
Task2 Run times:9
Task2 Run times:10
Task2 Run times:11
Task2 Run times:12
Task2 Run times:13
分析
- 一个时间片运行时间是50ms,而一个任务延时10ms,由于printf也占用时间,所以理论上一个时间片打印4-5次左右。
如果任务的优先级不同如Task2为2 Task3 为3 则会一直在Task3中运行,是抢占式调度,而Task3中使用HAL_Delay延时,也就是一直处于就绪态,从未退出,所以会一直运行