目录
一 建立任务
任务三要素:任务栈,任务控制块,任务函数
OS_TCB StartTaskTCB; //任务控制块
CPU_STK START_TASK_STK[128];//任务堆栈
void start_task(void *p_arg);//任务函数
任务创建函数OSTaskCreate各参数介绍如下:
void OSTaskCreate(OS_TCB *p_tcb, //任务控制块
CPU_CHAR *p_name, //任务名字,字符串形式
OS_TASK_PTR p_task, //任务入口函数
void *p_arg, //任务入口函数形参,不用的时候配置为 0 或者 NULL
OS_PRIO prio, //任务的优先级
CPU_STK *p_stk_base,//指向任务堆栈的基地址
CPU_STK_SIZE stk_limit, //设置堆栈深度的限制位置,一般设置为堆栈大小的1/10
CPU_STK_SIZE stk_size, //任务堆栈大小
OS_MSG_QTY q_size, //可以发送到任务的最大消息数
OS_TICK time_quanta,//在任务之间循环时的时间片的时间量
void *p_ext, //是指向用户提供的内存位置的指针,用作 TCB 扩展
OS_OPT opt, //用户可选的任务特定选项,在os.h中搜索“TASK OPTIONS”
OS_ERR *p_err); //用于保存返回的错误代码
创建一个简单的任务,代码如下:
#include "main.h"
#define START_TASK_PRIO 3 //任务优先级
#define START_STK_SIZE 128 //任务堆栈大小
OS_TCB StartTaskTCB; //任务控制块
CPU_STK START_TASK_STK[START_STK_SIZE];//任务堆栈
void start_task(void *p_arg);//任务函数
void ucos_init(void)
{
OS_ERR err;
CPU_SR_ALLOC();//定义cpu_sr变量
OSInit(&err); //初始化 UCOSIII
OS_CRITICAL_ENTER(); //进入临界区
//创建开始任务
OSTaskCreate((OS_TCB* )&StartTaskTCB, //任务控制块
(CPU_CHAR* )"start task", //任务名字
(OS_TASK_PTR )start_task, //任务函数
(void* )0, //传递给任务函数的参数
(OS_PRIO )START_TASK_PRIO, //任务优先级
(CPU_STK* )&START_TASK_STK[0], //任务堆栈基地址
(CPU_STK_SIZE )START_STK_SIZE/10, //任务堆栈深度限位
(CPU_STK_SIZE )START_STK_SIZE, //任务堆栈大小
(OS_MSG_QTY )0, //任务内部消息队列能够接收
//的最大消息数目,为 0 时禁止
//接收消息
(OS_TICK )0, //当使能时间片轮转时的时间片长度,为 0 时为默认长度。
(void* )0, //用户补充的存储区
(OS_OPT ) OS_OPT_TASK_STK_CHK|OS_OPT_TASK_STK_CLR|\
OS_OPT_TASK_SAVE_FP,
(OS_ERR* )&err); //存放该函数错误时的返回值
OS_CRITICAL_EXIT(); //退出临界区
OSStart(&err); //开启 UCOSIII
}
//开始任务函数
void start_task(void *p_arg)
{
while(1)
{
}
}
二 任务状态切换图
三 任务就绪表
任务就绪表有两部分:优先级位映射表OSPrioTbl[]和就绪任务列表 OSRdyList[]。
优先级表OSPrioTbl:实际就是一个数组,其中OSPrioTbl[0]的bit31为最高优先级,即优先级为0,下面举例说明:
OSPrioTbl[0] = 0xE000001 表示优先级为4,5,6的任务正在等待执行,
当优先级为4的任务执行完毕后,OSPrioTbl[0] = 0x6000001 .
就绪列表OSRdyList:在代码的层面上看就是一个 OS_RDY_LIST 数据类型的数组 OSRdyList[],数组的大小由
宏 OS_CFG_PRIO_MAX 决定任务的优先级与 OSRdyList[]的索引一一对应,比如优先级 3 的任务的 TCB会被放到 OSRdyList[3]中。
四 时间片轮转调度任务
要实现时间片轮转调度需要满足以下条件
- os_cfg.h中的OS_CFG_SCHED_ROUND_ROBIN_EN宏是否设置为1
- 在新建任务的时候,为任务设置time_quanta,该值表示该任务最多执行的时间段
- 调用 OSSchedRoundRobinCfg()函数来使能 UCOSIII的时间片功能
- 需要两个同等优先级的任务
在程序设计的时候,我们设置的任务时间一般会大于执行任务的实际时间,所以我们在任务执行完成后,使用函数OSSchedRoundRobinYield可以立即切换到下一个需要执行的任务。
五 统计任务OS_StatTask
统计任务可用来统计 CPU 的使用率、各个任务的 CPU 使用率和各任务的堆栈使用情况,使用统计任务需要满足以下条件:
- os_cfg.h中的OS_CFG_STAT_TASK_EN宏是否设置为1
- 调用OSStatTaskCPUUsageInit()函数,需要统计的任务在该函数调用后进行创建。
- CPU 的使用率用一个0~10000 之间的整数表示,其中OSStatTaskCPUUsageMax报存了CPU历史最大使用率,OSStatTaskCPUUsage保存了当前CPU使用率,OS_TCB中的CPUUsage成员保存了单个任务的CPU使用率。
- 将宏 OS_CFG_STAT_TASK_STK_CHK_EN 置 1 ,检查任务堆栈使用情况将检测结果
写入到每个任务的 OS_TCB 中的 StkFree 和 StkUsed 中
六 任务相关的其他函数介绍
修改任务优先级 | OSTaskChangePrio | |
删除任务 | OSTaskDel | OS_CFG_TASK_DEL_EN |
挂起任务 | OS_TaskSuspend | OS_CFG_TASK_SUSPEND_EN |
将挂起任务恢复 | OSTaskResume | OS_CFG_TASK_SUSPEND_EN |
设置某个任务的寄存器 | OSTaskRegSet | OS_CFG_TASK_REG_TBL_SIZE |
获取某个任务的寄存器 | OSTaskRegGet | OS_CFG_TASK_REG_TBL_SIZE |
获取任务堆栈使用情况 | OSTaskStkChk | OS_CFG_TASK_STAT_CHK_EN |
设置任务时间片 | OSTaskTimeQuantaSet | OS_CFG_SCHED_ROUND_ROBIN_EN |