OS_MBOX.C

简介: 1 /*2 *********************************************************************************************************3 * uC/OS-II实时控制内核4 *
1 /*
2 *********************************************************************************************************
3 *                                          uC/OS-II实时控制内核
4 *                                              消息邮箱管理
5 * 文 件 : OS_MBOX.C     消息邮件管理代码
6 * 作 者 : Jean J. Labrosse
7 * 中文注解: 钟常慰  zhongcw @ 126.com  整理:lin-credible 译注版本:1.0 请尊重原版内容
8 *********************************************************************************************************
9 */
10
11 #ifndef  OS_MASTER_FILE                      //是否已经定义OS_MASTER_FILE
12 #include "includes.h"                        //包含"includes.h"文件
13 #endif                                       //结束定义
14
15 #if OS_MBOX_EN > 0                           //条件编译允许(1)产生消息邮箱相关代码
16 /*
17 *********************************************************************************************************
18 *                查看指定的消息邮箱是否有需要的消息(ACCEPT MESSAGE FROM MAILBOX)
19 *
20 * 描述: OSMboxAccept()函数查看指定的消息邮箱是否有需要的消息。不同于OSMboxPend()函数,如果没有需要的消息,
21 *       OSMboxAccept()函数并不挂起任务。如果消息已经到达,该消息被传递到用户任务并且从消息邮箱中清除。通
22 *       常中断调用该函数,因为中断不允许挂起等待消息。
23 *
24 * 意见: pevent  是指向需要查看的消息邮箱的指针。当建立消息邮箱时,该指针返回到用户程序。
25 *      (参考OSMboxCreate()函数)。
26 *
27 * 返回: 如果消息已经到达,返回指向该消息的指针;如果消息邮箱没有消息,返回空指针。
28 *
29 * 注意: 必须先建立消息邮箱,然后使用。
30 *********************************************************************************************************
31 */
32
33 #if OS_MBOX_ACCEPT_EN > 0                       //允许(1)生成 OSMboxAccept()代码
34 void  *OSMboxAccept (OS_EVENT *pevent)          //查看消息邮箱(消息邮箱指针)
35 {
36 #if OS_CRITICAL_METHOD == 3                     //中断函数被设定为模式3
37     OS_CPU_SR  cpu_sr;
38 #endif
39     void      *msg;                             //定义消息邮箱内容的指针
40
41
42 #if OS_ARG_CHK_EN > 0                           //所有参数必须在指定的参数内
43     if (pevent == (OS_EVENT *)0) {              //当消息邮箱指针为NULL时,返回0,空指针
44         return ((void *)0);
45     }
46     if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {     //当事件类型≠消息邮箱类型
47         return ((void *)0);                              //返回空指针
48     }
49 #endif
50     OS_ENTER_CRITICAL();                       //关闭中断
51     msg                = pevent->OSEventPtr;   //取消息邮箱中的内容
52     pevent->OSEventPtr = (void *)0;            //将消息邮箱的内容清0
53     OS_EXIT_CRITICAL();                        //打开中断
54     return (msg);                              //返回消息,如果为空,说明没有消息;不为空,说明有内容
55 }
56 #endif
57 /*$PAGE*/
58 /*
59 *********************************************************************************************************
60 *                            建立并初始化一个消息邮箱(CREATE A MESSAGE MAILBOX)
61 *
62 * 描述: 建立并初始化一个消息邮箱。消息邮箱允许任务或中断向其他一个或几个任务发送消息。
63 *
64 * 参数: msg 参数用来初始化建立的消息邮箱。如果该指针不为空,建立的消息邮箱将含有消息。
65 *
66 * 返回: 指向分配给所建立的消息邮箱的事件控制块的指针。如果没有可用的事件控制块,返回空指针。
67 *
68 * 注意: 必须先建立消息邮箱,然后使用。
69 *********************************************************************************************************
70 */
71
72 OS_EVENT  *OSMboxCreate (void *msg)          //建立并初始化一个消息邮箱(msg 参数不为空含内容)
73 {
74 #if OS_CRITICAL_METHOD == 3                  //中断函数被设定为模式3
75     OS_CPU_SR  cpu_sr;
76 #endif
77     OS_EVENT  *pevent;                       //定义一个指向事件控制块的指针
78
79
80     if (OSIntNesting > 0) {                  //中断嵌套数>0时,表示还有中断任务在运行
81         return ((OS_EVENT *)0);              //返回0
82     }
83     OS_ENTER_CRITICAL();                     //关闭中断
84     pevent = OSEventFreeList;                //pevent=空余事件管理列表
85     if (OSEventFreeList != (OS_EVENT *)0) {  //如果有空余事件管理块
86         OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
87     }                                        //空余事件控制链表指向下一个空余事件控制块
88     OS_EXIT_CRITICAL();                      //打开中断
89     if (pevent != (OS_EVENT *)0) {           //如果有空余的事件控制块可用
90         pevent->OSEventType = OS_EVENT_TYPE_MBOX;  //则这个类型=消息邮箱类形
91         pevent->OSEventPtr  = msg;           //将初始值存入事件管理块ECB中
92         OS_EventWaitListInit(pevent);        //初始化一个事件控制块
93     }
94     return (pevent);                         //返回该详细邮箱(事件)的指针,即邮箱句柄
95 }
96 /*$PAGE*/
97 /*
98 *********************************************************************************************************
99 *                               删除消息邮箱 (DELETE A MAIBOX)
100 *
101 * 描述: 删除消息邮箱。因为多任务可能会试图继续使用已经删除了的邮箱,故调用本函数有风险。使用本函数
102 *       须特别小心。一般的说,删除邮箱之前,应该首先删除与本邮箱有关的任务。
103 *
104 * 描述: pevent  指向邮箱得指针.该指针是在邮箱建立时,返回给用户应用程序的指针.(参考OSMboxCreate())
105 *
106 *       opt     该选项定义邮箱的删除条件:
107 *               opt == OS_DEL_NO_PEND   可以选择只能在已经没有任何任务在等待该邮箱的消息时,才能删除邮箱;
108 *               opt == OS_DEL_ALWAYS    不管有没有任务在等待邮箱的消息,立即删除邮箱。
109 *                 -->第2种情况下,所有等待邮箱消息的任务都立即进入就绪态。
110 *
111 *       err     指向错误代码的指针,返回出错代码可以是以下几种之一:
112 *               OS_NO_ERR               调用成功,邮箱已经删除;
113 *               OS_ERR_DEL_ISR          试图在中断服务子程序中删除邮箱;
114 *               OS_ERR_INVALID_OPT      无效的opt参数,用户没有将opt定义为上述2种情况之一;
115 *               OS_ERR_TASK_WAITING     一个或更多的任务在等待邮箱的消息;
116 *               OS_ERR_EVENT_TYPE       pevent不是指向邮箱的指针;
117 *               OS_ERR_PEVENT_NULL      已经没有OS_EVENT数据结构可以使用。
118 *
119 * 返回: pevent  返回空指针NULL,表示邮箱已被删除,返回pevent,表示邮箱没有删除,在这种情况下,应该进一步
120 *               查看出错代码,找到出错原因。
121 *
122 * 注意: 1) 使用这个函数调用时,须特别小心。因为其他任务可能还要用这个邮箱。
123 *       2) 当挂起的任务进入就绪态时,中断是关闭的,这就意味着中断延迟时间与在等待邮箱的消息的任务数有关。
124 *       3) 调用OSMboxAccept()函数也不可能知道邮箱是否已经被删除了。
125 *********************************************************************************************************
126 */
127
128 #if OS_MBOX_DEL_EN > 0                           //允许(1)生成 OSMboxDel()代码
129                                                  //删除消息邮箱(消息邮箱指针、删除条件、出错代码指针)
130 OS_EVENT  *OSMboxDel (OS_EVENT *pevent, INT8U opt, INT8U *err)
131 {
132 #if OS_CRITICAL_METHOD == 3                      //中断函数被设定为模式3
133     OS_CPU_SR  cpu_sr;
134 #endif
135     BOOLEAN tasks_waiting;                    //定义布尔量,任务等待条件
136
137
138     if (OSIntNesting > 0) {                      //中断嵌套数>0时,表示还有中断任务在运行
139         *err = OS_ERR_DEL_ISR;                   //错误等于(试图在中断程序中删除一个信号量事件)
140         return (pevent);                         //返回消息邮箱指针
141     }
142 #if OS_ARG_CHK_EN > 0                            //所有参数在指定的范围之内
143     if (pevent == (OS_EVENT *)0) {               //当消息邮箱指针为NULL,即0(空)
144         *err = OS_ERR_PEVENT_NULL;               //错误等于(已经没有可用的OS_EVENT数据结构了)
145         return (pevent);                         //返回消息邮箱指针
146     }
147     if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {   //当事件类型不否是消息邮箱类型
148         *err = OS_ERR_EVENT_TYPE;                //pevent指针不是指向消息邮箱
149         return (pevent);                         //返回消息邮箱指针
150     }
151 #endif
152     OS_ENTER_CRITICAL();                         //关闭中断
153     if (pevent->OSEventGrp != 0x00) {            //事件等待标志,索引值≠0,有任务在等待
154         tasks_waiting = TRUE;                    //有任务在等待=1(TRUE真)
155     } else {
156         tasks_waiting = FALSE;                   //否则,没有任务在等待=0,(FALSE假)
157     }
158     switch (opt) {                               //条件选择
159         case OS_DEL_NO_PEND:                     //1)没有任务在等待该消息邮箱
160              if (tasks_waiting == FALSE) {       //如果没有事件在等待
161                  pevent->OSEventType = OS_EVENT_TYPE_UNUSED;  //事件类型=空闲
162                  pevent->OSEventPtr  = OSEventFreeList;       //信号量对应的指针=空余块链接表
163                  OSEventFreeList     = pevent;                //空余块链接表=当前事件指针
164                  OS_EXIT_CRITICAL();             //关闭中断
165                  *err = OS_NO_ERR;               //错误等于(成功删除)
166                  return ((OS_EVENT *)0);         //返回0
167              } else {                            //否则,有任务在等待
168                  OS_EXIT_CRITICAL();             //打开中断
169                  *err = OS_ERR_TASK_WAITING;     //错误等于(有一个或一个以上的任务在等待消息邮箱)
170                  return (pevent);                //返回消息邮箱指针
171              }
172
173         case OS_DEL_ALWAYS:                      //2)多任务等待,尽管有任务在等待,还是要删除
174              while (pevent->OSEventGrp != 0x00) {                  //等待标志≠0,还是要删除
175                                        //OS_EventTaskRdy()函数将最高级优先级任务从等待列表中删除
176                  OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX); //使一个任务进入就绪态
177              }
178              pevent->OSEventType = OS_EVENT_TYPE_UNUSED;           //事件类型=空闲
179              pevent->OSEventPtr  = OSEventFreeList;                //消息邮箱对应的指针=空余块链接表
180              OSEventFreeList     = pevent;                         //空余块链接表=当前事件指针
181              OS_EXIT_CRITICAL();                 //关闭中断
182              if (tasks_waiting == TRUE) {        //当任务等待=1,真
183                  OS_Sched();                     //任务调度,最高优先级进入运行状态
184              }
185              *err = OS_NO_ERR;                   //错误等于(成功删除)
186              return ((OS_EVENT *)0);             //返回0
187
188         default:                                 // 3)当以上两种情况都不是
189              OS_EXIT_CRITICAL();                 //关闭中断
190              *err = OS_ERR_INVALID_OPT;          //错误等于(没有将opt参数定义为2种合法的参数之一)
191              return (pevent);                    //返回信号量指针
192     }
193 }
194 #endif
195
196 /*$PAGE*/
197 /*
198 *********************************************************************************************************
199 *                             任务等待消息(PEND ON MAILBOX FOR A MESSAGE)
200 *
201 * 描述: 用于任务等待消息。消息通过中断或另外的任务发送给需要的任务。
202 *
203 * 参数: pevent  是指向即将接受消息的消息邮箱的指针。该指针的值在建立该消息邮箱时可以得到。
204 *
205 *       timeout 允许一个任务在经过了指定数目的时钟节拍后还没有得到需要的消息时恢复运行。如果该值为零表
206 *               示任务将持续的等待消息。最大的等待时间为65,535个时钟节拍。这个时间长度并不是非常严格的,
207 *               可能存在一个时钟节拍的误差,因为只有在一个时钟节拍结束后才会减少定义的等待超时时钟节拍。
208 *
209 *       err     是指向包含错误码的变量的指针。OSMboxPend()函数返回的错误码可能为下述几种:
210 *
211 *               OS_NO_ERR           消息被正确的接受;
212 *               OS_TIMEOUT          消息没有在指定的周期数内送到;
213 *               OS_ERR_EVENT_TYPE   pevent 不是指向消息邮箱的指针;
214 *               OS_ERR_PEND_ISR     从中断调用该函数。虽然规定了不允许从中断调用该函数,但uC/OS-ii仍
215 *                                   然包含了检测这种情况的功能;
216 *               OS_ERR_PEVENT_NULL  'pevent'是空指针。
217 *
218 * 返回: 返回接受的消息并将 *err置为OS_NO_ERR。如果没有在指定数目的时钟节拍内接受到需要的消息,
219 *       OSMboxPend()函数返回空指针并且将 *err设置为OS_TIMEOUT。
220 *
221 * 注意: 必须先建立消息邮箱,然后使用。
222 *       不允许从中断调用该函数。
223 *********************************************************************************************************
224 */
225 //等待一个消息邮箱函数(消息邮箱指针、允许等待的时钟节拍、代码错误指针)
226 void  *OSMboxPend (OS_EVENT *pevent, INT16U timeout, INT8U *err)
227 {
228 #if OS_CRITICAL_METHOD == 3                      //中断函数被设定为模式3
229     OS_CPU_SR  cpu_sr;
230 #endif
231     void      *msg;                              //定义消息邮箱内容的指针
232
233
234     if (OSIntNesting > 0) {                       //中断嵌套数>0时,表示还有中断任务在运行
235         *err = OS_ERR_PEND_ISR;                   //错误等于(试图在中断程序中等待一个消息邮箱事件)
236         return ((void *)0);                       //返回
237     }
238 #if OS_ARG_CHK_EN > 0                             //所有参数在指定的范围之内
239     if (pevent == (OS_EVENT *)0) {                //当邮箱指针为NULL,即0(空)
240         *err = OS_ERR_PEVENT_NULL;                //pevent是空指针
241         return ((void *)0);                       //返回
242     }
243     if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  //当事件类型不否是消息邮箱类型
244         *err = OS_ERR_EVENT_TYPE;                 //pevent指针不是指向消息邮箱
245         return ((void *)0);                       //返回
246     }
247 #endif
248     OS_ENTER_CRITICAL();                          //关闭中断
249     msg = pevent->OSEventPtr;                     //试取消息邮箱内容
250     if (msg != (void *)0) {                       //检查消息邮箱是否为空
251         pevent->OSEventPtr = (void *)0;           //将0存入消息邮箱中
252         OS_EXIT_CRITICAL();                       //打开中断
253         *err = OS_NO_ERR;                         //返回成功调用,取出消息
254         return (msg);                             //返回接收消息
255     }                                             //如果消息邮箱为空,则进入等待中
256     OSTCBCur->OSTCBStat |= OS_STAT_MBOX; //将任务状态置1,进入睡眠状态,只能通过消息邮箱唤醒
257     OSTCBCur->OSTCBDly   = timeout;               //最长等待时间=timeout,递减式
258     OS_EventTaskWait(pevent);                     //使任务进入等待时间唤醒状态
259     OS_EXIT_CRITICAL();                           //打开中断
260     OS_Sched();                                   //进入调度任务,使就绪态优先级最高任务运行
261     OS_ENTER_CRITICAL();                          //关闭中断
262     msg = OSTCBCur->OSTCBMsg;                     //接收消息=指向任务消息的指针
263     if (msg != (void *)0) {                       //接收消息邮箱是否为空
264         OSTCBCur->OSTCBMsg      = (void *)0;      //传递给消息的指针=空
265         OSTCBCur->OSTCBStat     = OS_STAT_RDY;    //表示任务处于就绪状态
266         OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0;  //指向事件控制块的指针=0
267         OS_EXIT_CRITICAL();                       //打开中断
268         *err                     = OS_NO_ERR;      //成功等待该消息邮箱
269         return (msg);                             //返回接收消息
270     }
271     OS_EventTO(pevent);                           //如果没有获得消息,由于等待超时而返回
272     OS_EXIT_CRITICAL();                           //打开中断
273     *err = OS_TIMEOUT;                            //消息没有在指定的时间送到
274     return ((void *)0);                           //返回0
275 }
276 /*$PAGE*/
277 /*
278 *********************************************************************************************************
279 *                    通过消息邮箱向任务发送消息(POST MESSAGE TO A MAILBOX)
280 *
281 * 描述: 通过消息邮箱向任务发送消息。消息是一个指针长度的变量,在不同的程序中消息的使用也可能不同。如果
282 *       消息邮箱中已经存在消息,返回错误码说明消息邮箱已满。OSMboxPost()函数立即返回调用者,消息也没
283 *       有能够发到消息邮箱。如果有任何任务在等待消息邮箱的消息,最高优先级的任务将得到这个消息。如果等
284 *       待消息的任务优先级比发送消息的任务优先级高,那么高优先级的任务将得到消息而恢复执行,也就是说,
285 *       发生了一次任务切换。
286 *
287 * 参数: pevent  是指向即将接受消息的消息邮箱的指针。该指针的值在建立该消息邮箱时可以得到。
288 *               参考OSMboxCreate()函数
289 *
290 *       msg     是即将实际发送给任务的消息。消息是一个指针长度的变量,在不同的程序中消息的使用也可能不
291 *               同。不允许传递一个空指针,因为这意味着消息邮箱为空。
292 *
293 * 返回: OS_NO_ERR             消息成功的放到消息邮箱中;
294 *       OS_MBOX_FULL          消息邮箱已经包含了其他消息,不空;
295 *       OS_ERR_EVENT_TYPE     'pevent'不是指向消息邮箱的指针;
296 *       OS_ERR_PEVENT_NULL    'pevent'是空指针。
297 *       OS_ERR_POST_NULL_PTR  用户试图发出空指针。根据规则,在这里不支持空指针。
298 *
299 * 注意: 必须先建立消息邮箱,然后使用。
300 *       不允许传递一个空指针,因为这意味着消息邮箱为空。
301 *********************************************************************************************************
302 */
303
304 #if OS_MBOX_POST_EN > 0                          //允许(1)生成 OSMboxPost()代码
305 INT8U  OSMboxPost (OS_EVENT *pevent, void *msg)  //发送消息函数(消息邮箱指针、即将实际发送给任务的消息)
306 {                                   钟常慰
307 #if OS_CRITICAL_METHOD == 3                      //中断函数被设定为模式3
308     OS_CPU_SR  cpu_sr;
309 #endif
310
311
312 #if OS_ARG_CHK_EN > 0                            //所有参数在指定的范围之内
313     if (pevent == (OS_EVENT *)0) {               //当邮箱指针为NULL,即0(空)
314         return (OS_ERR_PEVENT_NULL);             //返回(pevent是空指针)
315     }
316     if (msg == (void *)0) {                      //检查消息是否为空
317         return (OS_ERR_POST_NULL_PTR);           //返回(用户试图发出空指针)不支持空指针
318     }
319     if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  //事件发送标志是否是邮箱标志
320         return (OS_ERR_EVENT_TYPE);                   //'pevent'不是指向消息邮箱的指针
321     }
322 #endif
323     OS_ENTER_CRITICAL();                         //关闭中断
324     if (pevent->OSEventGrp != 0x00) {            //是否有任务在等待该邮箱,索引值≠0
325                                         //OS_EventTaskRdy()函数将最高级优先级任务从等待列表中删除
326         OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX);
327         OS_EXIT_CRITICAL();                           //关闭中断
328         OS_Sched();                                   //如果该任务不是最高优先级,进入(任务调度)
329         return (OS_NO_ERR);                      //消息成功的放到消息邮箱中;
330     }
331     if (pevent->OSEventPtr != (void *)0) {       //事件邮箱指针=空
332         OS_EXIT_CRITICAL();                      //打开中断
333         return (OS_MBOX_FULL);                   //消息邮箱中已经包含了其它的消息(邮箱已满)
334     }
335     pevent->OSEventPtr = msg;                    //指向消息的指针保存到邮箱中
336     OS_EXIT_CRITICAL();                          //打开中断
337     return (OS_NO_ERR);                          //消息成功的放到消息邮箱中
338 }
339 #endif
340
341 /*$PAGE*/
342 /*
343 *********************************************************************************************************
344 *                    通过邮箱向(多)任务发送消息 (POST  MESSAGE TO A MAILBOX)
345 *
346 * 描述: OSMboxPostOpt()与OSMboxPost()相同,只是允许用户程序发消息给多个任务。也就是允许将消息广播给
347 *       所有的等待邮箱消息的任务。OSMboxPostOpt()实际上取代OSMboxPost(),因为它可仿真OSMboxPost().
348 *
349 *       通过邮箱向任务发送消息。消息是一个指针长度的变量,在不同的程序中消息的使用也可能不同。如果
350 *       消息邮箱中已经存在消息,返回错误码说明消息邮箱已满。OSMboxPostOpt()函数立即返回调用者,消息
351 *       也没有能够发到消息邮箱。如果有任何任务在等待消息邮箱的消息,那么OSMboxPostOpt()允许选择2种
352 *       情况之一:1、定义消息只发送给等待邮箱消息得任务中优先级最高得任务,2、让所有等待邮箱消息得,
353 *       任务都得到消息无论在那种条件下,如果得到消息的任务优先级比发送消息的任务优先级高,那么得到
354 *       消息的最高优先级的任务将恢复执行,发消息的任务将被挂起。也就是发生一次任务切换。
355 *
356 * 参数: pevent   是指向即将发送消息的消息邮箱的指针。该指针的值在建立该消息邮箱时可以得到。
357 *                参考OSMboxCreate()函数.
358 *
359 *       msg      是即将实际发送给任务的消息。消息是一个指针长度的变量,在不同的程序中消息的使用也可能
360 *                不同。不允许传递一个空指针,因为这意味着消息邮箱为空。
361 *
362 *       opt      该选项定义邮箱的发送条件:
363 *                OS_POST_OPT_NONE         定义消息只发送给等待邮箱消息得任务中优先级最高得任务;
364 *                OS_POST_OPT_BROADCAST    让所有等待邮箱消息得任务都得到消息。
365 *
366 * 返回: OS_NO_ERR              消息成功的放到消息邮箱中;
367 *       OS_MBOX_FULL           消息邮箱已经包含了其他消息,已满;
368 *       OS_ERR_EVENT_TYPE      'pevent'不是指向消息邮箱的指针;
369 *       S_ERR_PEVENT_NULL      'pevent'是空指针
370 *       OS_ERR_POST_NULL_PTR   用户试图发出空指针。根据规则,在这里不支持空指针。
371 *
372 * 警告: 1) 必须先建立消息邮箱,然后再使用;
373 *       2) 不允许向邮箱发送空指针,因为这意味着消息邮箱为空;
374 *       3) 若想使用本函数,又希望压缩代码长度,则可以将OSMboxPost()函数得开关量关掉;
375 *          因为OSMboxPostOpt()可以仿真OSMboxPost().
376 *       4) OSMboxPostOpt()在广播方式下,即已将opt置为OS_POST_OPT_BROADCAST,函数的执行时间取决与等待
377 *          邮箱消息的任务的数目。
378 *********************************************************************************************************
379 */
380
381 #if OS_MBOX_POST_OPT_EN > 0                      //允许(1)生成 OSMboxPost()代码
382 INT8U  OSMboxPostOpt (OS_EVENT *pevent, void *msg, INT8U opt)
383 {                                                //向邮箱发送一则消息(邮箱指针、消息、条件)
384 #if OS_CRITICAL_METHOD == 3                      //中断函数被设定为模式3
385     OS_CPU_SR  cpu_sr;
386 #endif
387
388
389 #if OS_ARG_CHK_EN > 0                            //所有参数在指定的范围之内
390     if (pevent == (OS_EVENT *)0) {               //当邮箱指针为NULL,即0(空)
391         return (OS_ERR_PEVENT_NULL);             //返回(pevent是空指针)
392     }
393     if (msg == (void *)0) {                      //检查消息是否为空指针
394         return (OS_ERR_POST_NULL_PTR);           //返回(用户试图发出空指针),不支持空指针
395     }
396     if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {  //事件发送标志是否是邮箱标志
397         return (OS_ERR_EVENT_TYPE);                   //'pevent'不是指向消息邮箱的指针
398     }
399 #endif
400     OS_ENTER_CRITICAL();                        //关闭中断
401     if (pevent->OSEventGrp != 0x00) {           //是否有任务在等待该邮箱,索引值≠0
402                                        //如果opt必须为OS_POST_OPT_BROADCAST,所有的任务都得到该消息
403         if ((opt & OS_POST_OPT_BROADCAST) != 0x00) {  //如果opt必须为OS_POST_OPT_BROADCAST
404             while (pevent->OSEventGrp != 0x00) {      //如果是,所有的任务都得到该消息
                    // OS_EventTaskRdy()函数将最高级优先级任务从等待列表中删除
405                 OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX);
406             }
407         } else {                      //如果没有请求广播,那么只有最高任务进入就绪态,准备运行
408                                       // OS_EventTaskRdy()函数将最高级优先级任务从等待列表中删除
409             OS_EventTaskRdy(pevent, msg, OS_STAT_MBOX);
410         }
411         OS_EXIT_CRITICAL();                      //打开中断
412         OS_Sched();                              //如果该任务不是最高优先级,进入(任务调度)
413         return (OS_NO_ERR);                      //消息成功的放到消息邮箱中
414     }
415     if (pevent->OSEventPtr != (void *)0) {       //是否有任务在等待该邮箱,索引值≠0
416         OS_EXIT_CRITICAL();                      //打开中断
417         return (OS_MBOX_FULL);                   //消息邮箱已经包含了其他消息,已满
418     }
419     pevent->OSEventPtr = msg;                    //将消息的指针保存到邮箱中
420     OS_EXIT_CRITICAL();                          //打开中断
421     return (OS_NO_ERR);                          //消息成功的放到消息邮箱中
422 }
423 #endif
424
425 /*$PAGE*/
426 /*
427 *********************************************************************************************************
428 *                    取得消息邮箱的信息(QUERY A MESSAGE MAILBOX)
429 *
430 * 描述: 用来取得消息邮箱的信息。用户程序必须分配一个OS_MBOX_DATA的数据结构,该结构用来从消息邮箱的事件
431 *       控制块接受数据。通过调用OSMboxQuery()函数可以知道任务是否在等待消息以及有多少个任务在等待消息,
432 *       还可以检查消息邮箱现在的消息。
433 *
434 * 参数: pevent 是指向即将接受消息的消息邮箱的指针。该指针的值在建立该消息邮箱时可以得到。
435 *
436 *       pdata  是指向OS_MBOX_DATA数据结构的指针,该数据结构包含下述成员:
437 *   Void   *OSMsg;                              /* 消息邮箱中消息的复制   */
438 *   INT8U  OSEventTbl[OS_EVENT_TBL_SIZE];       /* 消息邮箱等待队列的复制 */
439 *   INT8U  OSEventGrp;
440 *
441 * 返回: OS_NO_ERR           调用成功
442 *       OS_ERR_EVENT_TYPE   'pevent'不是指向消息邮箱的指针。
443 *       OS_ERR_PEVENT_NULL  'pevent'是空指针。
444 *注意:  必须先建立消息邮箱,然后使用
445 *********************************************************************************************************
446 */
447
448 #if OS_MBOX_QUERY_EN > 0                         //允许(1)生成 OSMboxPost()代码
449 INT8U  OSMboxQuery (OS_EVENT *pevent, OS_MBOX_DATA *pdata)
450 {                                                //查询一个邮箱的当前状态(信号量指针、状态数据结构指针)
451 #if OS_CRITICAL_METHOD == 3                      //中断函数被设定为模式3
452     OS_CPU_SR  cpu_sr;                           //返回(pevent是空指针)
453 #endif
454     INT8U     *psrc;                             //定义8位pevent->OSEventTbl[0]的地址指针
455     INT8U     *pdest;                            //定义8位pdata->OSEventTbl[0]的地址指针
456
457
458 #if OS_ARG_CHK_EN > 0                            //所有参数在指定的范围之内
459     if (pevent == (OS_EVENT *)0) {               //当邮箱指针为NULL,即0(空)
460         return (OS_ERR_PEVENT_NULL);             //返回(pevent是空指针)
461     }
462     if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) {   //当事件类型不是邮箱类型
463         return (OS_ERR_EVENT_TYPE);                    //'pevent'不是指向消息邮箱的指针
464     }
465 #endif
466     OS_ENTER_CRITICAL();                               //关闭中断
467     //将事件(邮箱)结构中的等待任务列表复制到pdata数据结构中
468     pdata->OSEventGrp = pevent->OSEventGrp;      //等待事件的任务组中的内容传送到状态数据结构中
469     psrc              = &pevent->OSEventTbl[0];  //保存pevent->OSEventTbl[0]对应的地址
470     pdest             = &pdata->OSEventTbl[0];   //保存pdata->OSEventTbl[0]对应的地址
471
472 #if OS_EVENT_TBL_SIZE > 0                        //当事件就绪对应表中的对应值>0时
473     *pdest++          = *psrc++;                 //地址指针下移一个类型地址,获取消息邮箱的值
474 #endif
475
476 #if OS_EVENT_TBL_SIZE > 1                        //事件就绪对应表中的对应值>1时
477     *pdest++          = *psrc++;                 //地址指针继续下移一个类型地址,获取消息邮箱的值
478 #endif
479
480 #if OS_EVENT_TBL_SIZE > 2                        //事件就绪对应表中的对应值>1时
481     *pdest++          = *psrc++;                 //地址指针继续下移一个类型地址,获取消息邮箱的值
482 #endif
483
484 #if OS_EVENT_TBL_SIZE > 3                        //事件就绪对应表中的对应值>1时
485     *pdest++          = *psrc++;                 //地址指针继续下移一个类型地址,获取消息邮箱的值
486 #endif
487
488 #if OS_EVENT_TBL_SIZE > 4                        //事件就绪对应表中的对应值>1时
489     *pdest++          = *psrc++;                 //地址指针继续下移一个类型地址,获取消息邮箱的值
490 #endif
491
492 #if OS_EVENT_TBL_SIZE > 5                        //事件就绪对应表中的对应值>1时
493     *pdest++          = *psrc++;                 //地址指针继续下移一个类型地址,获取消息邮箱的值
494 #endif
495
496 #if OS_EVENT_TBL_SIZE > 6                        //事件就绪对应表中的对应值>1时
497     *pdest++          = *psrc++;                 //地址指针继续下移一个类型地址,获取消息邮箱的值
498 #endif
499
500 #if OS_EVENT_TBL_SIZE > 7                        //事件就绪对应表中的对应值>7时
501     *pdest             = *psrc;                   //获取最后地址的信号量的值
502 #endif
503     pdata->OSMsg = pevent->OSEventPtr;           //将邮箱中的当前消息从事件数据结构复制到OS_MBOX_DATA数据结构中
504     OS_EXIT_CRITICAL();                          //打开中断
505     return (OS_NO_ERR);                          //返回成功运行
506 }
507 #endif                                           // OS_MBOX_QUERY_EN 函数结束
508 #endif                                           // OS_MBOX_EN文件结束
509

