📄 os_task.c
字号:
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY) { /* Task must be suspended */
//任务必须存在且被挂起
if (((ptcb->OSTCBStat &= ~OS_STAT_SUSPEND) == OS_STAT_RDY) && /* Remove suspension */
//是通过清除OSTCBStat域中的OS_STAT_SUSPEND位而取消挂起的
(ptcb->OSTCBDly == 0)) { /* Must not be delayed */
//要使任务处于就绪态,OSTCBDly须为0。因为没有任何标志表明任务
//正在等待延迟时间到
OSRdyGrp |= ptcb->OSTCBBitY; /* Make task ready to run */
OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;//当以上两个条件满足时,任务才处于就绪状态
OS_EXIT_CRITICAL();
OS_Sched();//任务调度会检查被恢复的任务拥有的优先级是否比调用本函数的任务
//优先级高。
} else {
OS_EXIT_CRITICAL();
}
return (OS_NO_ERR);//恢复成功
}
OS_EXIT_CRITICAL();
return (OS_TASK_NOT_SUSPENDED);//如果任务没有被挂起
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* STACK CHECKING
*
* Description: This function is called to check the amount of free memory left on the specified task's
* stack.
*
* Arguments : prio is the task priority
*
* pdata is a pointer to a data structure of type OS_STK_DATA.
*
* Returns : OS_NO_ERR upon success
* OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
* OS_TASK_NOT_EXIST if the desired task has not been created
* OS_TASK_OPT_ERR if you did NOT specified OS_TASK_OPT_STK_CHK when the task was created
*********************************************************************************************************
*/
/*
*********************************************************************************************************
堆栈检验
描述:这个函数用于检验指定任务堆栈的剩余存储空间数量
参数:prio:任务优先级
pdata:OS_STK_DATA结构类型的数据指针。
返回:OS_NO_ERR :成功。
OS_PRIO_INVALID:优先级数值大于最大值或者没有指定OS_PRIO_SELF
OS_TASK_NOT_EXIST:如果指定任务没有被创建
OS_TASK_OPT_ERR:如果任务创建时没有指定OS_TASK_OPT_STK_CHK
*********************************************************************************************************
*/
#if OS_TASK_CREATE_EXT_EN > 0
INT8U OSTaskStkChk (INT8U prio, OS_STK_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_TCB *ptcb;
OS_STK *pchk;
INT32U free;
INT32U size;
#if OS_ARG_CHK_EN > 0
if (prio > OS_LOWEST_PRIO && prio != OS_PRIO_SELF) { /* Make sure task priority is valid */
return (OS_PRIO_INVALID);//如果OS_ARG_CHK_EN设置为1,优先级值大于最大值且不是 OS_PRIO_SELF
}
#endif
pdata->OSFree = 0; /* Assume failure, set to 0 size */
pdata->OSUsed = 0;//初始化为0
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) { /* See if check for SELF */
prio = OSTCBCur->OSTCBPrio;//如果想知道当前任务堆栈信息
}
ptcb = OSTCBPrioTbl[prio];//提取优先级,如果非零,代表任务存在
if (ptcb == (OS_TCB *)0) { /* Make sure task exist */
OS_EXIT_CRITICAL();
return (OS_TASK_NOT_EXIST);//任务不存在
}
if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0) { /* Make sure stack checking option is set */
//要保证允许检验,要保证已经创建了任务,并传递了参数OS_TASK_OPT_STK_CHK
//如果建立任务的是OSTaskCreate(),而不是OSTaskCreateExt(),那么因为参数opt为零,
//所以检验失败。
OS_EXIT_CRITICAL();
return (OS_TASK_OPT_ERR);
}
free = 0;
size = ptcb->OSTCBStkSize;//如果所有条件满足,OSTaskStkChk就会像前面描述那样,从堆栈栈底
//开始统计堆栈的空闲空间,直到发现一个储存值非零的堆栈入口。
pchk = ptcb->OSTCBStkBottom;
OS_EXIT_CRITICAL();
#if OS_STK_GROWTH == 1//如果堆栈设置成从高到低增长
while (*pchk++ == (OS_STK)0) { /* Compute the number of zero entries on the stk */
free++;//计算空块
}
#else//如果从低到高增长
while (*pchk-- == (OS_STK)0) {
free++;
}
#endif
pdata->OSFree = free * sizeof(OS_STK); /* Compute number of free bytes on the stack */
//计算空堆栈字节
pdata->OSUsed = (size - free) * sizeof(OS_STK); /* Compute number of bytes used on the stack */
//计算已用堆栈字节
return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* SUSPEND A TASK
*
* Description: This function is called to suspend a task. The task can be the calling task if the
* priority passed to OSTaskSuspend() is the priority of the calling task or OS_PRIO_SELF.
*
* Arguments : prio is the priority of the task to suspend. If you specify OS_PRIO_SELF, the
* calling task will suspend itself and rescheduling will occur.
*
* Returns : OS_NO_ERR if the requested task is suspended
* OS_TASK_SUSPEND_IDLE if you attempted to suspend the idle task which is not allowed.
* OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. >= OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
* OS_TASK_SUSPEND_PRIO if the task to suspend does not exist
*
* Note : You should use this function with great care. If you suspend a task that is waiting for
* an event (i.e. a message, a semaphore, a queue ...) you will prevent this task from
* running when the event arrives.
*********************************************************************************************************
*/
/*
*********************************************************************************************************
挂起一个任务
描述:调用此函数去挂起一个任务,如果传送到OSTaskSuspend()的任务的优先级是要挂起的任务或者是
OS_PRIO_SELF,那么这个任务将被挂起。
参数: prio:需要挂起任务的优先级。如果指定OS_PRIO_SELF,那么这个任务将自己挂起,再发生再
次调度。
返回:OS_NO_ERR:如果请求的任务被挂起。
OS_TASK_SUSPEND_IDLE:如果想挂起空闲任务
OS_PRIO_INVALID :想挂起任务优先级不合理
OS_TASK_SUSPEND_PRIO:需要挂起的任务不存在。
备注:调用时要十分小心,如果你想挂起一个等待事件(邮箱,消息,队列)的任务,事件到来的时候
你将阻止这个任务运行。
*********************************************************************************************************
*/
#if OS_TASK_SUSPEND_EN > 0
INT8U OSTaskSuspend (INT8U prio)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
BOOLEAN self;
OS_TCB *ptcb;
#if OS_ARG_CHK_EN > 0
if (prio == OS_IDLE_PRIO) { /* Not allowed to suspend idle task */
return (OS_TASK_SUSPEND_IDLE);//不能挂起空闲任务
}
if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) { /* Task priority valid ? */
return (OS_PRIO_INVALID);//任务优先级不合理
}
#endif
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) { /* See if suspend SELF */
//是不是要挂起自己,这样,OSTaskSuspend 会从当前任务的任务控制块中
//获得当前任务的优先级
prio = OSTCBCur->OSTCBPrio;
self = TRUE;
} else if (prio == OSTCBCur->OSTCBPrio) { /* See if suspending self */
self = TRUE;//也可以通过指定优先级,挂起调用本函数的任务。这两种情况下,
//任务调度都被调用,这是为什么要定义局部变量self的原因,该变量在
//适当的时候会被测试,如果没有挂起调用本函数的任务,OSTaskSus_pend()
//就没有必要运行任务调度程序,因为调用该函数的任务正在挂起一个
//优先级比较低的任务
} else {
self = FALSE; /* No suspending another task */
//不是要挂起自己
}
ptcb = OSTCBPrioTbl[prio];//取需要挂起任务的TCB
if (ptcb == (OS_TCB *)0) { /* Task to suspend must exist */
OS_EXIT_CRITICAL();
return (OS_TASK_SUSPEND_PRIO);//如果要挂起的任务不存在
}
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) { /* Make task not ready */
OSRdyGrp &= ~ptcb->OSTCBBitY;//如果该任务存在,就会从就绪表中去掉。
//要挂起的任务可能不在就绪表中,有可能在等待事件发生或者延迟。要
//挂起的任务在OSRdyTbl[]中对应位已被清除。再次清除该位,比先检验该位是否被
//清除,如果没有清除再清除快得多,所以就没有检验了。
}
ptcb->OSTCBStat |= OS_STAT_SUSPEND; /* Status of task is 'SUSPENDED' */
//终于挂起来了
OS_EXIT_CRITICAL();
if (self == TRUE) { /* Context switch only if SELF */
OS_Sched();//仅仅在挂起任务自己的情况下才调用任务调度
}
return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
*********************************************************************************************************
* QUERY A TASK
*
* Description: This function is called to obtain a copy of the desired task's TCB.
*
* Arguments : prio is the priority of the task to obtain information from.
*
* Returns : OS_NO_ERR if the requested task is suspended
* OS_PRIO_INVALID if the priority you specify is higher that the maximum allowed
* (i.e. > OS_LOWEST_PRIO) or, you have not specified OS_PRIO_SELF.
* OS_PRIO_ERR if the desired task has not been created
*********************************************************************************************************
*/
/*
*********************************************************************************************************
查询一个任务
描述:此函数调用去获得一个指定任务TCB的副本
参数:prio:指定函数的优先级
返回: OS_NO_ERR:请求的函数被挂起
OS_PRIO_INVALID:任务优先级不合法
OS_PRIO_ERR如果指定的函数还没有创建
*********************************************************************************************************
*/
#if OS_TASK_QUERY_EN > 0
INT8U OSTaskQuery (INT8U prio, OS_TCB *pdata)
{
#if OS_CRITICAL_METHOD == 3 /* Allocate storage for CPU status register */
OS_CPU_SR cpu_sr;
#endif
OS_TCB *ptcb;
#if OS_ARG_CHK_EN > 0
if (prio > OS_LOWEST_PRIO && prio != OS_PRIO_SELF) { /* Task priority valid ? */
return (OS_PRIO_INVALID);//优先级不合法
}
#endif
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) { /* See if suspend SELF */
prio = OSTCBCur->OSTCBPrio;//挂起自己
}
ptcb = OSTCBPrioTbl[prio];//不挂起自己
if (ptcb == (OS_TCB *)0) { /* Task to query must exist */
//任务不存在
OS_EXIT_CRITICAL();
return (OS_PRIO_ERR);//返回错误
}
memcpy(pdata, ptcb, sizeof(OS_TCB)); /* Copy TCB into user storage area */
//任务的TCB复制到用户的存储空间
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -