OS_TASK.C

1 /*
2 *************************************************************************************************
3 *                                     uC/OS-II实时控制内核
4 *                                        主要的包含文件
5 *                                          任务管理
6 *
7 * 文 件: OS_TASK.C     任务管理代码
8 * 作 者: Jean J. Labrosse
9 * 中文注解: 钟常慰 zhongcw @ 126.com  整理:lin-credible 译注版本:1.0 请尊重原版内容
10 *************************************************************************************************
11 */
12
13 #ifndef  OS_MASTER_FILE                      //是否已经定义OS_MASTER_FILE
14 #include "includes.h"                        //包含"includes.h"文件
15 #endif                                       //结束定义
16
17 /*
18 *************************************************************************************************
19 *                        改变一个任务的优先级(CHANGE PRIORITY OF A TASK)
20 *
21 * 描述: 改变一个任务的优先级。
22 *
23 * 参数: oldp    是任务原先的优先级。
24 *
25 *       newp    是任务的新优先级。
26 *
27 * 返回: OS_NO_ERR        任务优先级成功改变。
28 *       OS_PRIO_INVALID  参数中的任务原先优先级或新优先级大于或等于OS_LOWEST_PRIO。
29 *          (i.e. >= OS_LOWEST_PRIO)
30 *       OS_PRIO_EXIST    优先级为PIP的任务已经存在;
31 *       OS_PRIO_ERR      参数中的任务原先优先级不存在。
32 *
33 * 注意: 参数中的新优先级必须是没有使用过的,否则会返回错误码.在OSTaskChangePrio()中还会先
34 *       判断要改变优先级的任务是否存在。
35 *
36 *************************************************************************************************
37 */
38
39 #if OS_TASK_CHANGE_PRIO_EN > 0             //允许生成OSTaskChangePrio()函数
40 INT8U  OSTaskChangePrio (INT8U oldprio, INT8U newprio)
41 {                                          //改变一个任务的优先级(任务旧的优先级、任务新的优先级)
42 #if OS_CRITICAL_METHOD == 3                //允许生成OSTaskCreate()函数
43     OS_CPU_SR    cpu_sr;
44 #endif
45
46 #if OS_EVENT_EN > 0                        //消息事件是否 > 0
47     OS_EVENT    *pevent;                   //定义事件指针
48 #endif
49
50     OS_TCB      *ptcb;                     //定义消息事件的任务控制块指针
51     INT8U        x;                        //优先级低3位值
52     INT8U        y;                        //优先级高3位值
53     INT8U        bitx;                     //优先级低3位值计算对应值
54     INT8U        bity;                     //优先级高3位值计算索引值
55
56
57
58 #if OS_ARG_CHK_EN > 0                     //所有参数必须在指定的参数内
59                             //当旧任务 >= 最低优先级 并且 旧任务不是本身 并且新任务>= 最低优先级
60     if ((oldprio >= OS_LOWEST_PRIO && oldprio != OS_PRIO_SELF)  ||
61          newprio >= OS_LOWEST_PRIO) {
62         return (OS_PRIO_INVALID);     //参数中的任务原先优先级或新优先级大于或等于OS_LOWEST_PRIO
63     }
64 #endif
65     OS_ENTER_CRITICAL();                         //关闭中断
66     if (OSTCBPrioTbl[newprio] != (OS_TCB *)0) {  //确认新任务优先级未被使用,即就绪态为0
67         OS_EXIT_CRITICAL();                      //打开中断
68         return (OS_PRIO_EXIST);                  //返回新任务(优先级为PIP的任务已经存在)
69     } else {
70         OSTCBPrioTbl[newprio] = (OS_TCB *)1;     //新任务优先级未被使用,保留它(为1)
71         OS_EXIT_CRITICAL();                      //打开中断
72                                                  //预先计算新任务优先级任务控制块OS_TCB的某些值
73         y    = newprio >> 3;                     //保留优先级高3位(3-5位)
74         bity = OSMapTbl[y];                      //计算索引值
75         x    = newprio & 0x07;                   //保存优先级低3位(0-2位)
76         bitx = OSMapTbl[x];                      //计算对应值
77         OS_ENTER_CRITICAL();                     //关闭中断
78         if (oldprio == OS_PRIO_SELF) {           //要改变的是否使旧任务本身
79             oldprio = OSTCBCur->OSTCBPrio;       //如果是(正在运行的优先级(旧任务本身的优先级))钟常慰
80         }
81         if ((ptcb = OSTCBPrioTbl[oldprio]) != (OS_TCB *)0) {  //变更的旧任务必须存在(1即就绪)
82             OSTCBPrioTbl[oldprio] = (OS_TCB *)0;              //旧任务就绪态去除它(为0)
83             if ((OSRdyTbl[ptcb->OSTCBY] & ptcb->OSTCBBitX) != 0x00) {
84                 //如果该任务处于就绪态,那么必须在当前的优先级下,从就绪表中移除该任务,然后在新
85                 //的优先级下,将该任务插入到就绪表中。
86                 if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) {
87                     OSRdyGrp &= ~ptcb->OSTCBBitY;
88                  }
89                 OSRdyGrp    |= bity;                    //利用预先计算值将任务插入到就绪表中
90                 OSRdyTbl[y] |= bitx;
91 #if OS_EVENT_EN > 0                                     //消息事件是否 > 0
92             } else {                                    //(任务未就绪)否则,拾取任务事件指针
93                 if ((pevent = ptcb->OSTCBEventPtr) != (OS_EVENT *)0) {   //任务事件表为1(有消息)
94                     //如果任务正在等待某一事件的发生,该函数必须将任务从事件控制块的等待列表中删除
95                     //并在新的优先级下将事件插入到等待队列中。任务也可能正在等待延时时间到,或是被
96                     //挂起。
97                     if ((pevent->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) {
98                         pevent->OSEventGrp &= ~ptcb->OSTCBBitY;
99                      }
100                     pevent->OSEventGrp    |= bity;      //将任务插入到等待列表中
101                     pevent->OSEventTbl[y] |= bitx;
102                  }
103 #endif
104             }
105             OSTCBPrioTbl[newprio] = ptcb;               //将任务的OS_TCB的指针存到新任务OSTCBPrioTbl[]
106             ptcb->OSTCBPrio       = newprio;            //设定新的任务优先级,并保存原有计算值
107             ptcb->OSTCBY          = y;                  //高3位计算值
108             ptcb->OSTCBX          = x;                  //低3位计算值
109             ptcb->OSTCBBitY       = bity;
110             ptcb->OSTCBBitX       = bitx;
111             OS_EXIT_CRITICAL();                         //打开中断
112             OS_Sched();                                 //任务调度,最高任务优先级运行
113             return (OS_NO_ERR);                         //任务优先级成功改变
114         } else {                                        //否则
115             OSTCBPrioTbl[newprio] = (OS_TCB *)0;        //新任务就绪态去除它(为0不存在),
116             OS_EXIT_CRITICAL();                         //打开中断
117             return (OS_PRIO_ERR);                       //返回(参数中的任务原先优先级不存在)
118         }
119     }
120 }
121 #endif
122 /*$PAGE*/
123 /*
124 *************************************************************************************************
125 *                                  建立一个新任务(CREATE A TASK)
126 *
127 * 描述: 建立一个新任务。任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立.中断
128 *       处理程序中不能建立任务.一个任务必须为无限循环结构(如下所示),且不能有返回点。
129 *          OSTaskCreate()是为与先前的μC/OS版本保持兼容,新增的特性在OSTaskCreateExt()函数中.
130 *       无论用户程序中是否产生中断,在初始化任务堆栈时,堆栈的结构必须与CPU中断后寄存器入栈的
131 *       顺序结构相同.详细说明请参考所用处理器的手册。
132 *
133 * 参数: task    是指向任务代码的指针。
134 *
135 *       pdata   指向一个数据结构,该结构用来在建立任务时向任务传递参数。下例中说明uC/OS中的任
136 *               务结构以及如何传递参数pdata:
137 *      void Task (void *pdata)
138 *               {
139 *       ...        // 对参数'pdata'进行操作
140 *                 for (;;) {           // 任务函数体.
141 *                 ...
142 *                 ...
143 *   // 在任务体中必须调用如下函数之一:
144 *   //    OSMboxPend()     用于任务等待消息,消息通过中断或另外的任务发送给需要的任务
145 *   //    OSFlgPend()      用于任务等待事件标志中的事件标志
146 *   //    OSMutexPend()    任务需要独占资源
147 *   //    OSQPend()        用于任务等待消息
148 *   //    OSSemPend()      用于任务试图取得共享资源的使用权,任务需要与其它任务或中断
149 *                               同步及任务需要等待特定事件的发生场合
150 *   //    OSTimeDly()      任务延时若干时钟节拍
151 *   //    OSTimeDlyHMSM()  任务延时若干时间
152 *   //    OSTaskSuspend()  挂起任务本身
153 *   //    OSTaskDel()      删除任务本身
154 *                ...
155 *                ...
156 *              }
157 *       ptos   为指向任务堆栈栈顶的指针。任务堆栈用来保存局部变量,函数参数,返回地址以及任务被
158 *              中断时的CPU寄存器内容.任务堆栈的大小决定于任务的需要及预计的中断嵌套层数。计算
159 *              堆栈的大小,需要知道任务的局部变量所占的空间,可能产生嵌套调用的函数,及中断嵌套
160 *              所需空间。如果初始化常量OS_STK_GROWTH设为1,堆栈被设为从内存高地址向低地址增长,
161 *              此时ptos应该指向任务堆栈空间的最高地址。反之,如果OS_STK_GROWTH设为0,堆栈将从内
162 *              存的低地址向高地址增长。
163 *
164 *       prio   为任务的优先级。每个任务必须有一个唯一的优先级作为标识。数字越小,优先级越高。
165 *
166 * 返回: OS_NO_ERR        函数调用成功;
167 *       OS_PRIO_EXIT     具有该优先级的任务已经存在;
168 *       OS_PRIO_INVALID  参数指定的优先级大于OS_LOWEST_PRIO;  (i.e. >= OS_LOWEST_PRIO)
169 *       OS_NO_MORE_TCB   系统中没有OS_TCB可以分配给任务了。
170 *
171 * 注意: 1、任务堆栈必须声明为OS_STK类型。
172 *       2、在任务中必须调用uC/OS提供的下述过程之一:延时等待、任务挂起、等待事件发生(等待信
173 *          号量,消息邮箱、消息队列),以使其他任务得到CPU。
174 *       3、用户程序中不能使用优先级0,1,2,3,以及OS_LOWEST_PRIO-3, OS_LOWEST_PRIO-2,
175 *          OS_LOWEST_PRIO-1, OS_LOWEST_PRIO。这些优先级μC/OS系统保留,其余的56个优先级提供给
176 *          应用程序。
177 *************************************************************************************************
178 */
179
180 #if OS_TASK_CREATE_EN > 0                     //允许生成OSTaskCreate()函数
181 INT8U  OSTaskCreate (void (*task)(void *pd), void *pdata, OS_STK *ptos, INT8U prio)
182 {                        //建立任务(任务代码指针、传递参数指针、分配任务堆栈栈顶指针、任务优先级)
183 #if OS_CRITICAL_METHOD == 3                   //中断函数被设定为模式3
184     OS_CPU_SR  cpu_sr;
185 #endif
186     OS_STK    *psp;                           //初始化任务堆栈指针变量,返回新的栈顶指针
187     INT8U      err;                           //定义(获得并定义初始化任务控制块)是否成功
188
189 #if OS_ARG_CHK_EN > 0                         //所有参数必须在指定的参数内
190     if (prio > OS_LOWEST_PRIO) {              //检查任务优先级是否合法
191         return (OS_PRIO_INVALID);             //参数指定的优先级大于OS_LOWEST_PRIO
192     }
193 #endif
194     OS_ENTER_CRITICAL();                      //关闭中断
195     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) {  //确认优先级未被使用,即就绪态为0
196         OSTCBPrioTbl[prio] = (OS_TCB *)1;     //保留这个优先级,将就绪态设为0
197
198         OS_EXIT_CRITICAL();                   //打开中断
199         psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, 0);          //初始化任务堆栈
200         err = OS_TCBInit(prio, psp, (OS_STK *)0, 0, 0, (void *)0, 0); //获得并初始化任务控制块
201         if (err == OS_NO_ERR) {                                       //任务控制初始化成功
202             OS_ENTER_CRITICAL();              //关闭中断
203             OSTaskCtr++;                      //任务计数器加1
204             OS_EXIT_CRITICAL();               //打开中断
205             if (OSRunning == TRUE) {          //检查是否有(某个)任务在运行
206                 OS_Sched();                   //任务调度,最高任务优先级运行
207             }
208         } else {                              //否则,任务初始化失败
209             OS_ENTER_CRITICAL();              //关闭中断
210             OSTCBPrioTbl[prio] = (OS_TCB *)0; //放弃任务,设此任务就绪态为0
211             OS_EXIT_CRITICAL();               //打开中断
212         }
213         return (err);                         //返回(获得并定义初始化任务控制块是否成功)
214     }
215     OS_EXIT_CRITICAL();                       //打开中断
216     return (OS_PRIO_EXIST);                   //返回(具有该优先级的任务已经存在)
217 }
218 #endif
219 /*$PAGE*/
220 /*
221 *************************************************************************************************
222 *                                     CREATE A TASK (Extended  Version)
223 *
224 * 描述: 建立一个新任务。与OSTaskCreate()不同的是,OSTaskCreateExt()允许用户设置更多的细节
225 *       内容.任务的建立可以在多任务环境启动之前,也可以在正在运行的任务中建立,但中断处理
226 *       程序中不能建立新任务。一个任务必须为无限循环结构(如下所示),且不能有返回点。
227 *
228 * 参数: task     是指向任务代码的指针。
229 *
230 *       pdata Pdata指针指向一个数据结构,该结构用来在建立任务时向任务传递参数。下例中说
231 *
232 *                为了避免在编译中出现"参数未使用"的警告信息,可以写一句pdata= pdata;)
233 *                void Task (void *pdata)
234 *               {
235 *       ...         //对参数pdata进行操作,例如pdata= pdata
236 *                   for (;;) {           // 任务函数体.总是为无限循环结构
237 *                ...
238 *                ...
239 *   // 任务中必须调用如下的函数:
240 *   //    OSMboxPend()     用于任务等待消息,消息通过中断或另外的任务发送给需要的任务
241 *   //    OSFlgPend()      用于任务等待事件标志中的事件标志
242 *   //    OSMutexPend()    任务需要独占资源
243 *   //    OSQPend()        用于任务等待消息
244 *   //    OSSemPend()      用于任务试图取得共享资源的使用权,任务需要与其它任务或中断
245 *                               同步及任务需要等待特定事件的发生场合
246 *   //    OSTimeDly()      任务延时若干时钟节拍
247 *   //    OSTimeDlyHMSM()  任务延时若干时间
248 *   //    OSTaskSuspend()  挂起任务本身
249 *   //    OSTaskDel()      删除任务本身
250 *               ...
251 *               ...
252 *                 }
253 *              }
254 *      ptos     为指向任务堆栈栈顶的指针.任务堆栈用来保存局部变量,函数参数,返回地址以及中
255 *               断时的CPU寄存器内容.任务堆栈的大小决定于任务的需要及预计的中断嵌套层数.计
256 *               算堆栈的大小,需要知道任务的局部变量所占的空间,可能产生嵌套调用的函数,及
257 *               中断嵌套所需空间.如果初始化常量OS_STK_GROWTH设为1,堆栈被设为向低端增长
258 *      (从内存高地址向低地址增长).此时ptos应该指向任务堆栈空间的最高地址.反之,
259 *               如果OS_STK_GROWTH设为0,堆栈将从低地址向高地址增长.
260 *
261 *      prio     任务的优先级。每个任务必须有一个唯一的优先级作为标识.数字越小,优先级越高。
262 *
263 *      id       是任务的标识,目前这个参数没有实际的用途,但保留在OSTaskCreateExt()中供今后
264 *               扩展,应用程序中可设置id与优先级相同.(0..65535)
265 *
266 *      pbos     为指向堆栈底端的指针。如果初始化常量OS_STK_GROWTH设为1,堆栈被设为从内存高
267 *               地址向低地址增长.此时pbos应该指向任务堆栈空间的最低地址.反之,如果
268 *               OS_STK_GROWTH设为0,堆栈将从低地址向高地址增长。pbos应该指向堆栈空间的最高
269 *               地址.参数pbos用于堆栈检测函数OSTaskStkChk().
270 *
271 *      stk_size 指定任务堆栈的大小。其单位由OS_STK定义:当OS_STK的类型定义为INT8U、INT16U、
272 *               INT32U的时候, stk_size的单位为分别为字节(8位)、字(16位)和双字(32位)。
273 *
274 *      pext     是一个用户定义数据结构的指针,可作为TCB的扩展。例如,当任务切换时,用户定义
275 *               的数据结构中可存放浮点寄存器的数值,任务运行时间,任务切入次数等等信息。
276 *
277 *      opt      存放与任务相关的操作信息。opt的低8位由uC/OS保留,用户不能使用。用户可以使用
278 *               opt的高8位。每一种操作由opt中的一位或几位指定,当相应的位被置位时,表示选择
279 *               某种操作。当前的μC/OS版本支持下列操作:
280 *             OS_TASK_OPT_STK_CHK:决定是否进行任务堆栈检查;
281 *             OS_TASK_OPT_STK_CLR:决定是否清空堆栈;
282 *             OS_TASK_OPT_SAVE_FP:决定是否保存浮点寄存器的数值。此项操作仅当处理器有浮
283 *                                      点硬件时有效。保存操作由硬件相关的代码完成。
284 *
285 *
286 * 返回: OS_NO_ERR:函数调用成功;
287 *   OS_PRIO_EXIST:具有该优先级的任务已经存在;
288 *   OS_PRIO_INVALID:参数指定的优先级大于OS_LOWEST_PRIO;
289 *   OS_NO_MORE_TCB:系统中没有OS_TCB可以分配给任务了.
290 *
291 * 注意: 1、任务堆栈必须声明为OS_STK类型;
292 *       2、在任务中必须进行uC/OS提供的下述过程之一:延时等待、任务挂起、等待事件发生(等待
293 *          信号量,消息邮箱、消息队列),以使其他任务得到CPU;
294 *       3、用户程序中不能使用优先级0,1,2,3,以及OS_LOWEST_PRIO-3, OS_LOWEST_PRIO-2,
295 *          OS_LOWEST_PRIO-1, OS_LOWEST_PRIO。这些优先级μC/OS系统保留,其余56个优先级提供给
296 *          应用程序.
297 *************************************************************************************************
298 */
299 /*$PAGE*/
300 #if OS_TASK_CREATE_EXT_EN > 0                     //允许生成OSTaskCreateExt()函数
301 INT8U  OSTaskCreateExt (void   (*task)(void *pd), //建立扩展任务(任务代码指针
302                         void    *pdata,           //传递参数指针
303                         OS_STK  *ptos,            //分配任务堆栈栈顶指针
304                         INT8U    prio,            //分配任务优先级
305                         INT16U   id,              //(未来的)优先级标识(与优先级相同)
306                         OS_STK  *pbos,            //分配任务堆栈栈底指针
307                         INT32U   stk_size,        //指定堆栈的容量(检验用)
308                         void    *pext,            //指向用户附加的数据域的指针
309                         INT16U   opt)             //建立任务设定选项)
310 {
311 #if OS_CRITICAL_METHOD == 3                       //中断函数被设定为模式3
312     OS_CPU_SR  cpu_sr;
313 #endif
314     OS_STK    *psp;                               //初始化任务堆栈指针变量,返回新的栈顶指针
315     INT8U      err;                               //定义(获得并定义初始化任务控制块)是否成功
316
317 #if OS_ARG_CHK_EN > 0                             //所有参数必须在指定的参数内
318     if (prio > OS_LOWEST_PRIO) {                  //检查任务优先级是否合法
319         return (OS_PRIO_INVALID);                 //参数指定的优先级大于OS_LOWEST_PRIO
320     }
321 #endif
322     OS_ENTER_CRITICAL();                          //关闭中断
323     if (OSTCBPrioTbl[prio] == (OS_TCB *)0) {      //确认优先级未被使用,即就绪态为0
324         OSTCBPrioTbl[prio] = (OS_TCB *)1;         //保留这个优先级,将就绪态设为0
325
326         OS_EXIT_CRITICAL();                       //打开中断
327  //以下两为1堆栈才能清0
328         if (((opt & OS_TASK_OPT_STK_CHK) != 0x0000) ||              //检验任务堆栈,CHK=1
329             ((opt & OS_TASK_OPT_STK_CLR) != 0x0000)) {              //任务建立时是否清0,CLR=1
330             #if OS_STK_GROWTH == 1                                  //堆栈生长方向
331             (void)memset(pbos, 0, stk_size * sizeof(OS_STK));       //从下向上递增
332             #else
333             (void)memset(ptos, 0, stk_size * sizeof(OS_STK));       //从上向下递减
334             #endif
335         }
336
337         psp = (OS_STK *)OSTaskStkInit(task, pdata, ptos, opt);      //初始化任务堆栈
338         err = OS_TCBInit(prio, psp, pbos, id, stk_size, pext, opt); //获得并初始化任务控制块
339         if (err == OS_NO_ERR) {                                     //任务控制初始化成功
340             OS_ENTER_CRITICAL();                  //关闭中断
341             OSTaskCtr++;                          //任务计数器加1
342             OS_EXIT_CRITICAL();                   //打开中断
343             if (OSRunning == TRUE) {              //检查是否有(某个)任务在运行
344                 OS_Sched();                       //任务调度,最高任务优先级运行
345             }
346         } else {                                  //否则,任务初始化失败
347             OS_ENTER_CRITICAL();                  //关闭中断
348             OSTCBPrioTbl[prio] = (OS_TCB *)0;     //放弃任务,设此任务就绪态为0
349             OS_EXIT_CRITICAL();                   //打开中断
350         }
351         return (err);                             //返回(获得并定义初始化任务控制块是否成功)
352     }
353     OS_EXIT_CRITICAL();                           //打开中断
354     return (OS_PRIO_EXIST);                       //具有该优先级的任务已经存在
355 }
356 #endif
357 /*$PAGE*/
358 /*
359 *************************************************************************************************
360 *                            删除一个指定优先级的任务(DELETE A TASK)
361 *
362 * 描述: 删除一个指定优先级的任务。任务可以传递自己的优先级给OSTaskDel(),从而删除自身.如果任
363 *       务不知道自己的优先级,还可以传递参数OS_PRIO_SELF.被删除的任务将回到休眠状态.任务被删
364 *       除后可以用函数OSTaskCreate()或OSTaskCreateExt()重新建立.
365 *
366 * 参数: prio   为指定要删除任务的优先级,也可以用参数OS_PRIO_SELF代替,此时,下一个优先级最高
367 *              的就绪任务将开始运行。
368 *
369 * 返回: OS_NO_ERR:函数调用成功;
370 *   OS_TASK_DEL_IDLE:错误操作,试图删除空闲任务(Idle task);
371 *   OS_TASK_DEL_ ERR:错误操作,指定要删除的任务不存在;
372 *   OS_PRIO_INVALID:参数指定的优先级大于OS_LOWEST_PRIO;
373 *   OS_TASK_DEL_ISR:错误操作,试图在中断处理程序中删除任务.
374 *
375 *
376 * 注意: 1、OSTaskDel()将判断用户是否试图删除uC/OS中的空闲任务(Idle task);
377 *       2、在删除占用系统资源的任务时要小心,此时,为安全起见可以用另一个函数OSTaskDelReq().
378
379 *************************************************************************************************
380 */
381 /*$PAGE*/
382 #if OS_TASK_DEL_EN > 0                      //允许生成 OSTaskDel()函数
383 INT8U  OSTaskDel (INT8U prio)               //删除任务(任务的优先级)
384 {
385 #if OS_CRITICAL_METHOD == 3                 //中断函数被设定为模式3
386     OS_CPU_SR     cpu_sr;
387 #endif
388
389 #if OS_EVENT_EN > 0                         //消息事件是否 > 0
390     OS_EVENT     *pevent;                   //定义事件指针
391 #endif
392     //版本是否 > 2.51 并且 允许产生事件标志相关代码 并且应用中最多事件标志组的数目 > 0
393 #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
394     OS_FLAG_NODE *pnode;                    //定义标志节点
395 #endif
396     OS_TCB       *ptcb;                     //定义消息事件的任务控制块指针
397
398
399
400     if (OSIntNesting > 0) {                 //当前中断嵌套 > 0时,表示还有中断程序运行
401         return (OS_TASK_DEL_ISR);           //错误操作,试图在中断处理程序中删除任务
402     }
403 #if OS_ARG_CHK_EN > 0                       //所有参数必须在指定的参数内
404     if (prio == OS_IDLE_PRIO) {             //检查任务优先级是否是空闲任务
405         return (OS_TASK_DEL_IDLE);          //错误操作,试图删除空闲任务(Idle task)
406     }  //当任务 >= 最低优先级 并且 任务不是本身
407     if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {  //检查任务是否是合法的
408         return (OS_PRIO_INVALID);           //参数指定的优先级大于OS_LOWEST_PRIO
409     }
410 #endif
411     OS_ENTER_CRITICAL();                    //关闭中断
412     if (prio == OS_PRIO_SELF) {             //检查的删除者是否是任务(优先级)本身
413         prio = OSTCBCur->OSTCBPrio;         //正在运行的优先级(任务本身的优先级)
414     }                                                   //删除的任务必须存在
415     if ((ptcb = OSTCBPrioTbl[prio]) != (OS_TCB *)0) {   //调用这个任务的优先级的就绪值
416         if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) {  //当就绪=1(即就绪状态)
417             OSRdyGrp &= ~ptcb->OSTCBBitY;   //该任务处于就绪值,从就绪表中去除
418         }
419 #if OS_EVENT_EN > 0                         //消息事件是否 > 0
420         pevent = ptcb->OSTCBEventPtr;       //拾取该任务的事件控制指针
421         if (pevent != (OS_EVENT *)0) {
422                                             //指向事件控制块的指针是否为Null
423             if ((pevent->OSEventTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0) {
424                                             //事件(消息)在等待表中将自己所处的表中删除
425                 pevent->OSEventGrp &= ~ptcb->OSTCBBitY;
426             }
427         }
428 #endif
429     //版本是否 > 2.51 并且 允许产生事件标志相关代码 并且应用中最多事件标志组的数目 > 0
430 #if (OS_VERSION >= 251) && (OS_FLAG_EN > 0) && (OS_MAX_FLAGS > 0)
431         pnode = ptcb->OSTCBFlagNode;         //标志节点 = 指向事件标志节点的指针
432         if (pnode != (OS_FLAG_NODE *)0) {    //如果任务处于事件标志的等待表中
433             OS_FlagUnlink(pnode);            //就从此表中删除
434         }
435 #endif
436         ptcb->OSTCBDly  = 0;                 //将任务时钟节拍清0,确保重新开中断,中断程序不使该任务就绪
437         ptcb->OSTCBStat = OS_STAT_RDY;       //将任务的状态字处于完毕状态
438         if (OSLockNesting < 255) {   //如果锁定嵌套计数器 < 255,
439             OSLockNesting++;                 //锁定嵌套计数器加1,使这个任务处于休眠状态
440         }
441         OS_EXIT_CRITICAL();                  //打开中断
442         OS_Dummy();                          //增加一个空指令
443         OS_ENTER_CRITICAL();                 //关闭中断
444         if (OSLockNesting > 0) {     //(可以继续执行删除任务的操作了)
445             OSLockNesting--;                 //重新关闭中断后,可以通过锁定嵌套计数器减1,重新允许任务调度
446         }
447         OSTaskDelHook(ptcb);                 //可在钩子程序中加入自定程序
448         OSTaskCtr--;                         //任务计数器减1,ucos管理的任务减少一个
449         OSTCBPrioTbl[prio] = (OS_TCB *)0;    //将被删除的任务控制块OS_TCB指针=Null,
450                                              //从任务优先级中把OS_TCB删除
451         if (ptcb->OSTCBPrev == (OS_TCB *)0) {             //任务块双向链接表的前链接是否Null
452             ptcb->OSTCBNext->OSTCBPrev = (OS_TCB *)0;     //删除该任务的任务控制块OS_TCB
453             OSTCBList                  = ptcb->OSTCBNext; //链接表指向后一个链接
454         } else {                                          //否则
455             ptcb->OSTCBPrev->OSTCBNext = ptcb->OSTCBNext; // ?
456             ptcb->OSTCBNext->OSTCBPrev = ptcb->OSTCBPrev; // ?
457         }                                    //OSTCBPrev:用于任务块双向链接表的前链接
458                                              //OSTCBNext:用于任务块双向链接表的后链接
459                                              //OSTCBFreeList:空任务控制块指针
460         ptcb->OSTCBNext = OSTCBFreeList;     //被删除的任务控制块OS_TCB被退回到空闲OS_TCB表中
461         OSTCBFreeList   = ptcb;              //以供建立其它任务使用
462         OS_EXIT_CRITICAL();                  //打开中断
463         OS_Sched();                          //任务调度,最高任务优先级运行
464         return (OS_NO_ERR);                  //函数调用成功
465     }
466     OS_EXIT_CRITICAL();                      //打开中断
467     return (OS_TASK_DEL_ERR);                //错误操作,指定要删除的任务不存在
468 }
469 #endif
470 /*$PAGE*/
471 /*
472 *************************************************************************************************
473 *               请求一个任务删除其它任务或自身(REQUEST THAT A TASK DELETE ITSELF)
474 *
475 * 描述: 请求一个任务删除自身。通常OSTaskDelReq()用于删除一个占有系统资源的任务(例如任务建立
476 *       了信号量)对于此类任务,在删除任务之前应当先释放任务占用的系统资源。
477 *       具体的做法是:在需要被删除的任务中调用OSTaskDelReq()检测是否有其他任务的删除请求,如
478 *       果有,则释放自身占用的资源,然后调用OSTaskDel()删除自身。例如,假设任务5要删除任务10,
479 *       而任务10占有系统资源,此时任务5不能直接调用OSTaskDel(10)删除任务10,而应该调用
480 *       OSTaskDelReq(10)向任务10发送删除请求.在任务10中调用OSTaskDelReq(OS_PRIO_SELF),并检测
481 *       返回值。如果返回OS_TASK_DEL_REQ,则表明有来自其他任务的删除请求,此时任务10应该先释放
482 *       资源,然后调用OSTaskDel(OS_PRIO_SELF)删除自己。任务5可以循环调用OSTaskDelReq(10)并检
483 *       测返回值,如果返回OS_TASK_NOT_EXIST,表明任务10已经成功删除。
484 *         void Task(void *data)
485 *         {
486 *     ...
487 *     ...
488 *            while (1) {
489 *                       OSTimeDly(1);
490 *                       if (OSTaskDelReq(OS_PRIO_SELF) == OS_TASK_DEL_REQ)
491 *                       {
492 *                       释放任务占用的系统资源;
493 *                       释放动态分配的内存;
494 *                       OSTaskDel(OS_PRIO_SELF);
495 *                       }
496 *                      }
497 *         }
498 * 参数: prio  为要求删除任务的优先级。如果参数为OS_PRIO_SELF,则表示调用函数的任务正在查询
499 *             是否有来自其他任务的删除请求。
500 *
501 * 返回: OS_NO_ERR:删除请求已经被任务记录;
502 *   OS_TASK_NOT_EXIST:指定的任务不存在,发送删除请求的任务可以等待此返回值,看删除是否成功;
503 *   OS_TASK_DEL_IDLE: 错误操作,试图删除空闲任务(Idle task);
504 *   OS_PRIO_INVALID:  参数指定的优先级大于OS_LOWEST_PRIO或没有设定OS_PRIO_SELF的值;
505 *   OS_TASK_DEL_REQ:  当前任务收到来自其他任务的删除请求;
506 * 注意:OSTaskDelReq()将判断用户是否试图删除uC/OS中的空闲任务(Idle task)。
507 *************************************************************************************************
508 */
509 /*$PAGE*/
510 #if OS_TASK_DEL_EN > 0                      //允许生成 OSTaskDel()函数
511 INT8U  OSTaskDelReq (INT8U prio)            //请求一个任务删除其它任务或自身?(任务的优先级)
512 {
513 #if OS_CRITICAL_METHOD == 3                 //中断函数被设定为模式3
514     OS_CPU_SR  cpu_sr;
515 #endif
516     BOOLEAN stat;                        //定义(布尔)任务标志返回值
517     INT8U      err;                         //定义函数成功删除或其它任务正在申请删除
518     OS_TCB    *ptcb;                        //定义消息事件的任务控制块指针
519
520
521 #if OS_ARG_CHK_EN > 0                       //所有参数必须在指定的参数内
522     if (prio == OS_IDLE_PRIO) {             //检查任务优先级是否是空闲任务
523         return (OS_TASK_DEL_IDLE);          //错误操作,试图删除空闲任务(Idle task)
524     }                                       //当任务 >= 最低优先级 并且 任务不是本身
525     if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {   //检查任务是否是合法的
526         return (OS_PRIO_INVALID);           //参数指定的优先级大于OS_LOWEST_PRIO
527     }
528 #endif
529     if (prio == OS_PRIO_SELF) {             //如果删除者是任务本身
530         OS_ENTER_CRITICAL();                //关闭中断
531         stat = OSTCBCur->OSTCBDelReq;       //stat:存储在任务控制块中的标志值
532         OS_EXIT_CRITICAL();                 //打开中断
533         return (stat);                      //返回任务标志值
534     }
535     OS_ENTER_CRITICAL();                               //关闭中断
536     if ((ptcb = OSTCBPrioTbl[prio]) != (OS_TCB *)0) {  //调用这个任务的优先级的就绪值
537         ptcb->OSTCBDelReq = OS_TASK_DEL_REQ;           //当前任务收到来自其他任务的删除请求
538         err               = OS_NO_ERR;                 //删除请求已经被任务记录
539     } else {                                           //否则
540         err               = OS_TASK_NOT_EXIST;         //该任务可能已经删除了
541     }
542         //指定的任务不存在,发送删除请求的任务可以等待此返回值,看删除是否成功
543
544     OS_EXIT_CRITICAL();                                //关闭中断
545     return (err);                                      //返回删除情况标志
546 }
547 #endif
548 /*$PAGE*/
549 /*
550 *************************************************************************************************
551 *               唤醒一个用OSTaskSuspend()函数挂起的任务(RESUME A SUSPENDED TASK)
552 *
553 * 描述: 唤醒一个用OSTaskSuspend()函数挂起的任务。OSTaskResume()也是唯一能"解挂"挂起任务的函数。
554 *
555 * 参数: prio   指定要唤醒任务的优先级。
556 *
557 * 返回: OS_NO_ERR:            函数调用成功;
558 *   OS_TASK_RESUME_PRIO:  要唤醒的任务不存在;
559 *   OS_TASK_NOT_SUSPENDED:要唤醒的任务不在挂起状态;
560 *   OS_PRIO_INVALID:      参数指定的优先级大于或等于OS_LOWEST_PRIO。
561 *************************************************************************************************
562 */
563
564 #if OS_TASK_SUSPEND_EN > 0                //允许生成 OSTaskDel()函数
565 INT8U  OSTaskResume (INT8U prio)          //唤醒一个用OSTaskSuspend()函数挂起的任务(任务的优先级)
566 {
567 #if OS_CRITICAL_METHOD == 3               //中断函数被设定为模式3
568     OS_CPU_SR  cpu_sr;
569 #endif
570     OS_TCB    *ptcb;                      //定义消息事件的任务控制块指针
571
572
573 #if OS_ARG_CHK_EN > 0                     //所有参数必须在指定的参数内
574     if (prio >= OS_LOWEST_PRIO) {         //当任务 >= 最低优先级
575         return (OS_PRIO_INVALID);         //返回(要唤醒的任务不存在)
576     }
577 #endif
578     OS_ENTER_CRITICAL();                                //关闭中断
579     if ((ptcb = OSTCBPrioTbl[prio]) == (OS_TCB *)0) {   //调用这个任务的优先级的就绪值
580         OS_EXIT_CRITICAL();                             //打开中断
581         return (OS_TASK_RESUME_PRIO);                   //返回(要唤醒的任务不存在)
582     }   //任务控制块状态字相与OS_STAT_SUSPEND为1,任务存在
583     if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) != 0x00) {  //要恢复的任务必须是存在的
584           //通过清除OSTCBStat域中的OS_STAT_SUSPEND未而取消挂起
585           //要使任务处于就绪状态,OSTCBDly必须是0,这是因为在OSTCBStat中,没有任何标志表明任务正在
586           //等待延时事件到
587         if (((ptcb->OSTCBStat &= ~OS_STAT_SUSPEND) == OS_STAT_RDY) &&
588              (ptcb->OSTCBDly  == 0)) {
589                                                         //只有以上两个条件满足,任务才能处于就绪态
590             OSRdyGrp               |= ptcb->OSTCBBitY;  //保存任务就绪标准0-7到OSRdyGrp
591             OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;  //保存任务优先级别0-7到OSRdyTbl[]
592             OS_EXIT_CRITICAL();                         //打开中断
593             OS_Sched();                                 //任务调度,最高任务优先级运行
594         } else {                                        //否则
595             OS_EXIT_CRITICAL();                         //打开中断
596         }
597         return (OS_NO_ERR);                             //返回(函数调用成功)
598     }
599     OS_EXIT_CRITICAL();                                 //打开中断
600     return (OS_TASK_NOT_SUSPENDED);                     //返回(要唤醒的任务不在挂起状态)
601 }
602 #endif
603 /*$PAGE*/
604 /*
605 *************************************************************************************************
606 *       检查任务堆栈状态,计算指定任务堆栈中的未用空间和已用空间(STACK CHECKING)
607 *
608 * 描述: 检查任务堆栈状态,计算指定任务堆栈中的未用空间和已用空间。使用OSTaskStkChk()函数要求
609 *       所检查的任务是被OSTaskCreateExt()函数建立的,且opt参数中OS_TASK_OPT_STK_CHK操作项打开。
610 * //计算堆栈未用空间的方法是从堆栈底端向顶端逐个字节比较,检查堆栈中0的个数,直到一个非0的
611 *       数值出现.这种方法的前提是堆栈建立时已经全部清零.要实现清零操作,需要在任务建立初始化
612 *       堆栈时设置OS_TASK_OPT_STK_CLR为1.如果应用程序在初始化时已经将全部RAM清零,且不进行任
613 *       务删除操作,也可以设置OS_TASK_OPT_STK_CLR为0,这将加快OSTaskCreateExt()函数的执行速度。
614 *
615 * 参数: prio  为指定要获取堆栈信息的任务优先级,也可以指定参数OS_PRIO_SELF,获取调用任务本身的
616 *             信息。
617 *
618 *       pdata  指向一个类型为OS_STK_DATA的数据结构,其中包含如下信息:
619 *              INT32U OSFree;        // 堆栈中未使用的字节数
620 *              INT32U OSUsed;        // 堆栈中已使用的字节数
621 *
622 * 返回: OS_NO_ERR:        函数调用成功;
623 *   OS_PRIO_INVALID:  参数指定的优先级大于OS_LOWEST_PRIO,或未指定OS_PRIO_SELF;
624 *   OS_TASK_NOT_EXIST:指定的任务不存在;
625 *   OS_TASK_OPT_ERR:  任务用OSTaskCreateExt()函数建立的时候没有指定OS_TASK_OPT_STK_CHK
626 *                          操作,或者任务是用OSTaskCreate()函数建立的。
627 *
628 * 注意: 1、函数的执行时间是由任务堆栈的大小决定的,事先不可预料;
629 *       2、在应用程序中可以把OS_STK_DATA结构中的数据项OSFree和OSUsed相加,可得到堆栈的大小;
630 *       3、虽然原则上该函数可以在中断程序中调用,但由于该函数可能执行很长时间,所以实际中不提
631 *          倡这种做法。
632 *************************************************************************************************
633 */
634 #if OS_TASK_CREATE_EXT_EN > 0             //允许生成 OSTaskStkChk()函数
635 INT8U  OSTaskStkChk (INT8U prio, OS_STK_DATA *pdata)
636 {                                         //检查任务堆栈状态(任务优先级、检验堆栈数据结构)
637 #if OS_CRITICAL_METHOD == 3               //中断函数被设定为模式3
638     OS_CPU_SR  cpu_sr;
639 #endif
640     OS_TCB    *ptcb;                      //定义消息事件的任务控制块指针
641     OS_STK    *pchk;                      //定义指向当前任务堆栈栈底的指针
642     INT32U     free;                      //定义任务堆栈实际空闲字节数
643     INT32U     size;                      //定义存有栈中可容纳的指针数目
644
645
646 #if OS_ARG_CHK_EN > 0                     //所有参数必须在指定的参数内
647         //当任务 >= 最低优先级 并且 任务不是本身
648     if (prio > OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {   //检查任务是否是合法的
649         return (OS_PRIO_INVALID);  //参数指定的优先级大于OS_LOWEST_PRIO,或未指定OS_PRIO_SELF
650     }
651 #endif
652     pdata->OSFree = 0;                    //未使用的字节清0
653     pdata->OSUsed = 0;                    //已使用的字节清0
654     OS_ENTER_CRITICAL();                  //关闭中断
655     if (prio == OS_PRIO_SELF) {           //如果检查者是任务本身
656         prio = OSTCBCur->OSTCBPrio;       //指向正在运行(优先级)任务控制块的指针
657     }
658     ptcb = OSTCBPrioTbl[prio];            //调用这个优先级别任务的就绪值
659     if (ptcb == (OS_TCB *)0) {            //当检验OSTCBPrioTbl[]里是非0值,确定任务存在
660         OS_EXIT_CRITICAL();               //打开中断
661         return (OS_TASK_NOT_EXIST);       //指定的任务不存在
662     }
663     //要执行堆栈检验,必须用OSTaskCreateExt()函数建立任务,并且已经传递了选项OS_TASK_OPT_STK_CHK,
664     //而对OSTaskCreate()函数建立的任务,那么会对OPT(传递给OS_TCBInit)为0,而使检验失败
665     if ((ptcb->OSTCBOpt & OS_TASK_OPT_STK_CHK) == 0) {   //如果检验OPT=0
666         OS_EXIT_CRITICAL();                              //打开中断
667         return (OS_TASK_OPT_ERR);                        //返回检验失败
668     }                                     //从堆栈栈底统计堆栈空闲空间,直到遇到一个存储非0值
669     free = 0;                             //堆栈中未使用的字节数free = 0
670     size = ptcb->OSTCBStkSize;            //size = 存有栈中可容纳的指针数目
671     pchk = ptcb->OSTCBStkBottom;          //pchk = 指向当前任务堆栈栈底的指针
672     OS_EXIT_CRITICAL();                   //打开中断
673 #if OS_STK_GROWTH == 1                    //查看堆栈增长方向,为1递增
674     while (*pchk++ == (OS_STK)0) {        //当前任务堆栈栈顶的指针加1(内容)是否等于0
675         free++;                           //定义堆栈中未使用的字节数加1
676     }
677 #else                                     //否则,向下递减
678     while (*pchk-- == (OS_STK)0) {        //当前任务堆栈栈底的指针减1(内容)是否等于0
679         free++;                           //定义堆栈中未使用的字节数加1
680     }
681 #endif
682     pdata->OSFree = free * sizeof(OS_STK);           //任务堆栈实际空闲字节数
683     pdata->OSUsed = (size - free) * sizeof(OS_STK);  //任务堆栈已被占用的字节数
684     return (OS_NO_ERR);                              //函数调用成功
685 }
686 #endif
687 /*$PAGE*/
688 /*
689 *************************************************************************************************
690 *                       无条件挂起一个任务(SUSPEND A TASK)
691 *
692 * 描述: 无条件挂起一个任务. 调用此函数的任务也可以传递参数OS_PRIO_SELF,挂起调用任务本身.
693 *       当前任务挂起后,只有其他任务才能唤醒.任务挂起后,系统会重新进行任务调度,运行下一个
694 *       优先级最高的就绪任务.唤醒挂起任务需要调用函数OSTaskResume().
695 * //任务的挂起是可以叠加到其他操作上的。例如,任务被挂起时正在进行延时操作,那么任务的
696 *       唤醒就需要两个条件:延时的结束以及其他任务的唤醒操作.又如,任务被挂起时正在等待信
697 *       号量,当任务从信号量的等待对列中清除后也不能立即运行,而必须等到唤醒操作后。
698 *
699 * 参数: prio  为指定要获取挂起的任务优先级,也可以指定参数OS_PRIO_SELF,挂起任务本身.此时,
700 *             下一个优先级最高的就绪任务将运行.
701 *
702 * 返回: OS_NO_ERR:             函数调用成功;
703 *   OS_TASK_ SUSPEND_IDLE: 试图挂起uC/OS-II中的空闲任务(Idle task)。此为非法操作;
704 *   OS_PRIO_INVALID:       参数指定的优先级大于OS_LOWEST_PRIO或没有设定OS_PRIO_SELF的值;
705 *   OS_TASK_ SUSPEND _PRIO:要挂起的任务不存在。
706 *
707 * 注意: 1、在程序中OSTaskSuspend()和OSTaskResume()应该成对使用;
708 *       2、用OSTaskSuspend()挂起的任务只能用OSTaskResume()唤醒.
709 *************************************************************************************************
710 */
711
712 #if OS_TASK_SUSPEND_EN > 0                //允许生成 OSTaskSuspend()函数
713 INT8U  OSTaskSuspend (INT8U prio)         //无条件挂起一个任务(任务优先级)
714 {
715 #if OS_CRITICAL_METHOD == 3               //中断函数被设定为模式3
716     OS_CPU_SR  cpu_sr;
717 #endif
718     BOOLEAN self;                      //定义布尔(=1为任务本身)
719     OS_TCB    *ptcb;                      //定义消息事件的任务控制块指针
720
721
722 #if OS_ARG_CHK_EN > 0                     //所有参数必须在指定的参数内
723     if (prio == OS_IDLE_PRIO) {           //检查任务的优先级是否是空闲任务
724         return (OS_TASK_SUSPEND_IDLE); //试图挂起uC/OS-II中的空闲任务(Idle task)。此为非法操作
725     }    //当任务 >= 最低优先级 并且 任务不是本身
726     if (prio >= OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {   //检查任务是否是合法的
727         return (OS_PRIO_INVALID); //参数指定的优先级大于OS_LOWEST_PRIO或没有设定OS_PRIO_SELF的值
728     }
729 #endif
730     OS_ENTER_CRITICAL();                  //关闭中断
731     if (prio == OS_PRIO_SELF) {           //如果删除者是任务本身
732         prio = OSTCBCur->OSTCBPrio;       //从当前任务的任务控制块OS_TCB中获取当前任务的优先级
733         self = TRUE;                      //是任务本身(为1)
734     } else if (prio == OSTCBCur->OSTCBPrio) { //也可以通过指定优先级,挂起调用本函数的任务
735         self = TRUE;                          //是任务本身(为1)
736     } else {                                  //否则
737         self = FALSE;                         //要删除的不是任务本身
738     }
739     if ((ptcb = OSTCBPrioTbl[prio]) == (OS_TCB *)0) {  //检验要挂起的任务是否存在(为1任务存在)
740         OS_EXIT_CRITICAL();                            //打开中断
741         return (OS_TASK_SUSPEND_PRIO);                 //返回(要挂起的任务不存在)
742     }
743     if ((OSRdyTbl[ptcb->OSTCBY] &= ~ptcb->OSTCBBitX) == 0x00) { //如果该任务存在
744         OSRdyGrp &= ~ptcb->OSTCBBitY;     //从就绪表中清除它(等待事件的话也删除)
745     }
746     ptcb->OSTCBStat |= OS_STAT_SUSPEND;   //在任务的状态字中标明'SUSPENDED',表示任务被挂起
747     OS_EXIT_CRITICAL();                   //打开中断
748     if (self == TRUE) {                   //如果是任务本身(为1)
749         OS_Sched();                       //任务调度,最高任务优先级运行
750                               //说明:self == TRUE,删除本身,需要进入任务调度执行新的任务
751                               //self = FALSE,删除的是其它任务,无需进入调度,可继续执行本任务
752     }
753     return (OS_NO_ERR);                   //返回(函数调用成功)
754 }
755 #endif
756 /*$PAGE*/
757 /*
758 *************************************************************************************************
759 *                 获取任务信息,函数返回任务TCB的一个完整的拷贝(QUERY A TASK)
760 *
761 * 描述: 获取任务信息,函数返回任务TCB的一个完整的拷贝.应用程序必须建立一个OS_TCB类型的数据结
762 *       构容纳返回的数据.需要提醒用户的是,在对任务OS_TCB对象中的数据操作时要小心,尤其是数据
763 *       项OSTCBNext和OSTCBPrev.它们分别指向TCB链表中的后一项和前一项.
764 *
765 * 参数: prio 为指定要获取TCB内容的任务优先级,也可以指定参数OS_PRIO_SELF,获取调用任务的信息.
766 *       pdata指向一个OS_TCB类型的数据结构,容纳返回的任务TCB的一个拷贝.
767 *
768 * 返回: OS_NO_ERR:      函数调用成功;
769 *   OS_PRIO_ERR:    参数指定的任务非法;
770 *   OS_PRIO_INVALID:参数指定的优先级大于OS_LOWEST_PRIO.
771 * 注意: 任务控制块(TCB)中所包含的数据成员取决于下述开关量在初始化时的设定(参见OS_CFG.H)
772 *   OS_TASK_CREATE_EN
773 *   OS_Q_EN
774 *   OS_MBOX_EN
775 *   OS_SEM_EN
776 *   OS_TASK_DEL_EN
777 *************************************************************************************************
778 */
779
780 #if OS_TASK_QUERY_EN > 0                         //允许(1)生成OSTaskQuery()代码
781 INT8U  OSTaskQuery (INT8U prio, OS_TCB *pdata)   //获取任务信息(任务指针、保存数据结构指针)
782 {
783 #if OS_CRITICAL_METHOD == 3                                //中断函数被设定为模式3
784     OS_CPU_SR  cpu_sr;
785 #endif
786     OS_TCB    *ptcb;                                       //定义消息事件的任务控制块指针
787
788
789 #if OS_ARG_CHK_EN > 0
790         //当任务 >= 最低优先级 并且 任务不是本身
791     if (prio > OS_LOWEST_PRIO && prio != OS_PRIO_SELF) {   //检查任务是否是合法的
792         return (OS_PRIO_INVALID);                          //参数指定的优先级大于OS_LOWEST_PRIO
793     }
794 #endif
795     OS_ENTER_CRITICAL();                                   //关闭中断
796     if (prio == OS_PRIO_SELF) {                            //检查的删除者是否是任务(优先级)本身
797         prio = OSTCBCur->OSTCBPrio;                        //正在运行的优先级(任务本身的优先级)
798     }                                                      //获取(信息)任务必须存在
799     if ((ptcb = OSTCBPrioTbl[prio]) == (OS_TCB *)0) {      //调用这个任务的优先级的就绪值
800         OS_EXIT_CRITICAL();                                //打开中断
801         return (OS_PRIO_ERR);                              //返回(参数指定的任务非法)
802     }
803     memcpy(pdata, ptcb, sizeof(OS_TCB));                   //所有的域(通过赋值语句)一次性复制
804     OS_EXIT_CRITICAL();                                    //打开中断
805     return (OS_NO_ERR);                                    //返回获取信息成功(函数调用成功)
806 }
807 #endif
808


 

你可能感兴趣的:(OS_TASK.C)