目录
相关文章
|
Python
python os.listdir的替代方案os.scandir
python os.listdir的替代方案os.scandir
518 0
|
3月前
|
JSON Linux 数据格式
Pathlib好用吗?对比os.path
`pathlib`是Python 3.4引入的模块,提供了一种面向对象的方式来处理文件路径,以替代可能引起混淆的`os.path`字符串操作。从3.6版开始,`open()`及`os`, `shutil`, `os.path`中的函数都支持`pathlib.Path`对象。`pathlib`通过统一使用正斜杠处理不同操作系统路径,简化了代码,如在Windows和Linux上。它还允许直接对文件进行读写操作,减少错误和提高可读性。虽然`pathlib`可能稍慢于传统方法,但在大多数情况下,其易用性和可维护性优点远胜过这点性能损失。因此,推荐使用`pathlib`进行路径操作。
|
监控 C语言 Perl
什么是OS单站?西门子PCS7系统如何安装OS单站、OS服务器以及OS客户端?
本文我们来介绍什么是OS单站?OS单站、OS服务器以及OS客户端安装选项如何选择。
什么是OS单站?西门子PCS7系统如何安装OS单站、OS服务器以及OS客户端?
|
iOS开发
OS X开发NSMenu应用详解
OS X开发NSMenu应用详解
770 0
OS X开发NSMenu应用详解
|
Web App开发 安全 iOS开发
您需要的74个最佳OS X(Mac OS)应用程序(2018)
您需要的74个最佳OS X(Mac OS)应用程序(2018) 你刚买了一台新的Apple Mac Mac OS(OS X)机器,你想知道要安装的顶级Mac OS应用程序是什么吗?或者你可能有一段时间没有苹果Mac,但想知道你错过了什么?好吧,本指南几乎涵盖了在OS X Mac(Mac OS)上需要做的所有事情! 我首先列出了最重要的 - 他们(大多数)是免费的,非常棒,非常有用。
9089 0
|
API C语言 开发者
OS
BIOS注意点 1. BIOS是通过汇编或者C语言写的, 要想调动BIOS程序提供的函数, 需要CPU运行在16位模式下, 而我们的操作系统一般是在32位或者64位运行, 所以在操作系统的启动盘中, 我们需要在16位模式下调用BIOS程序的函数通过BIOS获取一些硬件的参数信息, 接着让CPU进入到32位或者64位模式 再谈C语言中的链接 1.
1084 0