目录
一.时间片调度
1.1 简介
同等优先级任务轮流地享有相同的 CPU 时间(可设置),叫时间片;
在FreeRTOS中,一个时间片就等于SysTick中断周期。在源码中,SysTick中断服务函数1ms中断一次,一个时间片就是1ms,滴答定时器SysTick的中断周期可以自己设置。
1.2 时间片调度运行举例
运行条件:
1.创建三个任务:Task1、Task2、Task3
2.Task1、Task2、Task3的优先级均为1;即3个任务同等优先级运行过程如下:
1、首先Task1运行完一个时间片后,切换至Task2运行(不管Task1是否运行完成,只能运行一个时间片)
2、Task2运行完一个时间片后,切换至Task3运行
3、Task3运行过程中(还不到一个时间片),Task3阻塞了(系统延时或等待信号量等,下次轮到Task3时还是只允许一个时间片,上次阻塞剩余的时间片,不会再被补回来),此时直接切换到下一个任务Task1
4、Task1运行完一个时间片后,切换至Task2运行
1.3 总结
1. 同等优先级任务,轮流执行,时间片流转;
2. 一个时间片大小,取决为滴答定时器中断频率;
3. 注意没有用完的时间片不会再使用,下次任务Task3得到执行还是按照一个时间片的时钟节拍运行。
二. 时间片调度实验
2.1使能宏
#define configUSE_PREEMPTION 1 /* 1: 抢占式调度器, 0: 协程式调度器, 无默认需定义 */
#define configUSE_TIME_SLICING 1 /* 1: 使能时间片调度, 默认: 1 */
2.2 滴答定时器中断频率
/* 定义系统时钟节拍频率, 单位: Hz, 无默认需定义 */
#define configTICK_RATE_HZ 20 //时钟节拍频率,这里设置为20,周期就是50ms
2.3 代码示例
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "FreeRTOS.h"
#include "task.h"
#include "key.h"
/*START任务的基本配置*/
#define START_STK_SIZE 128
#define START_TASK_PRIO 1
TaskHandle_t start_task_handler;
void StartTask_fun(void * pvParameters);
/*TASK1任务的基本配置*/
#define TASK1_STK_SIZE 128
#define TASK1_PRIO 2
TaskHandle_t task1_handler;
void TASK1(void * pvParameters);
/*TASK2任务的基本配置*/
#define TASK2_STK_SIZE 128
#define TASK2_PRIO 2
TaskHandle_t task2_handler;
void TASK2(void * pvParameters);
void freertosdemo()
{
xTaskCreate((TaskFunction_t ) StartTask_fun, //任务函数
(char * ) "StartTask_fun", //任务名字
(uint16_t ) START_STK_SIZE, //堆栈大小
(void * ) NULL, //任务参数
(UBaseType_t ) START_TASK_PRIO, //任务优先级
(TaskHandle_t * ) &start_task_handler);//任务句柄
vTaskStartScheduler(); //开启任务调度
}
/*
START任务创建 TASK1任务
*/
void StartTask_fun(void * pvParameters)
{
taskENTER_CRITICAL(); //进入临界区 临界区内的代码在执行过程中不被其它中断或者任务打断
xTaskCreate((TaskFunction_t ) TASK1, //任务函数
(char * ) "TASK1", //任务名字
(uint16_t ) TASK1_STK_SIZE, //堆栈大小
(void * ) NULL, //任务参数
(UBaseType_t ) TASK1_PRIO, //任务优先级
(TaskHandle_t * ) &task1_handler);//任务句柄
xTaskCreate((TaskFunction_t ) TASK2, //任务函数
(char * ) "TASK2", //任务名字
(uint16_t ) TASK2_STK_SIZE, //堆栈大小
(void * ) NULL, //任务参数
(UBaseType_t ) TASK2_PRIO, //任务优先级
(TaskHandle_t * ) &task2_handler);//任务句柄
taskEXIT_CRITICAL(); //退出临界区
vTaskDelete(NULL); //删除任务
}
/*由于时间片设置为50ms,所以每一个任务,同等享有50ms的cpu时间*/
/*通过串口打印task1的运行次数*/
void TASK1(void * pvParameters)
{
uint32_t task1_num = 0;
while(1)
{
taskENTER_CRITICAL(); //进入临界区
printf("task1运行次数:%d\r\n",++task1_num);
taskEXIT_CRITICAL(); //退出临界区
delay_ms(10);
}
}
/*通过串口打印task2的运行次数*/
void TASK2(void * pvParameters)
{
uint32_t task2_num = 0;
while(1)
{
taskENTER_CRITICAL(); //进入临界区
printf("task2运行次数:%d\r\n",++task2_num);
taskEXIT_CRITICAL(); //退出临界区
delay_ms(10);
}
}