快速回顾
在之前的文章中讲解了μC/OSⅡ的多任务模型以及初始化的源码:
本文继续探究任务生命周期的其它函数源码。
任务的挂起
任务挂起是一个动作,通过主动使用函数OSTaskSuspend(prio)可以使对应优先级的任务处于挂起状态,暂时无法被调度器调度:
//os_task.c
INT8U OSTaskSuspend (INT8U prio)
{
BOOLEAN self;
OS_TCB *ptcb;
INT8U y;
#if OS_CRITICAL_METHOD == 3u /* 初始化临界区变量 */
OS_CPU_SR cpu_sr = 0u;
#endif
#if OS_ARG_CHK_EN > 0u
if (prio == OS_TASK_IDLE_PRIO) { /* 不允许挂起空闲任务 */
return (OS_ERR_TASK_SUSPEND_IDLE);
}
if (prio >= OS_LOWEST_PRIO) { /* 要挂起的优先级不允许超出设定的最低优先级 */
if (prio != OS_PRIO_SELF) {
return (OS_ERR_PRIO_INVALID);
}
}
#endif
OS_ENTER_CRITICAL(); //进入临界区,关闭其它中断,只保留NMI和Hardfault中断
if (prio == OS_PRIO_SELF) { /* 检查是否要挂起自己 */
prio = OSTCBCur->OSTCBPrio;
self = OS_TRUE;
} else if (prio == OSTCBCur->OSTCBPrio) { /* 是否等于当前运行任务的优先级,和上面的判断是一样的 */
self = OS_TRUE;
} else {
self = OS_FALSE; /* self为TRUE表示要挂起自己,否则为挂起其它任务 */
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) { /* 任务不能是空,必须存在 */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_SUSPEND_PRIO);
}
if (ptcb == OS_TCB_RESERVED) { /* 任务控制块不能是OS_TCB_RESERVED状态 */
OS_EXIT_CRITICAL();
return (OS_ERR_TASK_NOT_EXIST);
}
y = ptcb->OSTCBY; //获取要挂起任务的优先级组下标
OSRdyTbl[y] &= (OS_PRIO)~ptcb->OSTCBBitX; /* 将任务的组内优先级就绪状态清空 */
if (OSRdyTbl[y] == 0u) { //如果挂起该任务后,整个组内没有就绪任务,则将该组的就绪状态清空
OSRdyGrp &= (OS_PRIO)~ptcb->OSTCBBitY;
}
ptcb->OSTCBStat |= OS_STAT_SUSPEND; /* 将任务状态切换为挂起状态 */
OS_EXIT_CRITICAL();
if (self == OS_TRUE) { /* 如果要挂起的任务就是自身,则进行上下文切换(停止运行当前任务) */
OS_Sched(); /* 切换任务 */
}
return (OS_ERR_NONE);
}
可以看到,挂起任务并不会将任务控制块丢弃或清空,只是将任务状态转换为SUSPEND而已,在这之后,任务将不会永远不会被加入到就绪队列中(除非被恢复)。
这里面有一些宏定义要额外提一下:
- 任务的状态,注意这些状态是可以按位进行组合的,即一个任务可能同时存在多种状态。
//ucos_ii.h
#define OS_STAT_RDY 0x00u /* 就绪 */
#define OS_STAT_SEM 0x01u /* 等待信号量 */
#define OS_STAT_MBOX 0x02u /* 等待邮箱 */
#define OS_STAT_Q 0x04u /* 等待消息队列 */
#define OS_STAT_SUSPEND 0x08u /* 已被悬起 */
#define OS_STAT_MUTEX 0x10u /* 等待互斥锁 */
#define OS_STAT_FLAG 0x20u /* 等待事件标志组 */
#define OS_STA
μC/OSⅡ任务生命周期函数源码探究

最低0.47元/天 解锁文章
1823

被折叠的 条评论
为什么被折叠?



