UCOSIII任务创建与删除
1.任务的创建OSTaskCreate()
void OSTaskCreate (OS_TCB *p_tcb, //任务控制块
CPU_CHAR *p_name, //任务命名
OS_TASK_PTR p_task, //指向任务函数
void *p_arg,
OS_PRIO prio, //任务优先级
CPU_STK *p_stk_base, //任务堆栈的基地址
CPU_STK_SIZE stk_limit, //警戒值,确保堆栈不溢出
CPU_STK_SIZE stk_size, //任务堆栈大小
OS_MSG_QTY q_size, //内检消息队列的长度
OS_TICK time_quanta, //指定时间片的轮转长度
void *p_ext, //指向用户补充的存储区
OS_OPT opt, //选项,共有四个,一般选第二个和第三个
OS_ERR *p_err) // 错误的查找
*p_tcb: 指向任务的任务控制块 OS_TCB。
*p_name: 指向任务的名字,我们可以给每个任务取一个名字
p_task: 执行任务代码,也就是任务函数名字
*p_arg: 传递给任务的参数
prio: 任务优先级,数值越低优先级越高,用户不能使用系统任务使用的那些优先级!
*p_stk_base:指向任务堆栈的基地址。
stk_limit: 任务堆栈的堆栈深度,用来检测和确保堆栈不溢出。
stk_size: 任务堆栈大小
q_size: UCOSIII 中每个任务都有一个可选的内部消息队列,我们要定义宏OS_CFG_TASK_Q_EN>0,这是才会使用这个内部消息队列。
time_quanta:在使能时间片轮转调度时用来设置任务的时间片长度,默认值为时钟节拍除以10。
*p_ext: 指向用户补充的存储区。
opt: 包含任务的特定选项,有如下选项可以设置。
OS_OPT_TASK_NONE 表示没有任何选项
OS_OPT_TASK_STK_CHK 指定是否允许检测该任务的堆栈
OS_OPT_TASK_STK_CLR 指定是否清除该任务的堆栈
OS_OPT_TASK_SAVE_FP 指定是否存储浮点寄存器,CPU 需要有浮点运算硬件并且有专用代码保存浮点寄存器。
*p_err: 用来保存调用该函数后返回的错误码。
2.任务删除函数OSTaskDel()
OSTaskDel()函数用来删除任务,当一个任务不需要运行的话,我们就可以将其删除掉,删
除任务不是说删除任务代码,而是 UCOSIII 不再管理这个任务,在有些应用中我们只需要某个
任务只运行一次,运行完成后就将其删除掉,比如外设初始化任务
void OSTaskDel (OS_TCB *p_tcb,
OS_ERR *p_err)
*p_tcb : 指向要删除的任务 TCB,也可以传递一个 NULL 指针来删除调用 OSTaskDel()函
数的任务自身。
*p_err: 指向一个变量用来保存调用 OSTaskDel()函数后返回的错误码
1.删除某个任务以后,它占用的OS_TCB和堆栈就可以再次利用来创建其他任务。
2.尽管UCOSIII允许在系统运行中删除任务,但是应该尽量避免这种操作,如果这个任务可能占有其他任务共享的资源,在删除此任务之前这个被占有的资源没有被释放就有可能导致奇怪的结果。
任务挂起和恢复实验
3.任务挂起函数OSTaskSuspend()
有时候有些任务因为某些原因需要暂停运行,但是以后还要运行,因此我们就不能删除掉任务,这里我们可以使用 OSTaskSuspend()函数挂起这个任务,以后再恢复运行。
函数OSTaskSuspend()的原型如下:
void OSTaskSuspend (OS_TCB *p_tcb,OS_ERR *p_err)
*p_tcb : 指向需要挂起的任务的 OS_TCB,可以通过指向一个 NULL 指针将调用该函
数的任务挂起。
*p_err : 指向一个变量,用来保存该函数的错误码。
我们可以多次调用 OSTaskSuspend ()函数来挂起一个任务,因此我们需要调用同样次数的OSTaskResume()函数才可以恢复被挂起的任务,这一点非常重要。
4.任务恢复函数OSTaskResume()
OSTaskResume()函数用来恢复被 OSTaskSuspend()函数挂起的任务,OSTaskResume()函数
是唯一能恢复被挂起任务的函数。如果被挂起的任务还在等待别的内核对象,比如事件标志组、
信号量、互斥信号量、消息队列等,即使使用 OSTaskResume()函数恢复了被挂起的任务,该任
务也不一定能立即运行,该任务还是要等相应的内核对象,只有等到内核对象后才可以继续运
行
OSTaskResume()函数原型如下:
void OSTaskResume (OS_TCB *p_tcb,OS_ERR *p_err)
*p_tcb : 指向需要解挂的任务的 OS_TCB,指向一个 NULL 指针是无效的,因为该任务正在运行,不需要解挂。
*p_err : 指向一个变量,用来保存该函数的错误码。
时间片轮转调度实验
5.OSSchedRoundRobinCfg()
OSSchedRoundRobinCfg()函数用来使能或失能 UCOSIII,如果我们要使用时间片轮转调度
功 能 的 话 不 仅 要 将 宏 OS_CFG_SCHED_ROUND_ROBIN_EN 定义 为 1, 还 需 要 调 用
OSSchedRoundRobinCfg()函数来使能 UCOSIII,OSSchedRoundRobinCfg()函数原型如下。
void OSSchedRoundRobinCfg ( CPU_BOOLEAN en,OS_TICK dflt_time_quanta,OS_ERR *p_err)
en : 用于设置打开或关闭时间片轮转调度机制,如果为 DEF_ENABLED 表示打开时间片轮转调度,为 DEF_DISABLED 表示关闭时间片轮转调度。
dflt_time_quanta : 设置默认的时间片长度,就是系统时钟节拍个数,比如我们设置系统时钟频率OSCfg_TickRate_Hz 为 200Hz,那么每个时钟节拍就是 5ms。当我们设置 dflt_time_quanta 为 n 时,时间片长度就是(5n)ms 长,如果我们设置 dflt_time_quanta 为 0 的话,UCOSIII 就会使用系统默认的时间片长度:OSCfg_TickRate_Hz / 10,比如如果 OSCfg_TickRate_Hz 为 200,那么时间片长度为:200/105=100ms。
*p_err : 保存调用此函数后返回的错误码
6 OSSchedRoundRobinYield()
当一个任务想放弃本次时间片,把 CPU 的使用权让给同优先级下的另外一个任务就可以使用 OSSchedRoundRobinYield()函数,函数原型如下:
void OSSchedRoundRobinYield (OS_ERR *p_err)
*p_err : 用来保存函数调用后返回的错误码。
OS_ERR_NONE 调用成功
OS_ERR_ROUND_ROBIN_1 当前优先级下没有其他就绪任务
OS_ERR_ROUND_ROBIN_DISABLED 未使能时间片轮转调度功能
OS_ERR_YIELD_ISR 在中断调用了本函数。
我们在调用这个后函数遇到最多的错误就是 OS_ERR_ROUND_ROBIN_1,也就是当前优
先级下没有就绪任务了。