8,FreeRTOS时间片调度
一、实验目标
创建三个动态任务,栈空间大小均为128字。startTask、Task1、Task2。startTask仅运行一次,负责task1、task2任务的创建,startTask任务的删除。Task1负责打印Task1执行次数,Task2负责打印Task1执行次数,二者优先级相同。
注:本实验基于正点原子FreeRTOS教程的学习总结。
时间片调度特点:
1.同等优先级的任务回轮流执行;
2.一个时间片的大小取决于滴答定时器的中断频率;
3.没有用完的时间片(任务中,任务阻塞),下次任务执行还是一个时间片,上次剩下的时间不会补齐。
二、实验准备
1.FreeRTOS的Keil动态任务创建与删除程序
2.STM3F407开发板
3.时间片相关宏定义使能
使能抢占式调度以及时间片调度,将下面两个宏定义置一。
#define configUSE_PREEMPTION 1 /* 1: 抢占式调度器, 0: 协程式调度器, 无默认需定义 */
#define configUSE_TIME_SLICING 1 /* 1: 使能时间片调度, 默认: 1 */
configTICK_RATE_HZ用来设置滴答定时器频率,默认1000Hz时间片为1ms,这里改为20Hz时间片为50ms。
#define configTICK_RATE_HZ 20 /* 定义系统时钟节拍频率, 单位: Hz, 无默认需定义 */
三、代码编写
3.1修改Task1的任务函数内容
Task1中使用临界区代码保护主要放置printf运行中被任务切换打断,注意这里使用的是delay_ms()死循环延时,而不是vTaskDelay()。是因为vTaskDelay会导致当前任务阻塞。
void task1(void *pvParameters)
{uint32_t task1_num = 0;while(1){taskENTER_CRITICAL(); /* 进入临界区 */printf("task1 num:%d\r\n",task1_num++);taskEXIT_CRITICAL(); /* 退出临界区 */delay_ms(10);}
}
3.2修改Task2的任务函数内容
Task2同上。
void task2(void *pvParameters)
{uint32_t task2_num = 0;while(1){taskENTER_CRITICAL(); /* 进入临界区 */printf("task2 num:%d\r\n",task2_num++);taskEXIT_CRITICAL(); /* 退出临界区 */delay_ms(10);}
}
四、实验现象
实验现象如下所示。可以看到每个task任务会发送4-5次的printf,然后就被时间片调度到另一任务中。我们当前设置的时间片大小是50ms,任务中运行的所需时间是>10ms,所以一次时间片会printf串口4次多一点,但由于采用了代码保护,超过4次多一点的printf也会被完全执行。
所以可以看到每个task任务会发送4-5次的printf。