| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
os_q.c
Go to the documentation of this file.
1 /*
2 ************************************************************************************************************************
3 * uC/OS-III
4 * The Real-Time Kernel
5 *
6 * (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
7 * All rights reserved. Protected by international copyright laws.
8 *
9 * MESSAGE QUEUE MANAGEMENT
10 *
11 * File : OS_Q.C
12 * By : JJL
13 * Version : V3.03.00
14 *
15 * LICENSING TERMS:
16 * ---------------
17 * uC/OS-III is provided in source form for FREE short-term evaluation, for educational use or
18 * for peaceful research. If you plan or intend to use uC/OS-III in a commercial application/
19 * product then, you need to contact Micrium to properly license uC/OS-III for its use in your
20 * application/product. We provide ALL the source code for your convenience and to help you
21 * experience uC/OS-III. The fact that the source is provided does NOT mean that you can use
22 * it commercially without paying a licensing fee.
23 *
24 * Knowledge of the source code may NOT be used to develop a similar product.
25 *
26 * Please help us continue to provide the embedded community with the finest software available.
27 * Your honesty is greatly appreciated.
28 *
29 * You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
30 ************************************************************************************************************************
31 */
32
33 #define MICRIUM_SOURCE
34 #include <os.h>
35
36 #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
37 const CPU_CHAR *os_q__c = "$Id: $";
38 #endif
39
40
41 #if OS_CFG_Q_EN > 0u
42 /*
43 ************************************************************************************************************************
44 * CREATE A MESSAGE QUEUE
45 *
46 * Description: This function is called by your application to create a message queue. Message queues MUST be created
47 * before they can be used.
48 *
49 * Arguments : p_q is a pointer to the message queue
50 *
51 * p_name is a pointer to an ASCII string that will be used to name the message queue
52 *
53 * max_qty indicates the maximum size of the message queue (must be non-zero). Note that it's also not
54 * possible to have a size higher than the maximum number of OS_MSGs available.
55 *
56 * p_err is a pointer to a variable that will contain an error code returned by this function.
57 *
58 * OS_ERR_NONE the call was successful
59 * OS_ERR_CREATE_ISR can't create from an ISR
60 * OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the Queue after you called
61 * OSSafetyCriticalStart().
62 * OS_ERR_NAME if 'p_name' is a NULL pointer
63 * OS_ERR_OBJ_CREATED if the message queue has already been created
64 * OS_ERR_OBJ_PTR_NULL if you passed a NULL pointer for 'p_q'
65 * OS_ERR_Q_SIZE if the size you specified is 0
66 *
67 * Returns : none
68 ************************************************************************************************************************
69 */
70
71 void OSQCreate (OS_Q *p_q,
72 CPU_CHAR *p_name,
73 OS_MSG_QTY max_qty,
74 OS_ERR *p_err)
75
76 {
77 CPU_SR_ALLOC();
78
79
80
81 #ifdef OS_SAFETY_CRITICAL
82 if (p_err == (OS_ERR *)0) {
83 OS_SAFETY_CRITICAL_EXCEPTION();
84 return;
85 }
86 #endif
87
88 #ifdef OS_SAFETY_CRITICAL_IEC61508
89 if (OSSafetyCriticalStartFlag == DEF_TRUE) {
90 *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
91 return;
92 }
93 #endif
94
95 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
96 if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to be called from an ISR */
97 *p_err = OS_ERR_CREATE_ISR;
98 return;
99 }
100 #endif
101
102 #if OS_CFG_ARG_CHK_EN > 0u
103 if (p_q == (OS_Q *)0) { /* Validate arguments */
104 *p_err = OS_ERR_OBJ_PTR_NULL;
105 return;
106 }
107 if (max_qty == (OS_MSG_QTY)0) { /* Cannot specify a zero size queue */
108 *p_err = OS_ERR_Q_SIZE;
109 return;
110 }
111 #endif
112
113 OS_CRITICAL_ENTER();
114 p_q->Type = OS_OBJ_TYPE_Q; /* Mark the data structure as a message queue */
115 p_q->NamePtr = p_name;
116 OS_MsgQInit(&p_q->MsgQ, /* Initialize the queue */
117 max_qty);
118 OS_PendListInit(&p_q->PendList); /* Initialize the waiting list */
119
120 #if OS_CFG_DBG_EN > 0u
121 OS_QDbgListAdd(p_q);
122 #endif
123 OSQQty++; /* One more queue created */
124
125 OS_CRITICAL_EXIT_NO_SCHED();
126 *p_err = OS_ERR_NONE;
127 }
128
129 /*$PAGE*/
130 /*
131 ************************************************************************************************************************
132 * DELETE A MESSAGE QUEUE
133 *
134 * Description: This function deletes a message queue and readies all tasks pending on the queue.
135 *
136 * Arguments : p_q is a pointer to the message queue you want to delete
137 *
138 * opt determines delete options as follows:
139 *
140 * OS_OPT_DEL_NO_PEND Delete the queue ONLY if no task pending
141 * OS_OPT_DEL_ALWAYS Deletes the queue even if tasks are waiting.
142 * In this case, all the tasks pending will be readied.
143 *
144 * p_err is a pointer to a variable that will contain an error code returned by this function.
145 *
146 * OS_ERR_NONE The call was successful and the queue was deleted
147 * OS_ERR_DEL_ISR If you tried to delete the queue from an ISR
148 * OS_ERR_OBJ_PTR_NULL if you pass a NULL pointer for 'p_q'
149 * OS_ERR_OBJ_TYPE if the message queue was not created
150 * OS_ERR_OPT_INVALID An invalid option was specified
151 * OS_ERR_TASK_WAITING One or more tasks were waiting on the queue
152 *
153 * Returns : == 0 if no tasks were waiting on the queue, or upon error.
154 * > 0 if one or more tasks waiting on the queue are now readied and informed.
155 *
156 * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of the queue MUST
157 * check the return code of OSQPend().
158 *
159 * 2) OSQAccept() callers will not know that the intended queue has been deleted.
160 *
161 * 3) Because ALL tasks pending on the queue will be readied, you MUST be careful in applications where the
162 * queue is used for mutual exclusion because the resource(s) will no longer be guarded by the queue.
163 ************************************************************************************************************************
164 */
165
166 #if OS_CFG_Q_DEL_EN > 0u
167 OS_OBJ_QTY OSQDel (OS_Q *p_q,
168 OS_OPT opt,
169 OS_ERR *p_err)
170 {
171 OS_OBJ_QTY cnt;
172 OS_OBJ_QTY nbr_tasks;
173 OS_PEND_DATA *p_pend_data;
174 OS_PEND_LIST *p_pend_list;
175 OS_TCB *p_tcb;
176 CPU_TS ts;
177 CPU_SR_ALLOC();
178
179
180
181 #ifdef OS_SAFETY_CRITICAL
182 if (p_err == (OS_ERR *)0) {
183 OS_SAFETY_CRITICAL_EXCEPTION();
184 return ((OS_OBJ_QTY)0);
185 }
186 #endif
187
188 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
189 if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't delete a message queue from an ISR */
190 *p_err = OS_ERR_DEL_ISR;
191 return ((OS_OBJ_QTY)0);
192 }
193 #endif
194
195 #if OS_CFG_ARG_CHK_EN > 0u
196 if (p_q == (OS_Q *)0) { /* Validate 'p_q' */
197 *p_err = OS_ERR_OBJ_PTR_NULL;
198 return ((OS_OBJ_QTY)0u);
199 }
200 switch (opt) { /* Validate 'opt' */
201 case OS_OPT_DEL_NO_PEND:
202 case OS_OPT_DEL_ALWAYS:
203 break;
204
205 default:
206 *p_err = OS_ERR_OPT_INVALID;
207 return ((OS_OBJ_QTY)0u);
208 }
209 #endif
210
211 #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
212 if (p_q->Type != OS_OBJ_TYPE_Q) { /* Make sure message queue was created */
213 *p_err = OS_ERR_OBJ_TYPE;
214 return ((OS_OBJ_QTY)0);
215 }
216 #endif
217
218 CPU_CRITICAL_ENTER();
219 p_pend_list = &p_q->PendList;
220 cnt = p_pend_list->NbrEntries;
221 nbr_tasks = cnt;
222 switch (opt) {
223 case OS_OPT_DEL_NO_PEND: /* Delete message queue only if no task waiting */
224 if (nbr_tasks == (OS_OBJ_QTY)0) {
225 #if OS_CFG_DBG_EN > 0u
226 OS_QDbgListRemove(p_q);
227 #endif
228 OSQQty--;
229 OS_QClr(p_q);
230 CPU_CRITICAL_EXIT();
231 *p_err = OS_ERR_NONE;
232 } else {
233 CPU_CRITICAL_EXIT();
234 *p_err = OS_ERR_TASK_WAITING;
235 }
236 break;
237
238 case OS_OPT_DEL_ALWAYS: /* Always delete the message queue */
239 OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT();
240 ts = OS_TS_GET(); /* Get local time stamp so all tasks get the same time */
241 while (cnt > 0u) { /* Remove all tasks from the pend list */
242 p_pend_data = p_pend_list->HeadPtr;
243 p_tcb = p_pend_data->TCBPtr;
244 OS_PendObjDel((OS_PEND_OBJ *)((void *)p_q),
245 p_tcb,
246 ts);
247 cnt--;
248 }
249 #if OS_CFG_DBG_EN > 0u
250 OS_QDbgListRemove(p_q);
251 #endif
252 OSQQty--;
253 OS_QClr(p_q);
254 OS_CRITICAL_EXIT_NO_SCHED();
255 OSSched(); /* Find highest priority task ready to run */
256 *p_err = OS_ERR_NONE;
257 break;
258
259 default:
260 CPU_CRITICAL_EXIT();
261 *p_err = OS_ERR_OPT_INVALID;
262 break;
263 }
264 return (nbr_tasks);
265 }
266 #endif
267
268 /*$PAGE*/
269 /*
270 ************************************************************************************************************************
271 * FLUSH QUEUE
272 *
273 * Description : This function is used to flush the contents of the message queue.
274 *
275 * Arguments : p_q is a pointer to the message queue to flush
276 *
277 * p_err is a pointer to a variable that will contain an error code returned by this function.
278 *
279 * OS_ERR_NONE upon success
280 * OS_ERR_FLUSH_ISR if you called this function from an ISR
281 * OS_ERR_OBJ_PTR_NULL If you passed a NULL pointer for 'p_q'
282 * OS_ERR_OBJ_TYPE If you didn't create the message queue
283 *
284 * Returns : The number of entries freed from the queue
285 *
286 * Note(s) : 1) You should use this function with great care because, when to flush the queue, you LOOSE the
287 * references to what the queue entries are pointing to and thus, you could cause 'memory leaks'. In
288 * other words, the data you are pointing to that's being referenced by the queue entries should, most
289 * likely, need to be de-allocated (i.e. freed).
290 ************************************************************************************************************************
291 */
292
293 #if OS_CFG_Q_FLUSH_EN > 0u
294 OS_MSG_QTY OSQFlush (OS_Q *p_q,
295 OS_ERR *p_err)
296 {
297 OS_MSG_QTY entries;
298 CPU_SR_ALLOC();
299
300
301
302 #ifdef OS_SAFETY_CRITICAL
303 if (p_err == (OS_ERR *)0) {
304 OS_SAFETY_CRITICAL_EXCEPTION();
305 return ((OS_MSG_QTY)0);
306 }
307 #endif
308
309 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
310 if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't flush a message queue from an ISR */
311 *p_err = OS_ERR_FLUSH_ISR;
312 return ((OS_MSG_QTY)0);
313 }
314 #endif
315
316 #if OS_CFG_ARG_CHK_EN > 0u
317 if (p_q == (OS_Q *)0) { /* Validate arguments */
318 *p_err = OS_ERR_OBJ_PTR_NULL;
319 return ((OS_MSG_QTY)0);
320 }
321 #endif
322
323 #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
324 if (p_q->Type != OS_OBJ_TYPE_Q) { /* Make sure message queue was created */
325 *p_err = OS_ERR_OBJ_TYPE;
326 return ((OS_MSG_QTY)0);
327 }
328 #endif
329
330 OS_CRITICAL_ENTER();
331 entries = OS_MsgQFreeAll(&p_q->MsgQ); /* Return all OS_MSGs to the OS_MSG pool */
332 OS_CRITICAL_EXIT();
333 *p_err = OS_ERR_NONE;
334 return ((OS_MSG_QTY)entries);
335 }
336 #endif
337
338 /*$PAGE*/
339 /*
340 ************************************************************************************************************************
341 * PEND ON A QUEUE FOR A MESSAGE
342 *
343 * Description: This function waits for a message to be sent to a queue
344 *
345 * Arguments : p_q is a pointer to the message queue
346 *
347 * timeout is an optional timeout period (in clock ticks). If non-zero, your task will wait for a
348 * message to arrive at the queue up to the amount of time specified by this argument. If you
349 * specify 0, however, your task will wait forever at the specified queue or, until a message
350 * arrives.
351 *
352 * opt determines whether the user wants to block if the queue is empty or not:
353 *
354 * OS_OPT_PEND_BLOCKING
355 * OS_OPT_PEND_NON_BLOCKING
356 *
357 * p_msg_size is a pointer to a variable that will receive the size of the message
358 *
359 * p_ts is a pointer to a variable that will receive the timestamp of when the message was
360 * received, pend aborted or the message queue deleted, If you pass a NULL pointer (i.e.
361 * (CPU_TS *)0) then you will not get the timestamp. In other words, passing a NULL pointer
362 * is valid and indicates that you don't need the timestamp.
363 *
364 * p_err is a pointer to a variable that will contain an error code returned by this function.
365 *
366 * OS_ERR_NONE The call was successful and your task received a message.
367 * OS_ERR_OBJ_PTR_NULL if you pass a NULL pointer for 'p_q'
368 * OS_ERR_OBJ_TYPE if the message queue was not created
369 * OS_ERR_PEND_ABORT the pend was aborted
370 * OS_ERR_PEND_ISR if you called this function from an ISR
371 * OS_ERR_PEND_WOULD_BLOCK If you specified non-blocking but the queue was not empty
372 * OS_ERR_SCHED_LOCKED the scheduler is locked
373 * OS_ERR_TIMEOUT A message was not received within the specified timeout
374 * would lead to a suspension.
375 *
376 * Returns : != (void *)0 is a pointer to the message received
377 * == (void *)0 if you received a NULL pointer message or,
378 * if no message was received or,
379 * if 'p_q' is a NULL pointer or,
380 * if you didn't pass a pointer to a queue.
381 ************************************************************************************************************************
382 */
383
384 void *OSQPend (OS_Q *p_q,
385 OS_TICK timeout,
386 OS_OPT opt,
387 OS_MSG_SIZE *p_msg_size,
388 CPU_TS *p_ts,
389 OS_ERR *p_err)
390 {
391 OS_PEND_DATA pend_data;
392 void *p_void;
393 CPU_SR_ALLOC();
394
395
396
397 #ifdef OS_SAFETY_CRITICAL
398 if (p_err == (OS_ERR *)0) {
399 OS_SAFETY_CRITICAL_EXCEPTION();
400 return ((void *)0);
401 }
402 #endif
403
404 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
405 if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
406 *p_err = OS_ERR_PEND_ISR;
407 return ((void *)0);
408 }
409 #endif
410
411 #if OS_CFG_ARG_CHK_EN > 0u
412 if (p_q == (OS_Q *)0) { /* Validate arguments */
413 *p_err = OS_ERR_OBJ_PTR_NULL;
414 return ((void *)0);
415 }
416 if (p_msg_size == (OS_MSG_SIZE *)0) {
417 *p_err = OS_ERR_PTR_INVALID;
418 return ((void *)0);
419 }
420 switch (opt) {
421 case OS_OPT_PEND_BLOCKING:
422 case OS_OPT_PEND_NON_BLOCKING:
423 break;
424
425 default:
426 *p_err = OS_ERR_OPT_INVALID;
427 return ((void *)0);
428 }
429 #endif
430
431 #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
432 if (p_q->Type != OS_OBJ_TYPE_Q) { /* Make sure message queue was created */
433 *p_err = OS_ERR_OBJ_TYPE;
434 return ((void *)0);
435 }
436 #endif
437
438 if (p_ts != (CPU_TS *)0) {
439 *p_ts = (CPU_TS )0; /* Initialize the returned timestamp */
440 }
441
442 CPU_CRITICAL_ENTER();
443 p_void = OS_MsgQGet(&p_q->MsgQ, /* Any message waiting in the message queue? */
444 p_msg_size,
445 p_ts,
446 p_err);
447 if (*p_err == OS_ERR_NONE) {
448 CPU_CRITICAL_EXIT();
449 return (p_void); /* Yes, Return message received */
450 }
451
452 if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
453 CPU_CRITICAL_EXIT();
454 *p_err = OS_ERR_PEND_WOULD_BLOCK; /* No */
455 return ((void *)0);
456 } else {
457 if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend when the scheduler is locked */
458 CPU_CRITICAL_EXIT();
459 *p_err = OS_ERR_SCHED_LOCKED;
460 return ((void *)0);
461 }
462 }
463
464 OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
465 OS_Pend(&pend_data, /* Block task pending on Message Queue */
466 (OS_PEND_OBJ *)((void *)p_q),
467 OS_TASK_PEND_ON_Q,
468 timeout);
469 OS_CRITICAL_EXIT_NO_SCHED();
470
471 OSSched(); /* Find the next highest priority task ready to run */
472
473 CPU_CRITICAL_ENTER();
474 switch (OSTCBCurPtr->PendStatus) {
475 case OS_STATUS_PEND_OK: /* Extract message from TCB (Put there by Post) */
476 p_void = OSTCBCurPtr->MsgPtr;
477 *p_msg_size = OSTCBCurPtr->MsgSize;
478 if (p_ts != (CPU_TS *)0) {
479 *p_ts = OSTCBCurPtr->TS;
480 }
481 *p_err = OS_ERR_NONE;
482 break;
483
484 case OS_STATUS_PEND_ABORT: /* Indicate that we aborted */
485 p_void = (void *)0;
486 *p_msg_size = (OS_MSG_SIZE)0;
487 if (p_ts != (CPU_TS *)0) {
488 *p_ts = OSTCBCurPtr->TS;
489 }
490 *p_err = OS_ERR_PEND_ABORT;
491 break;
492
493 case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get event within TO */
494 p_void = (void *)0;
495 *p_msg_size = (OS_MSG_SIZE)0;
496 if (p_ts != (CPU_TS *)0) {
497 *p_ts = (CPU_TS )0;
498 }
499 *p_err = OS_ERR_TIMEOUT;
500 break;
501
502 case OS_STATUS_PEND_DEL: /* Indicate that object pended on has been deleted */
503 p_void = (void *)0;
504 *p_msg_size = (OS_MSG_SIZE)0;
505 if (p_ts != (CPU_TS *)0) {
506 *p_ts = OSTCBCurPtr->TS;
507 }
508 *p_err = OS_ERR_OBJ_DEL;
509 break;
510
511 default:
512 p_void = (void *)0;
513 *p_msg_size = (OS_MSG_SIZE)0;
514 *p_err = OS_ERR_STATUS_INVALID;
515 break;
516 }
517 CPU_CRITICAL_EXIT();
518 return (p_void);
519 }
520
521
522 /*$PAGE*/
523 /*
524 ************************************************************************************************************************
525 * ABORT WAITING ON A MESSAGE QUEUE
526 *
527 * Description: This function aborts & readies any tasks currently waiting on a queue. This function should be used to
528 * fault-abort the wait on the queue, rather than to normally signal the queue via OSQPost().
529 *
530 * Arguments : p_q is a pointer to the message queue
531 *
532 * opt determines the type of ABORT performed:
533 *
534 * OS_OPT_PEND_ABORT_1 ABORT wait for a single task (HPT) waiting on the queue
535 * OS_OPT_PEND_ABORT_ALL ABORT wait for ALL tasks that are waiting on the queue
536 * OS_OPT_POST_NO_SCHED Do not call the scheduler
537 *
538 * p_err is a pointer to a variable that will contain an error code returned by this function.
539 *
540 * OS_ERR_NONE At least one task waiting on the queue was readied and
541 * informed of the aborted wait; check return value for the
542 * number of tasks whose wait on the queue was aborted.
543 * OS_ERR_OPT_INVALID if you specified an invalid option
544 * OS_ERR_OBJ_PTR_NULL if you pass a NULL pointer for 'p_q'
545 * OS_ERR_OBJ_TYPE if the message queue was not created
546 * OS_ERR_PEND_ABORT_ISR If this function was called from an ISR
547 * OS_ERR_PEND_ABORT_NONE No task were pending
548 *
549 * Returns : == 0 if no tasks were waiting on the queue, or upon error.
550 * > 0 if one or more tasks waiting on the queue are now readied and informed.
551 ************************************************************************************************************************
552 */
553
554 #if OS_CFG_Q_PEND_ABORT_EN > 0u
555 OS_OBJ_QTY OSQPendAbort (OS_Q *p_q,
556 OS_OPT opt,
557 OS_ERR *p_err)
558 {
559 OS_PEND_LIST *p_pend_list;
560 OS_TCB *p_tcb;
561 CPU_TS ts;
562 OS_OBJ_QTY nbr_tasks;
563 CPU_SR_ALLOC();
564
565
566
567 #ifdef OS_SAFETY_CRITICAL
568 if (p_err == (OS_ERR *)0) {
569 OS_SAFETY_CRITICAL_EXCEPTION();
570 return ((OS_OBJ_QTY)0u);
571 }
572 #endif
573
574 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
575 if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to Pend Abort from an ISR */
576 *p_err = OS_ERR_PEND_ABORT_ISR;
577 return ((OS_OBJ_QTY)0u);
578 }
579 #endif
580
581 #if OS_CFG_ARG_CHK_EN > 0u
582 if (p_q == (OS_Q *)0) { /* Validate 'p_q' */
583 *p_err = OS_ERR_OBJ_PTR_NULL;
584 return ((OS_OBJ_QTY)0u);
585 }
586 switch (opt) { /* Validate 'opt' */
587 case OS_OPT_PEND_ABORT_1:
588 case OS_OPT_PEND_ABORT_ALL:
589 case OS_OPT_PEND_ABORT_1 | OS_OPT_POST_NO_SCHED:
590 case OS_OPT_PEND_ABORT_ALL | OS_OPT_POST_NO_SCHED:
591 break;
592
593 default:
594 *p_err = OS_ERR_OPT_INVALID;
595 return ((OS_OBJ_QTY)0u);
596 }
597 #endif
598
599 #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
600 if (p_q->Type != OS_OBJ_TYPE_Q) { /* Make sure queue was created */
601 *p_err = OS_ERR_OBJ_TYPE;
602 return ((OS_OBJ_QTY)0u);
603 }
604 #endif
605
606 CPU_CRITICAL_ENTER();
607 p_pend_list = &p_q->PendList;
608 if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0u) { /* Any task waiting on queue? */
609 CPU_CRITICAL_EXIT(); /* No */
610 *p_err = OS_ERR_PEND_ABORT_NONE;
611 return ((OS_OBJ_QTY)0u);
612 }
613
614 OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT();
615 nbr_tasks = 0u;
616 ts = OS_TS_GET(); /* Get local time stamp so all tasks get the same time */
617 while (p_pend_list->NbrEntries > (OS_OBJ_QTY)0u) {
618 p_tcb = p_pend_list->HeadPtr->TCBPtr;
619 OS_PendAbort((OS_PEND_OBJ *)((void *)p_q),
620 p_tcb,
621 ts);
622 nbr_tasks++;
623 if (opt != OS_OPT_PEND_ABORT_ALL) { /* Pend abort all tasks waiting? */
624 break; /* No */
625 }
626 }
627 OS_CRITICAL_EXIT_NO_SCHED();
628
629 if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0u) {
630 OSSched(); /* Run the scheduler */
631 }
632
633 *p_err = OS_ERR_NONE;
634 return (nbr_tasks);
635 }
636 #endif
637
638 /*$PAGE*/
639 /*
640 ************************************************************************************************************************
641 * POST MESSAGE TO A QUEUE
642 *
643 * Description: This function sends a message to a queue. With the 'opt' argument, you can specify whether the message
644 * is broadcast to all waiting tasks and/or whether you post the message to the front of the queue (LIFO)
645 * or normally (FIFO) at the end of the queue.
646 *
647 * Arguments : p_q is a pointer to a message queue that must have been created by OSQCreate().
648 *
649 * p_void is a pointer to the message to send.
650 *
651 * msg_size specifies the size of the message (in bytes)
652 *
653 * opt determines the type of POST performed:
654 *
655 * OS_OPT_POST_ALL POST to ALL tasks that are waiting on the queue. This option
656 * can be added to either OS_OPT_POST_FIFO or OS_OPT_POST_LIFO
657 * OS_OPT_POST_FIFO POST message to end of queue (FIFO) and wake up a single
658 * waiting task.
659 * OS_OPT_POST_LIFO POST message to the front of the queue (LIFO) and wake up
660 * a single waiting task.
661 * OS_OPT_POST_NO_SCHED Do not call the scheduler
662 *
663 * Note(s): 1) OS_OPT_POST_NO_SCHED can be added (or OR'd) with one of the other options.
664 * 2) OS_OPT_POST_ALL can be added (or OR'd) with one of the other options.
665 * 3) Possible combination of options are:
666 *
667 * OS_OPT_POST_FIFO
668 * OS_OPT_POST_LIFO
669 * OS_OPT_POST_FIFO + OS_OPT_POST_ALL
670 * OS_OPT_POST_LIFO + OS_OPT_POST_ALL
671 * OS_OPT_POST_FIFO + OS_OPT_POST_NO_SCHED
672 * OS_OPT_POST_LIFO + OS_OPT_POST_NO_SCHED
673 * OS_OPT_POST_FIFO + OS_OPT_POST_ALL + OS_OPT_POST_NO_SCHED
674 * OS_OPT_POST_LIFO + OS_OPT_POST_ALL + OS_OPT_POST_NO_SCHED
675 *
676 * p_err is a pointer to a variable that will contain an error code returned by this function.
677 *
678 * OS_ERR_NONE The call was successful and the message was sent
679 * OS_ERR_MSG_POOL_EMPTY If there are no more OS_MSGs to use to place the message into
680 * OS_ERR_OBJ_PTR_NULL If 'p_q' is a NULL pointer
681 * OS_ERR_OBJ_TYPE If the message queue was not initialized
682 * OS_ERR_Q_MAX If the queue is full
683 *
684 * Returns : None
685 ************************************************************************************************************************
686 */
687
688 void OSQPost (OS_Q *p_q,
689 void *p_void,
690 OS_MSG_SIZE msg_size,
691 OS_OPT opt,
692 OS_ERR *p_err)
693 {
694 CPU_TS ts;
695
696
697
698 #ifdef OS_SAFETY_CRITICAL
699 if (p_err == (OS_ERR *)0) {
700 OS_SAFETY_CRITICAL_EXCEPTION();
701 return;
702 }
703 #endif
704
705 #if OS_CFG_ARG_CHK_EN > 0u
706 if (p_q == (OS_Q *)0) { /* Validate 'p_q' */
707 *p_err = OS_ERR_OBJ_PTR_NULL;
708 return;
709 }
710 switch (opt) { /* Validate 'opt' */
711 case OS_OPT_POST_FIFO:
712 case OS_OPT_POST_LIFO:
713 case OS_OPT_POST_FIFO | OS_OPT_POST_ALL:
714 case OS_OPT_POST_LIFO | OS_OPT_POST_ALL:
715 case OS_OPT_POST_FIFO | OS_OPT_POST_NO_SCHED:
716 case OS_OPT_POST_LIFO | OS_OPT_POST_NO_SCHED:
717 case OS_OPT_POST_FIFO | OS_OPT_POST_ALL | OS_OPT_POST_NO_SCHED:
718 case OS_OPT_POST_LIFO | OS_OPT_POST_ALL | OS_OPT_POST_NO_SCHED:
719 break;
720
721 default:
722 *p_err = OS_ERR_OPT_INVALID;
723 return;
724 }
725 #endif
726
727 #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
728 if (p_q->Type != OS_OBJ_TYPE_Q) { /* Make sure message queue was created */
729 *p_err = OS_ERR_OBJ_TYPE;
730 return;
731 }
732 #endif
733
734 ts = OS_TS_GET(); /* Get timestamp */
735
736 #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
737 if (OSIntNestingCtr > (OS_NESTING_CTR)0) {
738 OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_Q, /* Post to ISR queue */
739 (void *)p_q,
740 (void *)p_void,
741 (OS_MSG_SIZE)msg_size,
742 (OS_FLAGS )0,
743 (OS_OPT )opt,
744 (CPU_TS )ts,
745 (OS_ERR *)p_err);
746 return;
747 }
748 #endif
749
750 OS_QPost(p_q,
751 p_void,
752 msg_size,
753 opt,
754 ts,
755 p_err);
756 }
757
758 /*$PAGE*/
759 /*
760 ************************************************************************************************************************
761 * CLEAR THE CONTENTS OF A MESSAGE QUEUE
762 *
763 * Description: This function is called by OSQDel() to clear the contents of a message queue
764 *
765
766 * Argument(s): p_q is a pointer to the queue to clear
767 * ---
768 *
769 * Returns : none
770 *
771 * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
772 ************************************************************************************************************************
773 */
774
775 void OS_QClr (OS_Q *p_q)
776 {
777 (void)OS_MsgQFreeAll(&p_q->MsgQ); /* Return all OS_MSGs to the free list */
778 p_q->Type = OS_OBJ_TYPE_NONE; /* Mark the data structure as a NONE */
779 p_q->NamePtr = (CPU_CHAR *)((void *)"?Q");
780 OS_MsgQInit(&p_q->MsgQ, /* Initialize the list of OS_MSGs */
781 0u);
782 OS_PendListInit(&p_q->PendList); /* Initialize the waiting list */
783 }
784
785 /*$PAGE*/
786 /*
787 ************************************************************************************************************************
788 * ADD/REMOVE MESSAGE QUEUE TO/FROM DEBUG LIST
789 *
790 * Description: These functions are called by uC/OS-III to add or remove a message queue to/from a message queue debug
791 * list.
792 *
793 * Arguments : p_q is a pointer to the message queue to add/remove
794 *
795 * Returns : none
796 *
797 * Note(s) : These functions are INTERNAL to uC/OS-III and your application should not call it.
798 ************************************************************************************************************************
799 */
800
801
802 #if OS_CFG_DBG_EN > 0u
803 void OS_QDbgListAdd (OS_Q *p_q)
804 {
805 p_q->DbgNamePtr = (CPU_CHAR *)((void *)" ");
806 p_q->DbgPrevPtr = (OS_Q *)0;
807 if (OSQDbgListPtr == (OS_Q *)0) {
808 p_q->DbgNextPtr = (OS_Q *)0;
809 } else {
810 p_q->DbgNextPtr = OSQDbgListPtr;
811 OSQDbgListPtr->DbgPrevPtr = p_q;
812 }
813 OSQDbgListPtr = p_q;
814 }
815
816
817
818 void OS_QDbgListRemove (OS_Q *p_q)
819 {
820 OS_Q *p_q_next;
821 OS_Q *p_q_prev;
822
823
824 p_q_prev = p_q->DbgPrevPtr;
825 p_q_next = p_q->DbgNextPtr;
826
827 if (p_q_prev == (OS_Q *)0) {
828 OSQDbgListPtr = p_q_next;
829 if (p_q_next != (OS_Q *)0) {
830 p_q_next->DbgPrevPtr = (OS_Q *)0;
831 }
832 p_q->DbgNextPtr = (OS_Q *)0;
833
834 } else if (p_q_next == (OS_Q *)0) {
835 p_q_prev->DbgNextPtr = (OS_Q *)0;
836 p_q->DbgPrevPtr = (OS_Q *)0;
837
838 } else {
839 p_q_prev->DbgNextPtr = p_q_next;
840 p_q_next->DbgPrevPtr = p_q_prev;
841 p_q->DbgNextPtr = (OS_Q *)0;
842 p_q->DbgPrevPtr = (OS_Q *)0;
843 }
844 }
845 #endif
846
847 /*$PAGE*/
848 /*
849 ************************************************************************************************************************
850 * MESSAGE QUEUE INITIALIZATION
851 *
852 * Description: This function is called by OSInit() to initialize the message queue management.
853 *
854
855 * Arguments : p_err is a pointer to a variable that will receive an error code.
856 *
857 * OS_ERR_NONE the call was successful
858 *
859 * Returns : none
860 *
861 * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
862 ************************************************************************************************************************
863 */
864
865 void OS_QInit (OS_ERR *p_err)
866 {
867 #ifdef OS_SAFETY_CRITICAL
868 if (p_err == (OS_ERR *)0) {
869 OS_SAFETY_CRITICAL_EXCEPTION();
870 return;
871 }
872 #endif
873
874 #if OS_CFG_DBG_EN > 0u
875 OSQDbgListPtr = (OS_Q *)0;
876 #endif
877
878 OSQQty = (OS_OBJ_QTY)0;
879 *p_err = OS_ERR_NONE;
880 }
881
882 /*$PAGE*/
883 /*
884 ************************************************************************************************************************
885 * POST MESSAGE TO A QUEUE
886 *
887 * Description: This function sends a message to a queue. With the 'opt' argument, you can specify whether the message
888 * is broadcast to all waiting tasks and/or whether you post the message to the front of the queue (LIFO)
889 * or normally (FIFO) at the end of the queue.
890 *
891 * Arguments : p_q is a pointer to a message queue that must have been created by OSQCreate().
892 *
893 * p_void is a pointer to the message to send.
894 *
895 * msg_size specifies the size of the message (in bytes)
896 *
897 * opt determines the type of POST performed:
898 *
899 * OS_OPT_POST_ALL POST to ALL tasks that are waiting on the queue
900 *
901 * OS_OPT_POST_FIFO POST as FIFO and wake up single waiting task
902 * OS_OPT_POST_LIFO POST as LIFO and wake up single waiting task
903 *
904 * OS_OPT_POST_NO_SCHED Do not call the scheduler
905 *
906 * ts is the timestamp of the post
907 *
908 * p_err is a pointer to a variable that will contain an error code returned by this function.
909 *
910 * OS_ERR_NONE The call was successful and the message was sent
911 * OS_ERR_MSG_POOL_EMPTY If there are no more OS_MSGs to use to place the message into
912 * OS_ERR_OBJ_PTR_NULL If 'p_q' is a NULL pointer
913 * OS_ERR_OBJ_TYPE If the message queue was not initialized
914 * OS_ERR_Q_MAX If the queue is full
915 *
916 * Returns : None
917 *
918 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
919 ************************************************************************************************************************
920 */
921
922 void OS_QPost (OS_Q *p_q,
923 void *p_void,
924 OS_MSG_SIZE msg_size,
925 OS_OPT opt,
926 CPU_TS ts,
927 OS_ERR *p_err)
928 {
929 OS_OBJ_QTY cnt;
930 OS_OPT post_type;
931 OS_PEND_LIST *p_pend_list;
932 OS_PEND_DATA *p_pend_data;
933 OS_PEND_DATA *p_pend_data_next;
934 OS_TCB *p_tcb;
935 CPU_SR_ALLOC();
936
937
938
939 OS_CRITICAL_ENTER();
940 p_pend_list = &p_q->PendList;
941 if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0) { /* Any task waiting on message queue? */
942 if ((opt & OS_OPT_POST_LIFO) == (OS_OPT)0) { /* Determine whether we post FIFO or LIFO */
943 post_type = OS_OPT_POST_FIFO;
944 } else {
945 post_type = OS_OPT_POST_LIFO;
946 }
947 OS_MsgQPut(&p_q->MsgQ, /* Place message in the message queue */
948 p_void,
949 msg_size,
950 post_type,
951 ts,
952 p_err);
953 OS_CRITICAL_EXIT();
954 return;
955 }
956
957 if ((opt & OS_OPT_POST_ALL) != (OS_OPT)0) { /* Post message to all tasks waiting? */
958 cnt = p_pend_list->NbrEntries; /* Yes */
959 } else {
960 cnt = (OS_OBJ_QTY)1; /* No */
961 }
962 p_pend_data = p_pend_list->HeadPtr;
963 while (cnt > 0u) {
964 p_tcb = p_pend_data->TCBPtr;
965 p_pend_data_next = p_pend_data->NextPtr;
966 OS_Post((OS_PEND_OBJ *)((void *)p_q),
967 p_tcb,
968 p_void,
969 msg_size,
970 ts);
971 p_pend_data = p_pend_data_next;
972 cnt--;
973 }
974 OS_CRITICAL_EXIT_NO_SCHED();
975 if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0) {
976 OSSched(); /* Run the scheduler */
977 }
978 *p_err = OS_ERR_NONE;
979 }
980
981 #endif