转自:https://blog.csdn.net/u010650845/article/details/71638084
/*
** ver: 2.52
** file: os_task.c
** brief: 任务相关操作 C 文件
*/
#ifndef OS_MASTER_FILE
#include "includes.h" /* 包含头文件 */
#endif
/*
***************************************************************************
* 改变任务优先级
*
* brief : 该函数用来改变任务优先级
*
* oldprio : 旧的任务优先级
*
* newprio : 新的任务优先级
*
* Returns : OS_NO_ERR 优先级修改成功
* OS_PRIO_INVALID 无效优先级
* OS_PRIO_EXIST 优先级已经存在
* OS_PRIO_ERR 不存在优先级对应的任务
****************************************************************************
*/
#if OS_TASK_CHANGE_PRIO_EN > 0
INT8U OSTaskChangePrio (INT8U oldprio, INT8U newprio)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
#if OS_EVENT_EN > 0
OS_EVENT *pevent;
#endif
OS_TCB *ptcb;
INT8U x;
INT8U y;
INT8U bitx;
INT8U bity;
#if OS_ARG_CHK_EN > 0 /* 参数检查 */
if ((oldprio >= OS_LOWEST_PRIO && oldprio != OS_PRIO_SELF) ||
newprio >= OS_LOWEST_PRIO) { /* 优先级检查 */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) {
OS_EXIT_CRITICAL(); /* 已经存在 newprio 优先级的任务 */
return (OS_PRIO_EXIST);
} else {
OSTCBPrioTbl[newprio] = (OS_TCB *)1;/* 占用 OSTCBPrioTbl[newprio] */
OS_EXIT_CRITICAL();
y = newprio >> 3; /* 预运算 */
bity = OSMapTbl[y];
x = newprio & 0x07;
bitx = OSMapTbl[x];
OS_ENTER_CRITICAL();
if (oldprio == OS_PRIO_SELF) { /* 是否改变自身优先级 */
oldprio = OSTCBCur->OSTCBPrio; /* 改变自身优先级 */
}
ptcb = OSTCBPrioTbl[oldprio];
if (ptcb != (OS_TCB *)0) { /* 任务存在 */
OSTCBPrioTbl[oldprio] = (OS_TCB *)0;/* 移除 TCB */
if ((OSRdyTbl[ptcb->OSTCBY] & ptcb->OSTCBBitX) != 0x00) {
/* 如果任务是就绪,则清除 */
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) {
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
OSRdyGrp |= bity; /* 使优先级任务进入就绪 */
OSRdyTbl[y] |= bitx;
#if OS_EVENT_EN > 0
} else {
pevent = ptcb->OSTCBEventPtr;
if (pevent != (OS_EVENT *)0) {/* 任务正在等待事件发生 */
/* 清除等待任务 */
if ((pevent->OSEventTbl[ptcb->OSTCBY]
&= ~ptcb->OSTCBBitX) == 0) {
pevent->OSEventGrp &= ~ptcb->OSTCBBitY;
}
pevent->OSEventGrp |= bity;/* 使新优先级任务等待 */
pevent->OSEventTbl[y] |= bitx;
}
#endif
}
OSTCBPrioTbl[newprio] = ptcb; /* 把任务控制块给新优先级任务 */
ptcb->OSTCBPrio = newprio; /* 初始化任务控制块 */
ptcb->OSTCBY = y;
ptcb->OSTCBX = x;
ptcb->OSTCBBitY = bity;
ptcb->OSTCBBitX = bitx;
OS_EXIT_CRITICAL();
OS_Sched(); /* 任务调度 */
return (OS_NO_ERR);
} else { /* 任务不存在 */
OSTCBPrioTbl[newprio] = (OS_TCB *)0;/* 释放 OSTCBPrioTbl[newprio] */
OS_EXIT_CRITICAL();
return (OS_PRIO_ERR);
}
}
}
#endif
/*$PAGE*/
/*
****************************************************************************
* 创建一个任务
*
* brief : 创建任务,不能在 ISR 中调用
*
* task : 指向任务函数的指针
*
* pdata : 传递给任务的参数
*
* ptos : 堆栈栈顶指针
*
* prio : 任务优先级
*
* returns : OS_NO_ERR 创建任务成功
* OS_PRIO_EXIT 任务已经存在
* OS_PRIO_INVALID 无效优先级
*****************************************************************************
*/
#if OS_TASK_CREATE_EN > 0
INT8U OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
OS_STK *psp;
INT8U err;
#if OS_ARG_CHK_EN > 0
if (prio > OS_LOWEST_PRIO) { /* 检查优先级有效性 */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* 检查优先级唯一性 */
OSTCBPrioTbl[prio] = (OS_TCB *)1; /* 占用 OSTCBPrioTbl[prio] */
OS_EXIT_CRITICAL();
/* 初始化任务堆栈 */
psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0);
/* 初始化任务控制块 */
err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0);
if (err == OS_NO_ERR) {
OS_ENTER_CRITICAL();
OSTaskCtr++; /* 任务数加 1 */
OS_EXIT_CRITICAL();
if (OSRunning == TRUE) { /* 任务调度 */
OS_Sched();
}
} else {
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = (OS_TCB *)0;/* 释放 OSTCBPrioTbl[prio] */
OS_EXIT_CRITICAL();
}
return (err);
}
OS_EXIT_CRITICAL();
return (OS_PRIO_EXIST);
}
#endif
/*$PAGE*/
/*
*********************************************************************************
* 创建一个任务
*
* brief : 创建任务,类似于函数 OSTaskCreate(),对其进行了扩展
*
* task : 指向任务函数的指针
*
* pdata : 传递给任务的参数
*
* ptos : 堆栈栈顶指针
*
* prio : 任务优先级
*
* id : 任务 ID
*
* pbos : 堆栈栈底指针
*
* stk_size : 对栈大小
*
* pext : TCB 扩展数据结构指针
*
* opt : 选择项.
* OS_TASK_OPT_STK_CHK 堆栈检查
* OS_TASK_OPT_STK_CLR 堆栈清 0
* OS_TASK_OPT_SAVE_FP 保存浮点寄存器
*
*
* returns : OS_NO_ERR 创建任务成功
* OS_PRIO_EXIT 任务已经存在
* OS_PRIO_INVALID 无效优先级
********************************************************************************
*/
/*$PAGE*/
#if OS_TASK_CREATE_EXT_EN > 0
INT8U OSTaskCreateExt (void (*task)(void *pd),
void *pdata,
OS_STK *ptos,
INT8U prio,
INT16U id,
OS_STK *pbos,
INT32U stk_size,
void *pext,
INT16U opt)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
OS_STK *psp;
INT8U err;
#if OS_ARG_CHK_EN > 0
if (prio > OS_LOWEST_PRIO) { /* 检查优先级有效性 */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
if (OSTCBPrioTbl[prio] == (OS_TCB *)0) { /* 检查优先级唯一性 */
OSTCBPrioTbl[prio] = (OS_TCB *)1; /* 占用 OSTCBPrioTbl[prio] */
OS_EXIT_CRITICAL();
if (((opt & OS_TASK_OPT_STK_CHK) != 0x0000) || /* 堆栈检查 */
((opt & OS_TASK_OPT_STK_CLR) != 0x0000)) { /* 堆栈清 0 */
#if OS_STK_GROWTH == 1
(void)memset(pbos, 0, stk_size * sizeof(OS_STK));
#else
(void)memset(ptos, 0, stk_size * sizeof(OS_STK));
#endif
}
/* 堆栈初始化 */
psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, opt);
/* 任务控制块初始化 */
err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt);
if (err == OS_NO_ERR) {
OS_ENTER_CRITICAL();
OSTaskCtr++; /* 任务数加 1 */
OS_EXIT_CRITICAL();
if (OSRunning == TRUE) { /* 任务调度 */
OS_Sched();
}
} else {
OS_ENTER_CRITICAL();
OSTCBPrioTbl[prio] = (OS_TCB *)0; /* 释放 占用 OSTCBPrioTbl[prio] */
OS_EXIT_CRITICAL();
}
return (err);
}
OS_EXIT_CRITICAL();
return (OS_PRIO_EXIST);
}
#endif
/*$PAGE*/
/*
**********************************************************************************
* 删除一个任务
*
* bried: 删除任务,通过重新创建可以再次激活任务
*
* prio : 任务优先级
*
* returns : OS_NO_ERR 成功
* OS_TASK_DEL_IDLE 不允许删除空闲任务
* OS_PRIO_INVALID 无效优先级
* OS_TASK_DEL_ERR 任务不存在
* OS_TASK_DEL_ISR 不能中断中删除任务
*
**********************************************************************************
*/
/*$PAGE*/
#if OS_TASK_DEL_EN > 0
INT8U OSTaskDel (INT8U prio)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
#if OS_EVENT_EN > 0
OS_EVENT *pevent;
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
OS_FLAG_NODE *pnode;
#endif
OS_TCB *ptcb;
BOOLEAN self;
if (OSIntNesting > 0) { /* 不能在中断中删除任务 */
return (OS_TASK_DEL_ISR);
}
#if OS_ARG_CHK_EN > 0
if (prio == OS_IDLE_PRIO) { /* 不允许删除空闲任务 */
return (OS_TASK_DEL_IDLE);
}
if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {/* 检查优先级有效性 */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) { /* 删除自己 */
prio = OSTCBCur->OSTCBPrio; /* 获取优先级 */
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb != (OS_TCB *)0) { /* 任务必须存在 */
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) { /* 取消任务就绪 */
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
#if OS_EVENT_EN > 0
pevent = ptcb->OSTCBEventPtr;
if (pevent != (OS_EVENT *)0) {/* 任务正在等待事件 */
if ((pevent->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) {
pevent->OSEventGrp &= ~ptcb->OSTCBBitY;/* 取消等待事件 */
}
}
#endif
#if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
pnode = ptcb->OSTCBFlagNode;
if (pnode != (OS_FLAG_NODE *)0) {/* 任务等待时间标志组 */
OS_FlagUnlink(pnode); /* 取消等待时间标志组 */
}
#endif
ptcb->OSTCBDly = 0; /* 防止开中断后 OSTimeTick()又将任务就绪 */
ptcb->OSTCBStat = OS_STAT_RDY; /* 防止其他任务ISR调用 OSTaskResume()使任务运行 */
if (OSLockNesting < 255) { /* 禁止任务调度 */
OSLockNesting++;
}
OS_EXIT_CRITICAL(); /* 开中断,以缩短中断响应 */
OS_Dummy(); /* 确保中断被打开过 */
OS_ENTER_CRITICAL(); /* 关中断 */
if (OSLockNesting > 0) { /* 运行任务调度 */
OSLockNesting--;
}
OSTaskDelHook(ptcb); /* 调用用户自定义钩子函数 */
OSTaskCtr--; /* 任务数减 1 */
OSTCBPrioTbl[prio] = (OS_TCB *)0;/* 从优先级表中去除 任务控制块 */
if (ptcb->OSTCBPrev == (OS_TCB *)0) { /* 移除待删除任务的任务控制块 */
ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;
OSTCBList = ptcb->OSTCBNext;
} else {
ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext;
ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev;
}
ptcb->OSTCBNext = OSTCBFreeList; /* 任务控制块还给空链表 */
OSTCBFreeList = ptcb;
OS_EXIT_CRITICAL();
OS_Sched(); /* 任务调度 */
return (OS_NO_ERR);
}
OS_EXIT_CRITICAL();
return (OS_TASK_DEL_ERR);
}
#endif
/*$PAGE*/
/*
**************************************************************************************
* 请求删除任务
*
* brief : 这个函数被用来 :
* a) 任务A 通知任务B 删除任务B 就是老子不会杀你,你自杀的意思
* b) 任务B 查看是否有其他任务删除自己,注意 我要自杀了
* 是不是有点小懵逼. 简单的说就是, 你想删除一个任务
* 然而,这个任务占用一些资源 (内存缓冲区,信号量, 邮
* 箱, 队列 等等). 因此这个任务不能被删除,否则会导致
* 存储器漏洞,这就需要使用 OSTaskDelReq() 去通知到被
* 删除的任务,让其释放资源后删除自己,例如, 任务 #10
* 需要被删除. 任务#5将调用OSTaskDelReq(10),任务#10
* 调用OSTaskDelReq(OS_PRIO_SELF)查询是否有其他任务要
* 删除自己,如果返回 OS_TASK_DEL_REQ, 则任务 #10 完
* 成删除自己的动作
*
* void Task_#10(void *data)
* {
* .
* .
* while (1) {
* OSTimeDly(1);
* if (OSTaskDelReq(OS_PRIO_SELF) == OS_TASK_DEL_REQ) {
* 释放资源;
* 释放内存;
* OSTaskDel(OS_PRIO_SELF);
* }
* }
* }
*
* prio : 优先级
*
* Returns : OS_NO_ERR 成功
* OS_TASK_NOT_EXIST 任务不存在
* OS_TASK_DEL_IDLE 不允许删除空闲任务
* OS_PRIO_INVALID 优先级无效
* OS_TASK_DEL_REQ 发出任务删除请求
*************************************************************************************
/*$PAGE*/
#if OS_TASK_DEL_EN > 0
INT8U OSTaskDelReq (INT8U prio)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
BOOLEAN stat;
INT8U err;
OS_TCB *ptcb;
#if OS_ARG_CHK_EN > 0
if (prio == OS_IDLE_PRIO) { /* 不允许删除空闲任务 */
return (OS_TASK_DEL_IDLE);
}
if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {/* 检查任务优先级优先级 */
return (OS_PRIO_INVALID);
}
#endif
if (prio == OS_PRIO_SELF) { /* 删除自己 */
OS_ENTER_CRITICAL();
stat = OSTCBCur->OSTCBDelReq; /* 返回是否需要删除自己 */
OS_EXIT_CRITICAL();
return (stat);
}
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio]; /* 获取任务控制块 */
if (ptcb != (OS_TCB *)0) { /* 任务必须存存在 */
ptcb->OSTCBDelReq = OS_TASK_DEL_REQ; /* 设置删除任务请求 */
err = OS_NO_ERR;
} else {
err = OS_TASK_NOT_EXIST; /* 任务不存在 */
}
OS_EXIT_CRITICAL();
return (err);
}
#endif
/*$PAGE*/
/*
***********************************************************************************
* 恢复挂起的任务
*
* brief : 恢复被挂起的任务
*
* prio : 任务优先级
*
* returns : OS_NO_ERR 成功
* OS_PRIO_INVALID 无效优先级
* OS_TASK_RESUME_PRIO 任务不存在
* OS_TASK_NOT_SUSPENDED 任务没有被挂起
***********************************************************************************
*/
#if OS_TASK_SUSPEND_EN > 0
INT8U OSTaskResume (INT8U prio)
{
#if OS_CRITICAL_METHOD == 3
OS_CPU_SR cpu_sr;
#endif
OS_TCB *ptcb;
#if OS_ARG_CHK_EN > 0
if (prio >= OS_LOWEST_PRIO) { /* 检查优先级的有效性 */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) { /* 检查任务是否存在 */
OS_EXIT_CRITICAL();
return (OS_TASK_RESUME_PRIO);
}
if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != OS_STAT_RDY) {/* 任务被挂起 */
if (((ptcb->OSTCBStat &= ~OS_STAT_SUSPEND) == OS_STAT_RDY) && /* 取消挂起状态 */
(ptcb->OSTCBDly == 0)) { /* 不能有延时 */
OSRdyGrp |= ptcb->OSTCBBitY; /* 使任务就绪 */
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*/
/*
**********************************************************************************
* 堆栈检测
*
* brief : 该函数用于检测任务的堆栈使用情况
*
* prio : 任务优先级
*
* pdata : 保存堆栈使用情况的数据结构指针
*
* returns : OS_NO_ERR 成功
* OS_PRIO_INVALID 无效优先级
* OS_TASK_NOT_EXIST 任务不存在
* OS_TASK_OPT_ERR 选项错误
***********************************************************************************
*/
#if OS_TASK_CREATE_EXT_EN > 0
INT8U OSTaskStkChk (INT8U prio, OS_STK_DATA *pdata)
{
#if OS_CRITICAL_METHOD == 3
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) { /* 检查优先级有效性 */
return (OS_PRIO_INVALID);
}
#endif
pdata->OSFree = 0; /* 初始化局部变量 */
pdata->OSUsed = 0;
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) { /* 是否检测自身堆栈 */
prio = OSTCBCur->OSTCBPrio;
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) { /* 任务不存在 */
OS_EXIT_CRITICAL();
return (OS_TASK_NOT_EXIST);
}
if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0) { /* 检查 OPT 的有效性 */
OS_EXIT_CRITICAL();
return (OS_TASK_OPT_ERR);
}
free = 0;
size = ptcb->OSTCBStkSize;
pchk = ptcb->OSTCBStkBottom;
OS_EXIT_CRITICAL();
#if OS_STK_GROWTH == 1
while (*pchk++ == (OS_STK)0) { /* 计算堆栈中 0 的数量 */
free++;
}
#else
while (*pchk-- == (OS_STK)0) {
free++;
}
#endif
pdata->OSFree = free * sizeof(OS_STK); /* 计算剩余字节数 */
pdata->OSUsed = (size - free) * sizeof(OS_STK); /* 计算已使用字节数 */
return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
***********************************************************************************
* 挂起任务
*
* breif: 该函数用于挂起一个任务,可以使其他任务或者自身
*
* prio : 待挂起任务优先级. 如果等于 OS_PRIO_SELF,则挂起自身并进行任务调度
*
* returns : 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
OS_CPU_SR cpu_sr;
#endif
BOOLEAN self;
OS_TCB *ptcb;
#if OS_ARG_CHK_EN > 0
if (prio == OS_IDLE_PRIO) { /* 不允许挂起空闲任务 */
return (OS_TASK_SUSPEND_IDLE);
}
if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) { /* 检查优先级有效性 */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) { /* 挂起自身 */
prio = OSTCBCur->OSTCBPrio;
self = TRUE;
} else if (prio == OSTCBCur->OSTCBPrio) { /* 挂起自身 */
self = TRUE;
} else {
self = FALSE; /* 非自身挂起 */
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) { /* 待挂起任务不存在 */
OS_EXIT_CRITICAL();
return (OS_TASK_SUSPEND_PRIO);
}
if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) { /* 清除就绪表相应位 */
OSRdyGrp &= ~ptcb->OSTCBBitY;
}
ptcb->OSTCBStat |= OS_STAT_SUSPEND; /* 状态设置为挂起态 */
OS_EXIT_CRITICAL();
if (self == TRUE) { /* 任务调度 */
OS_Sched();
}
return (OS_NO_ERR);
}
#endif
/*$PAGE*/
/*
************************************************************************************
* 查询任务
*
* brief: 查询一个任务的状态
*
* prio : 待查询任务优先级
*
* Returns : 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
OS_CPU_SR cpu_sr;
#endif
OS_TCB *ptcb;
#if OS_ARG_CHK_EN > 0
if (prio > OS_LOWEST_PRIO && prio != OS_PRIO_SELF) { /* 检查优先级有效性 */
return (OS_PRIO_INVALID);
}
#endif
OS_ENTER_CRITICAL();
if (prio == OS_PRIO_SELF) { /* 是否查询自身 */
prio = OSTCBCur->OSTCBPrio;
}
ptcb = OSTCBPrioTbl[prio];
if (ptcb == (OS_TCB *)0) { /* 任务不存在 */
OS_EXIT_CRITICAL();
return (OS_PRIO_ERR);
}
memcpy(pdata, ptcb, sizeof(OS_TCB)); /* 复制 TCB 内容 */
OS_EXIT_CRITICAL();
return (OS_NO_ERR);
}
#endif