| 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_flag.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 * EVENT FLAG MANAGEMENT
10 *
11 * File : OS_FLAG.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_flag__c = "$Id: $";
38 #endif
39
40
41 #if OS_CFG_FLAG_EN > 0u
42
43 /*$PAGE*/
44 /*
45 ************************************************************************************************************************
46 * CREATE AN EVENT FLAG
47 *
48 * Description: This function is called to create an event flag group.
49 *
50 * Arguments : p_grp is a pointer to the event flag group to create
51 *
52 * p_name is the name of the event flag group
53 *
54 * flags contains the initial value to store in the event flag group (typically 0).
55 *
56 * p_err is a pointer to an error code which will be returned to your application:
57 *
58 * OS_ERR_NONE if the call was successful.
59 * OS_ERR_CREATE_ISR if you attempted to create an Event Flag from an ISR.
60 * OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the Event Flag after you
61 * called OSSafetyCriticalStart().
62 * OS_ERR_NAME if 'p_name' is a NULL pointer
63 * OS_ERR_OBJ_CREATED if the event flag group has already been created
64 * OS_ERR_OBJ_PTR_NULL if 'p_grp' is a NULL pointer
65 *
66 * Returns : none
67 ************************************************************************************************************************
68 */
69
70 void OSFlagCreate (OS_FLAG_GRP *p_grp,
71 CPU_CHAR *p_name,
72 OS_FLAGS flags,
73 OS_ERR *p_err)
74 {
75 CPU_SR_ALLOC();
76
77
78
79 #ifdef OS_SAFETY_CRITICAL
80 if (p_err == (OS_ERR *)0) {
81 OS_SAFETY_CRITICAL_EXCEPTION();
82 return;
83 }
84 #endif
85
86 #ifdef OS_SAFETY_CRITICAL_IEC61508
87 if (OSSafetyCriticalStartFlag == DEF_TRUE) {
88 *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
89 return;
90 }
91 #endif
92
93 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
94 if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from ISR ... */
95 *p_err = OS_ERR_CREATE_ISR; /* ... can't CREATE from an ISR */
96 return;
97 }
98 #endif
99
100 #if OS_CFG_ARG_CHK_EN > 0u
101 if (p_grp == (OS_FLAG_GRP *)0) { /* Validate 'p_grp' */
102 *p_err = OS_ERR_OBJ_PTR_NULL;
103 return;
104 }
105 #endif
106
107 OS_CRITICAL_ENTER();
108 p_grp->Type = OS_OBJ_TYPE_FLAG; /* Set to event flag group type */
109 p_grp->NamePtr = p_name;
110 p_grp->Flags = flags; /* Set to desired initial value */
111 p_grp->TS = (CPU_TS)0;
112 OS_PendListInit(&p_grp->PendList);
113
114 #if OS_CFG_DBG_EN > 0u
115 OS_FlagDbgListAdd(p_grp);
116 #endif
117 OSFlagQty++;
118
119 OS_CRITICAL_EXIT_NO_SCHED();
120 *p_err = OS_ERR_NONE;
121 }
122
123 /*$PAGE*/
124 /*
125 ************************************************************************************************************************
126 * DELETE AN EVENT FLAG GROUP
127 *
128 * Description: This function deletes an event flag group and readies all tasks pending on the event flag group.
129 *
130 * Arguments : p_grp is a pointer to the desired event flag group.
131 *
132 * opt determines delete options as follows:
133 *
134 * OS_OPT_DEL_NO_PEND Deletes the event flag group ONLY if no task pending
135 * OS_OPT_DEL_ALWAYS Deletes the event flag group even if tasks are waiting.
136 * In this case, all the tasks pending will be readied.
137 *
138 * p_err is a pointer to an error code that can contain one of the following values:
139 *
140 * OS_ERR_NONE The call was successful and the event flag group was deleted
141 * OS_ERR_DEL_ISR If you attempted to delete the event flag group from an ISR
142 * OS_ERR_OBJ_PTR_NULL If 'p_grp' is a NULL pointer.
143 * OS_ERR_OBJ_TYPE If you didn't pass a pointer to an event flag group
144 * OS_ERR_OPT_INVALID An invalid option was specified
145 * OS_ERR_TASK_WAITING One or more tasks were waiting on the event flag group.
146 *
147 * Returns : == 0 if no tasks were waiting on the event flag group, or upon error.
148 * > 0 if one or more tasks waiting on the event flag group are now readied and informed.
149 *
150 * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of the event flag
151 * group MUST check the return code of OSFlagPost and OSFlagPend().
152 ************************************************************************************************************************
153 */
154
155 #if OS_CFG_FLAG_DEL_EN > 0u
156 OS_OBJ_QTY OSFlagDel (OS_FLAG_GRP *p_grp,
157 OS_OPT opt,
158 OS_ERR *p_err)
159 {
160 OS_OBJ_QTY cnt;
161 OS_OBJ_QTY nbr_tasks;
162 OS_PEND_DATA *p_pend_data;
163 OS_PEND_LIST *p_pend_list;
164 OS_TCB *p_tcb;
165 CPU_TS ts;
166 CPU_SR_ALLOC();
167
168
169
170 #ifdef OS_SAFETY_CRITICAL
171 if (p_err == (OS_ERR *)0) {
172 OS_SAFETY_CRITICAL_EXCEPTION();
173 return ((OS_OBJ_QTY)0);
174 }
175 #endif
176
177 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
178 if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from ISR ... */
179 *p_err = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
180 return ((OS_OBJ_QTY)0);
181 }
182 #endif
183
184 #if OS_CFG_ARG_CHK_EN > 0u
185 if (p_grp == (OS_FLAG_GRP *)0) { /* Validate 'p_grp' */
186 *p_err = OS_ERR_OBJ_PTR_NULL;
187 return ((OS_OBJ_QTY)0);
188 }
189 switch (opt) { /* Validate 'opt' */
190 case OS_OPT_DEL_NO_PEND:
191 case OS_OPT_DEL_ALWAYS:
192 break;
193
194 default:
195 *p_err = OS_ERR_OPT_INVALID;
196 return ((OS_OBJ_QTY)0);
197 }
198 #endif
199
200 #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
201 if (p_grp->Type != OS_OBJ_TYPE_FLAG) { /* Validate event group object */
202 *p_err = OS_ERR_OBJ_TYPE;
203 return ((OS_OBJ_QTY)0);
204 }
205 #endif
206 OS_CRITICAL_ENTER();
207 p_pend_list = &p_grp->PendList;
208 cnt = p_pend_list->NbrEntries;
209 nbr_tasks = cnt;
210 switch (opt) {
211 case OS_OPT_DEL_NO_PEND: /* Delete group if no task waiting */
212 if (nbr_tasks == (OS_OBJ_QTY)0) {
213 #if OS_CFG_DBG_EN > 0u
214 OS_FlagDbgListRemove(p_grp);
215 #endif
216 OSFlagQty--;
217 OS_FlagClr(p_grp);
218
219 OS_CRITICAL_EXIT();
220 *p_err = OS_ERR_NONE;
221 } else {
222 OS_CRITICAL_EXIT();
223 *p_err = OS_ERR_TASK_WAITING;
224 }
225 break;
226
227 case OS_OPT_DEL_ALWAYS: /* Always delete the event flag group */
228 ts = OS_TS_GET(); /* Get local time stamp so all tasks get the same time */
229 while (cnt > 0u) { /* Remove all tasks from the pend list */
230 p_pend_data = p_pend_list->HeadPtr;
231 p_tcb = p_pend_data->TCBPtr;
232 OS_PendObjDel((OS_PEND_OBJ *)((void *)p_grp),
233 p_tcb,
234 ts);
235 cnt--;
236 }
237 #if OS_CFG_DBG_EN > 0u
238 OS_FlagDbgListRemove(p_grp);
239 #endif
240 OSFlagQty--;
241 OS_FlagClr(p_grp);
242 OS_CRITICAL_EXIT_NO_SCHED();
243 OSSched(); /* Find highest priority task ready to run */
244 *p_err = OS_ERR_NONE;
245 break;
246
247 default:
248 OS_CRITICAL_EXIT();
249 *p_err = OS_ERR_OPT_INVALID;
250 break;
251 }
252 return (nbr_tasks);
253 }
254 #endif
255
256 /*
257 ************************************************************************************************************************
258 * WAIT ON AN EVENT FLAG GROUP
259 *
260 * Description: This function is called to wait for a combination of bits to be set in an event flag group. Your
261 * application can wait for ANY bit to be set or ALL bits to be set.
262 *
263 * Arguments : p_grp is a pointer to the desired event flag group.
264 *
265 * flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to wait for.
266 * The bits you want are specified by setting the corresponding bits in 'flags'.
267 * e.g. if your application wants to wait for bits 0 and 1 then 'flags' would contain 0x03.
268 *
269 * timeout is an optional timeout (in clock ticks) that your task will wait for the
270 * desired bit combination. If you specify 0, however, your task will wait
271 * forever at the specified event flag group or, until a message arrives.
272 *
273 * opt specifies whether you want ALL bits to be set or ANY of the bits to be set.
274 * You can specify the 'ONE' of the following arguments:
275 *
276 * OS_OPT_PEND_FLAG_CLR_ALL You will wait for ALL bits in 'flags' to be clear (0)
277 * OS_OPT_PEND_FLAG_CLR_ANY You will wait for ANY bit in 'flags' to be clear (0)
278 * OS_OPT_PEND_FLAG_SET_ALL You will wait for ALL bits in 'flags' to be set (1)
279 * OS_OPT_PEND_FLAG_SET_ANY You will wait for ANY bit in 'flags' to be set (1)
280 *
281 * You can 'ADD' OS_OPT_PEND_FLAG_CONSUME if you want the event flag to be 'consumed' by
282 * the call. Example, to wait for any flag in a group AND then clear
283 * the flags that are present, set 'wait_opt' to:
284 *
285 * OS_OPT_PEND_FLAG_SET_ANY + OS_OPT_PEND_FLAG_CONSUME
286 *
287 * You can also 'ADD' the type of pend with 'ONE' of the two option:
288 *
289 * OS_OPT_PEND_NON_BLOCKING Task will NOT block if flags are not available
290 * OS_OPT_PEND_BLOCKING Task will block if flags are not available
291 *
292 * p_ts is a pointer to a variable that will receive the timestamp of when the event flag group was
293 * posted, aborted or the event flag group deleted. If you pass a NULL pointer (i.e. (CPU_TS *)0)
294 * then you will not get the timestamp. In other words, passing a NULL pointer is valid and
295 * indicates that you don't need the timestamp.
296 *
297 * p_err is a pointer to an error code and can be:
298 *
299 * OS_ERR_NONE The desired bits have been set within the specified 'timeout'
300 * OS_ERR_OBJ_PTR_NULL If 'p_grp' is a NULL pointer.
301 * OS_ERR_OBJ_TYPE You are not pointing to an event flag group
302 * OS_ERR_OPT_INVALID You didn't specify a proper 'opt' argument.
303 * OS_ERR_PEND_ABORT The wait on the flag was aborted.
304 * OS_ERR_PEND_ISR If you tried to PEND from an ISR
305 * OS_ERR_PEND_WOULD_BLOCK If you specified non-blocking but the flags were not
306 * available.
307 * OS_ERR_SCHED_LOCKED If you called this function when the scheduler is locked
308 * OS_ERR_TIMEOUT The bit(s) have not been set in the specified 'timeout'.
309 *
310 * Returns : The flags in the event flag group that made the task ready or, 0 if a timeout or an error
311 * occurred.
312 ************************************************************************************************************************
313 */
314
315 OS_FLAGS OSFlagPend (OS_FLAG_GRP *p_grp,
316 OS_FLAGS flags,
317 OS_TICK timeout,
318 OS_OPT opt,
319 CPU_TS *p_ts,
320 OS_ERR *p_err)
321 {
322 CPU_BOOLEAN consume;
323 OS_FLAGS flags_rdy;
324 OS_OPT mode;
325 OS_PEND_DATA pend_data;
326 CPU_SR_ALLOC();
327
328
329
330 #ifdef OS_SAFETY_CRITICAL
331 if (p_err == (OS_ERR *)0) {
332 OS_SAFETY_CRITICAL_EXCEPTION();
333 return ((OS_FLAGS)0);
334 }
335 #endif
336
337 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
338 if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from ISR ... */
339 *p_err = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
340 return ((OS_FLAGS)0);
341 }
342 #endif
343
344 #if OS_CFG_ARG_CHK_EN > 0u
345 if (p_grp == (OS_FLAG_GRP *)0) { /* Validate 'p_grp' */
346 *p_err = OS_ERR_OBJ_PTR_NULL;
347 return ((OS_FLAGS)0);
348 }
349 switch (opt) { /* Validate 'opt' */
350 case OS_OPT_PEND_FLAG_CLR_ALL:
351 case OS_OPT_PEND_FLAG_CLR_ANY:
352 case OS_OPT_PEND_FLAG_SET_ALL:
353 case OS_OPT_PEND_FLAG_SET_ANY:
354 case OS_OPT_PEND_FLAG_CLR_ALL | OS_OPT_PEND_FLAG_CONSUME:
355 case OS_OPT_PEND_FLAG_CLR_ANY | OS_OPT_PEND_FLAG_CONSUME:
356 case OS_OPT_PEND_FLAG_SET_ALL | OS_OPT_PEND_FLAG_CONSUME:
357 case OS_OPT_PEND_FLAG_SET_ANY | OS_OPT_PEND_FLAG_CONSUME:
358 case OS_OPT_PEND_FLAG_CLR_ALL | OS_OPT_PEND_NON_BLOCKING:
359 case OS_OPT_PEND_FLAG_CLR_ANY | OS_OPT_PEND_NON_BLOCKING:
360 case OS_OPT_PEND_FLAG_SET_ALL | OS_OPT_PEND_NON_BLOCKING:
361 case OS_OPT_PEND_FLAG_SET_ANY | OS_OPT_PEND_NON_BLOCKING:
362 case OS_OPT_PEND_FLAG_CLR_ALL | OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_NON_BLOCKING:
363 case OS_OPT_PEND_FLAG_CLR_ANY | OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_NON_BLOCKING:
364 case OS_OPT_PEND_FLAG_SET_ALL | OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_NON_BLOCKING:
365 case OS_OPT_PEND_FLAG_SET_ANY | OS_OPT_PEND_FLAG_CONSUME | OS_OPT_PEND_NON_BLOCKING:
366 break;
367
368 default:
369 *p_err = OS_ERR_OPT_INVALID;
370 return ((OS_OBJ_QTY)0);
371 }
372 #endif
373
374 #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
375 if (p_grp->Type != OS_OBJ_TYPE_FLAG) { /* Validate that we are pointing at an event flag */
376 *p_err = OS_ERR_OBJ_TYPE;
377 return ((OS_FLAGS)0);
378 }
379 #endif
380
381 if ((opt & OS_OPT_PEND_FLAG_CONSUME) != (OS_OPT)0) { /* See if we need to consume the flags */
382 consume = DEF_TRUE;
383 } else {
384 consume = DEF_FALSE;
385 }
386
387 if (p_ts != (CPU_TS *)0) {
388 *p_ts = (CPU_TS)0; /* Initialize the returned timestamp */
389 }
390
391 mode = opt & OS_OPT_PEND_FLAG_MASK;
392 CPU_CRITICAL_ENTER();
393 switch (mode) {
394 case OS_OPT_PEND_FLAG_SET_ALL: /* See if all required flags are set */
395 flags_rdy = (OS_FLAGS)(p_grp->Flags & flags); /* Extract only the bits we want */
396 if (flags_rdy == flags) { /* Must match ALL the bits that we want */
397 if (consume == DEF_TRUE) { /* See if we need to consume the flags */
398 p_grp->Flags &= ~flags_rdy; /* Clear ONLY the flags that we wanted */
399 }
400 OSTCBCurPtr->FlagsRdy = flags_rdy; /* Save flags that were ready */
401 if (p_ts != (CPU_TS *)0) {
402 *p_ts = p_grp->TS;
403 }
404 CPU_CRITICAL_EXIT(); /* Yes, condition met, return to caller */
405 *p_err = OS_ERR_NONE;
406 return (flags_rdy);
407 } else { /* Block task until events occur or timeout */
408 if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) {
409 CPU_CRITICAL_EXIT();
410 *p_err = OS_ERR_PEND_WOULD_BLOCK; /* Specified non-blocking so task would block */
411 return ((OS_FLAGS)0);
412 } else { /* Specified blocking so check is scheduler is locked */
413 if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* See if called with scheduler locked ... */
414 CPU_CRITICAL_EXIT();
415 *p_err = OS_ERR_SCHED_LOCKED; /* ... can't PEND when locked */
416 return ((OS_FLAGS)0);
417 }
418 }
419
420 OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
421 OS_FlagBlock(&pend_data,
422 p_grp,
423 flags,
424 opt,
425 timeout);
426 OS_CRITICAL_EXIT_NO_SCHED();
427 }
428 break;
429
430 case OS_OPT_PEND_FLAG_SET_ANY:
431 flags_rdy = (OS_FLAGS)(p_grp->Flags & flags); /* Extract only the bits we want */
432 if (flags_rdy != (OS_FLAGS)0) { /* See if any flag set */
433 if (consume == DEF_TRUE) { /* See if we need to consume the flags */
434 p_grp->Flags &= ~flags_rdy; /* Clear ONLY the flags that we got */
435 }
436 OSTCBCurPtr->FlagsRdy = flags_rdy; /* Save flags that were ready */
437 if (p_ts != (CPU_TS *)0) {
438 *p_ts = p_grp->TS;
439 }
440 CPU_CRITICAL_EXIT(); /* Yes, condition met, return to caller */
441 *p_err = OS_ERR_NONE;
442 return (flags_rdy);
443 } else { /* Block task until events occur or timeout */
444 if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) {
445 CPU_CRITICAL_EXIT();
446 *p_err = OS_ERR_PEND_WOULD_BLOCK; /* Specified non-blocking so task would block */
447 return ((OS_FLAGS)0);
448 } else { /* Specified blocking so check is scheduler is locked */
449 if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* See if called with scheduler locked ... */
450 CPU_CRITICAL_EXIT();
451 *p_err = OS_ERR_SCHED_LOCKED; /* ... can't PEND when locked */
452 return ((OS_FLAGS)0);
453 }
454 }
455
456 OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
457 OS_FlagBlock(&pend_data,
458 p_grp,
459 flags,
460 opt,
461 timeout);
462 OS_CRITICAL_EXIT_NO_SCHED();
463 }
464 break;
465
466 #if OS_CFG_FLAG_MODE_CLR_EN > 0u
467 case OS_OPT_PEND_FLAG_CLR_ALL: /* See if all required flags are cleared */
468 flags_rdy = (OS_FLAGS)(~p_grp->Flags & flags); /* Extract only the bits we want */
469 if (flags_rdy == flags) { /* Must match ALL the bits that we want */
470 if (consume == DEF_TRUE) { /* See if we need to consume the flags */
471 p_grp->Flags |= flags_rdy; /* Set ONLY the flags that we wanted */
472 }
473 OSTCBCurPtr->FlagsRdy = flags_rdy; /* Save flags that were ready */
474 if (p_ts != (CPU_TS *)0) {
475 *p_ts = p_grp->TS;
476 }
477 CPU_CRITICAL_EXIT(); /* Yes, condition met, return to caller */
478 *p_err = OS_ERR_NONE;
479 return (flags_rdy);
480 } else { /* Block task until events occur or timeout */
481 if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) {
482 CPU_CRITICAL_EXIT();
483 *p_err = OS_ERR_PEND_WOULD_BLOCK; /* Specified non-blocking so task would block */
484 return ((OS_FLAGS)0);
485 } else { /* Specified blocking so check is scheduler is locked */
486 if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* See if called with scheduler locked ... */
487 CPU_CRITICAL_EXIT();
488 *p_err = OS_ERR_SCHED_LOCKED; /* ... can't PEND when locked */
489 return ((OS_FLAGS)0);
490 }
491 }
492
493 OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
494 OS_FlagBlock(&pend_data,
495 p_grp,
496 flags,
497 opt,
498 timeout);
499 OS_CRITICAL_EXIT_NO_SCHED();
500 }
501 break;
502
503 case OS_OPT_PEND_FLAG_CLR_ANY:
504 flags_rdy = (OS_FLAGS)(~p_grp->Flags & flags); /* Extract only the bits we want */
505 if (flags_rdy != (OS_FLAGS)0) { /* See if any flag cleared */
506 if (consume == DEF_TRUE) { /* See if we need to consume the flags */
507 p_grp->Flags |= flags_rdy; /* Set ONLY the flags that we got */
508 }
509 OSTCBCurPtr->FlagsRdy = flags_rdy; /* Save flags that were ready */
510 if (p_ts != (CPU_TS *)0) {
511 *p_ts = p_grp->TS;
512 }
513 CPU_CRITICAL_EXIT(); /* Yes, condition met, return to caller */
514 *p_err = OS_ERR_NONE;
515 return (flags_rdy);
516 } else { /* Block task until events occur or timeout */
517 if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) {
518 CPU_CRITICAL_EXIT();
519 *p_err = OS_ERR_PEND_WOULD_BLOCK; /* Specified non-blocking so task would block */
520 return ((OS_FLAGS)0);
521 } else { /* Specified blocking so check is scheduler is locked */
522 if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* See if called with scheduler locked ... */
523 CPU_CRITICAL_EXIT();
524 *p_err = OS_ERR_SCHED_LOCKED; /* ... can't PEND when locked */
525 return ((OS_FLAGS)0);
526 }
527 }
528
529 OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT(); /* Lock the scheduler/re-enable interrupts */
530 OS_FlagBlock(&pend_data,
531 p_grp,
532 flags,
533 opt,
534 timeout);
535 OS_CRITICAL_EXIT_NO_SCHED();
536 }
537 break;
538 #endif
539
540 default:
541 CPU_CRITICAL_EXIT();
542 *p_err = OS_ERR_OPT_INVALID;
543 return ((OS_FLAGS)0);
544 }
545
546 OSSched(); /* Find next HPT ready to run */
547
548 CPU_CRITICAL_ENTER();
549 switch (OSTCBCurPtr->PendStatus) {
550 case OS_STATUS_PEND_OK: /* We got the vent flags */
551 if (p_ts != (CPU_TS *)0) {
552 *p_ts = OSTCBCurPtr->TS;
553 }
554 *p_err = OS_ERR_NONE;
555 break;
556
557 case OS_STATUS_PEND_ABORT: /* Indicate that we aborted */
558 if (p_ts != (CPU_TS *)0) {
559 *p_ts = OSTCBCurPtr->TS;
560 }
561 CPU_CRITICAL_EXIT();
562 *p_err = OS_ERR_PEND_ABORT;
563 return ((OS_FLAGS)0);
564
565 case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get semaphore within timeout */
566 if (p_ts != (CPU_TS *)0) {
567 *p_ts = (CPU_TS )0;
568 }
569 CPU_CRITICAL_EXIT();
570 *p_err = OS_ERR_TIMEOUT;
571 return ((OS_FLAGS)0);
572
573 case OS_STATUS_PEND_DEL: /* Indicate that object pended on has been deleted */
574 if (p_ts != (CPU_TS *)0) {
575 *p_ts = OSTCBCurPtr->TS;
576 }
577 CPU_CRITICAL_EXIT();
578 *p_err = OS_ERR_OBJ_DEL;
579 return ((OS_FLAGS)0);
580
581 default:
582 CPU_CRITICAL_EXIT();
583 *p_err = OS_ERR_STATUS_INVALID;
584 return ((OS_FLAGS)0);
585 }
586
587 flags_rdy = OSTCBCurPtr->FlagsRdy;
588 if (consume == DEF_TRUE) { /* See if we need to consume the flags */
589 switch (mode) {
590 case OS_OPT_PEND_FLAG_SET_ALL:
591 case OS_OPT_PEND_FLAG_SET_ANY: /* Clear ONLY the flags we got */
592 p_grp->Flags &= ~flags_rdy;
593 break;
594
595 #if OS_CFG_FLAG_MODE_CLR_EN > 0u
596 case OS_OPT_PEND_FLAG_CLR_ALL:
597 case OS_OPT_PEND_FLAG_CLR_ANY: /* Set ONLY the flags we got */
598 p_grp->Flags |= flags_rdy;
599 break;
600 #endif
601 default:
602 CPU_CRITICAL_EXIT();
603 *p_err = OS_ERR_OPT_INVALID;
604 return ((OS_FLAGS)0);
605 }
606 }
607 CPU_CRITICAL_EXIT();
608 *p_err = OS_ERR_NONE; /* Event(s) must have occurred */
609 return (flags_rdy);
610 }
611
612 /*$PAGE*/
613 /*
614 ************************************************************************************************************************
615 * ABORT WAITING ON AN EVENT FLAG GROUP
616 *
617 * Description: This function aborts & readies any tasks currently waiting on an event flag group. This function should
618 * be used to fault-abort the wait on the event flag group, rather than to normally post to the event flag
619 * group OSFlagPost().
620 *
621 * Arguments : p_grp is a pointer to the event flag group
622 *
623 * opt determines the type of ABORT performed:
624 *
625 * OS_OPT_PEND_ABORT_1 ABORT wait for a single task (HPT) waiting on the event flag
626 * OS_OPT_PEND_ABORT_ALL ABORT wait for ALL tasks that are waiting on the event flag
627 * OS_OPT_POST_NO_SCHED Do not call the scheduler
628 *
629 * p_err is a pointer to a variable that will contain an error code returned by this function.
630 *
631 * OS_ERR_NONE At least one task waiting on the event flag group and was
632 * readied and informed of the aborted wait; check return value
633 * for the number of tasks whose wait on the event flag group
634 * was aborted.
635 * OS_ERR_OBJ_PTR_NULL If 'p_grp' is a NULL pointer.
636 * OS_ERR_OBJ_TYPE If 'p_grp' is not pointing at an event flag group
637 * OS_ERR_OPT_INVALID If you specified an invalid option
638 * OS_ERR_PEND_ABORT_ISR If you called this function from an ISR
639 * OS_ERR_PEND_ABORT_NONE No task were pending
640 *
641 * Returns : == 0 if no tasks were waiting on the event flag group, or upon error.
642 * > 0 if one or more tasks waiting on the event flag group are now readied and informed.
643 ************************************************************************************************************************
644 */
645
646 #if OS_CFG_FLAG_PEND_ABORT_EN > 0u
647 OS_OBJ_QTY OSFlagPendAbort (OS_FLAG_GRP *p_grp,
648 OS_OPT opt,
649 OS_ERR *p_err)
650 {
651 OS_PEND_LIST *p_pend_list;
652 OS_TCB *p_tcb;
653 CPU_TS ts;
654 OS_OBJ_QTY nbr_tasks;
655 CPU_SR_ALLOC();
656
657
658
659 #ifdef OS_SAFETY_CRITICAL
660 if (p_err == (OS_ERR *)0) {
661 OS_SAFETY_CRITICAL_EXCEPTION();
662 return ((OS_OBJ_QTY)0u);
663 }
664 #endif
665
666 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
667 if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to Pend Abort from an ISR */
668 *p_err = OS_ERR_PEND_ABORT_ISR;
669 return ((OS_OBJ_QTY)0u);
670 }
671 #endif
672
673 #if OS_CFG_ARG_CHK_EN > 0u
674 if (p_grp == (OS_FLAG_GRP *)0) { /* Validate 'p_grp' */
675 *p_err = OS_ERR_OBJ_PTR_NULL;
676 return ((OS_OBJ_QTY)0u);
677 }
678 switch (opt) { /* Validate 'opt' */
679 case OS_OPT_PEND_ABORT_1:
680 case OS_OPT_PEND_ABORT_ALL:
681 case OS_OPT_PEND_ABORT_1 | OS_OPT_POST_NO_SCHED:
682 case OS_OPT_PEND_ABORT_ALL | OS_OPT_POST_NO_SCHED:
683 break;
684
685 default:
686 *p_err = OS_ERR_OPT_INVALID;
687 return ((OS_OBJ_QTY)0u);
688 }
689 #endif
690
691 #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
692 if (p_grp->Type != OS_OBJ_TYPE_FLAG) { /* Make sure event flag group was created */
693 *p_err = OS_ERR_OBJ_TYPE;
694 return ((OS_OBJ_QTY)0u);
695 }
696 #endif
697
698 CPU_CRITICAL_ENTER();
699 p_pend_list = &p_grp->PendList;
700 if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0u) { /* Any task waiting on flag group? */
701 CPU_CRITICAL_EXIT(); /* No */
702 *p_err = OS_ERR_PEND_ABORT_NONE;
703 return ((OS_OBJ_QTY)0u);
704 }
705
706 OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT();
707 nbr_tasks = 0u;
708 ts = OS_TS_GET(); /* Get local time stamp so all tasks get the same time */
709 while (p_pend_list->NbrEntries > (OS_OBJ_QTY)0u) {
710 p_tcb = p_pend_list->HeadPtr->TCBPtr;
711 OS_PendAbort((OS_PEND_OBJ *)((void *)p_grp),
712 p_tcb,
713 ts);
714 nbr_tasks++;
715 if (opt != OS_OPT_PEND_ABORT_ALL) { /* Pend abort all tasks waiting? */
716 break; /* No */
717 }
718 }
719 OS_CRITICAL_EXIT_NO_SCHED();
720
721 if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0u) {
722 OSSched(); /* Run the scheduler */
723 }
724
725 *p_err = OS_ERR_NONE;
726 return (nbr_tasks);
727 }
728 #endif
729
730 /*$PAGE*/
731 /*
732 ************************************************************************************************************************
733 * GET FLAGS WHO CAUSED TASK TO BECOME READY
734 *
735 * Description: This function is called to obtain the flags that caused the task to become ready to run.
736 * In other words, this function allows you to tell "Who done it!".
737 *
738 * Arguments : p_err is a pointer to an error code
739 *
740 * OS_ERR_NONE if the call was successful
741 * OS_ERR_PEND_ISR if called from an ISR
742 *
743 * Returns : The flags that caused the task to be ready.
744 ************************************************************************************************************************
745 */
746
747 OS_FLAGS OSFlagPendGetFlagsRdy (OS_ERR *p_err)
748 {
749 OS_FLAGS flags;
750 CPU_SR_ALLOC();
751
752
753
754 #ifdef OS_SAFETY_CRITICAL
755 if (p_err == (OS_ERR *)0) {
756 OS_SAFETY_CRITICAL_EXCEPTION();
757 return ((OS_FLAGS)0);
758 }
759 #endif
760
761 #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
762 if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from ISR ... */
763 *p_err = OS_ERR_PEND_ISR; /* ... can't get from an ISR */
764 return ((OS_FLAGS)0);
765 }
766 #endif
767
768 CPU_CRITICAL_ENTER();
769 flags = OSTCBCurPtr->FlagsRdy;
770 CPU_CRITICAL_EXIT();
771 *p_err = OS_ERR_NONE;
772 return (flags);
773 }
774
775 /*$PAGE*/
776 /*
777 ************************************************************************************************************************
778 * POST EVENT FLAG BIT(S)
779 *
780 * Description: This function is called to set or clear some bits in an event flag group. The bits to set or clear are
781 * specified by a 'bit mask'.
782 *
783 * Arguments : p_grp is a pointer to the desired event flag group.
784 *
785 * flags If 'opt' (see below) is OS_OPT_POST_FLAG_SET, each bit that is set in 'flags' will
786 * set the corresponding bit in the event flag group. e.g. to set bits 0, 4
787 * and 5 you would set 'flags' to:
788 *
789 * 0x31 (note, bit 0 is least significant bit)
790 *
791 * If 'opt' (see below) is OS_OPT_POST_FLAG_CLR, each bit that is set in 'flags' will
792 * CLEAR the corresponding bit in the event flag group. e.g. to clear bits 0,
793 * 4 and 5 you would specify 'flags' as:
794 *
795 * 0x31 (note, bit 0 is least significant bit)
796 *
797 * opt indicates whether the flags will be:
798 *
799 * OS_OPT_POST_FLAG_SET set
800 * OS_OPT_POST_FLAG_CLR cleared
801 *
802 * you can also 'add' OS_OPT_POST_NO_SCHED to prevent the scheduler from being called.
803 *
804 * p_err is a pointer to an error code and can be:
805 *
806 * OS_ERR_NONE The call was successful
807 * OS_ERR_OBJ_PTR_NULL You passed a NULL pointer
808 * OS_ERR_OBJ_TYPE You are not pointing to an event flag group
809 * OS_ERR_OPT_INVALID You specified an invalid option
810 *
811 * Returns : the new value of the event flags bits that are still set.
812 *
813 * Note(s) : 1) The execution time of this function depends on the number of tasks waiting on the event flag group.
814 ************************************************************************************************************************
815 */
816
817 OS_FLAGS OSFlagPost (OS_FLAG_GRP *p_grp,
818 OS_FLAGS flags,
819 OS_OPT opt,
820 OS_ERR *p_err)
821 {
822 OS_FLAGS flags_cur;
823 CPU_TS ts;
824
825
826
827 #ifdef OS_SAFETY_CRITICAL
828 if (p_err == (OS_ERR *)0) {
829 OS_SAFETY_CRITICAL_EXCEPTION();
830 return ((OS_FLAGS)0);
831 }
832 #endif
833
834 #if OS_CFG_ARG_CHK_EN > 0u
835 if (p_grp == (OS_FLAG_GRP *)0) { /* Validate 'p_grp' */
836 *p_err = OS_ERR_OBJ_PTR_NULL;
837 return ((OS_FLAGS)0);
838 }
839 switch (opt) { /* Validate 'opt' */
840 case OS_OPT_POST_FLAG_SET:
841 case OS_OPT_POST_FLAG_CLR:
842 case OS_OPT_POST_FLAG_SET | OS_OPT_POST_NO_SCHED:
843 case OS_OPT_POST_FLAG_CLR | OS_OPT_POST_NO_SCHED:
844 break;
845
846 default:
847 *p_err = OS_ERR_OPT_INVALID;
848 return ((OS_FLAGS)0);
849 }
850 #endif
851
852 #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
853 if (p_grp->Type != OS_OBJ_TYPE_FLAG) { /* Make sure we are pointing to an event flag grp */
854 *p_err = OS_ERR_OBJ_TYPE;
855 return ((OS_FLAGS)0);
856 }
857 #endif
858
859 ts = OS_TS_GET(); /* Get timestamp */
860 #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
861 if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from an ISR */
862 OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_FLAG, /* Post to ISR queue */
863 (void *)p_grp,
864 (void *)0,
865 (OS_MSG_SIZE)0,
866 (OS_FLAGS )flags,
867 (OS_OPT )opt,
868 (CPU_TS )ts,
869 (OS_ERR *)p_err);
870 return ((OS_FLAGS)0);
871 }
872 #endif
873
874 flags_cur = OS_FlagPost(p_grp,
875 flags,
876 opt,
877 ts,
878 p_err);
879
880 return (flags_cur);
881 }
882
883 /*$PAGE*/
884 /*
885 ************************************************************************************************************************
886 * SUSPEND TASK UNTIL EVENT FLAG(s) RECEIVED OR TIMEOUT OCCURS
887 *
888 * Description: This function is internal to uC/OS-III and is used to put a task to sleep until the desired
889 * event flag bit(s) are set.
890 *
891 * Arguments : p_pend_data is a pointer to an object used to link the task being blocked to the list of task(s)
892 * ----------- pending on the desired event flag group.
893 *
894 * p_grp is a pointer to the desired event flag group.
895 * -----
896 *
897 * flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to check.
898 * The bits you want are specified by setting the corresponding bits in
899 * 'flags'. e.g. if your application wants to wait for bits 0 and 1 then
900 * 'flags' would contain 0x03.
901 *
902 * opt specifies whether you want ALL bits to be set/cleared or ANY of the bits
903 * to be set/cleared.
904 * You can specify the following argument:
905 *
906 * OS_OPT_PEND_FLAG_CLR_ALL You will check ALL bits in 'mask' to be clear (0)
907 * OS_OPT_PEND_FLAG_CLR_ANY You will check ANY bit in 'mask' to be clear (0)
908 * OS_OPT_PEND_FLAG_SET_ALL You will check ALL bits in 'mask' to be set (1)
909 * OS_OPT_PEND_FLAG_SET_ANY You will check ANY bit in 'mask' to be set (1)
910 *
911 * timeout is the desired amount of time that the task will wait for the event flag
912 * bit(s) to be set.
913 *
914 * Returns : none
915 *
916 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
917 ************************************************************************************************************************
918 */
919
920 void OS_FlagBlock (OS_PEND_DATA *p_pend_data,
921 OS_FLAG_GRP *p_grp,
922 OS_FLAGS flags,
923 OS_OPT opt,
924 OS_TICK timeout)
925 {
926 OSTCBCurPtr->FlagsPend = flags; /* Save the flags that we need to wait for */
927 OSTCBCurPtr->FlagsOpt = opt; /* Save the type of wait we are doing */
928 OSTCBCurPtr->FlagsRdy = (OS_FLAGS)0;
929
930 OS_Pend(p_pend_data,
931 (OS_PEND_OBJ *)((void *)p_grp),
932 OS_TASK_PEND_ON_FLAG,
933 timeout);
934 }
935
936 /*$PAGE*/
937 /*
938 ************************************************************************************************************************
939 * CLEAR THE CONTENTS OF AN EVENT FLAG GROUP
940 *
941 * Description: This function is called by OSFlagDel() to clear the contents of an event flag group
942 *
943
944 * Argument(s): p_grp is a pointer to the event flag group to clear
945 * -----
946 *
947 * Returns : none
948 *
949 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
950 ************************************************************************************************************************
951 */
952
953 void OS_FlagClr (OS_FLAG_GRP *p_grp)
954 {
955 OS_PEND_LIST *p_pend_list;
956
957
958
959 p_grp->Type = OS_OBJ_TYPE_NONE;
960 p_grp->NamePtr = (CPU_CHAR *)((void *)"?FLAG"); /* Unknown name */
961 p_grp->Flags = (OS_FLAGS )0;
962 p_pend_list = &p_grp->PendList;
963 OS_PendListInit(p_pend_list);
964 }
965
966 /*$PAGE*/
967 /*
968 ************************************************************************************************************************
969 * INITIALIZE THE EVENT FLAG MODULE
970 *
971 * Description: This function is called by uC/OS-III to initialize the event flag module. Your application MUST NOT call
972 * this function. In other words, this function is internal to uC/OS-III.
973 *
974 * Arguments : p_err is a pointer to an error code that can contain one of the following values:
975 *
976 * OS_ERR_NONE The call was successful.
977 *
978 * Returns : none
979 *
980 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
981 ************************************************************************************************************************
982 */
983
984 void OS_FlagInit (OS_ERR *p_err)
985 {
986 #ifdef OS_SAFETY_CRITICAL
987 if (p_err == (OS_ERR *)0) {
988 OS_SAFETY_CRITICAL_EXCEPTION();
989 return;
990 }
991 #endif
992
993 #if OS_CFG_DBG_EN > 0u
994 OSFlagDbgListPtr = (OS_FLAG_GRP *)0;
995 #endif
996
997 OSFlagQty = (OS_OBJ_QTY )0;
998 *p_err = OS_ERR_NONE;
999 }
1000
1001 /*$PAGE*/
1002 /*
1003 ************************************************************************************************************************
1004 * ADD/REMOVE EVENT FLAG GROUP TO/FROM DEBUG LIST
1005 *
1006 * Description: These functions are called by uC/OS-III to add or remove an event flag group from the event flag debug
1007 * list.
1008 *
1009 * Arguments : p_grp is a pointer to the event flag group to add/remove
1010 *
1011 * Returns : none
1012 *
1013 * Note(s) : These functions are INTERNAL to uC/OS-III and your application should not call it.
1014 ************************************************************************************************************************
1015 */
1016
1017 #if OS_CFG_DBG_EN > 0u
1018 void OS_FlagDbgListAdd (OS_FLAG_GRP *p_grp)
1019 {
1020 p_grp->DbgNamePtr = (CPU_CHAR *)((void *)" ");
1021 p_grp->DbgPrevPtr = (OS_FLAG_GRP *)0;
1022 if (OSFlagDbgListPtr == (OS_FLAG_GRP *)0) {
1023 p_grp->DbgNextPtr = (OS_FLAG_GRP *)0;
1024 } else {
1025 p_grp->DbgNextPtr = OSFlagDbgListPtr;
1026 OSFlagDbgListPtr->DbgPrevPtr = p_grp;
1027 }
1028 OSFlagDbgListPtr = p_grp;
1029 }
1030
1031
1032
1033 void OS_FlagDbgListRemove (OS_FLAG_GRP *p_grp)
1034 {
1035 OS_FLAG_GRP *p_grp_next;
1036 OS_FLAG_GRP *p_grp_prev;
1037
1038
1039 p_grp_prev = p_grp->DbgPrevPtr;
1040 p_grp_next = p_grp->DbgNextPtr;
1041
1042 if (p_grp_prev == (OS_FLAG_GRP *)0) {
1043 OSFlagDbgListPtr = p_grp_next;
1044 if (p_grp_next != (OS_FLAG_GRP *)0) {
1045 p_grp_next->DbgPrevPtr = (OS_FLAG_GRP *)0;
1046 }
1047 p_grp->DbgNextPtr = (OS_FLAG_GRP *)0;
1048
1049 } else if (p_grp_next == (OS_FLAG_GRP *)0) {
1050 p_grp_prev->DbgNextPtr = (OS_FLAG_GRP *)0;
1051 p_grp->DbgPrevPtr = (OS_FLAG_GRP *)0;
1052
1053 } else {
1054 p_grp_prev->DbgNextPtr = p_grp_next;
1055 p_grp_next->DbgPrevPtr = p_grp_prev;
1056 p_grp->DbgNextPtr = (OS_FLAG_GRP *)0;
1057 p_grp->DbgPrevPtr = (OS_FLAG_GRP *)0;
1058 }
1059 }
1060 #endif
1061
1062 /*$PAGE*/
1063 /*
1064 ************************************************************************************************************************
1065 * POST EVENT FLAG BIT(S)
1066 *
1067 * Description: This function is called to set or clear some bits in an event flag group. The bits to set or clear are
1068 * specified by a 'bit mask'.
1069 *
1070 * Arguments : p_grp is a pointer to the desired event flag group.
1071 *
1072 * flags If 'opt' (see below) is OS_OPT_POST_FLAG_SET, each bit that is set in 'flags' will
1073 * set the corresponding bit in the event flag group. e.g. to set bits 0, 4
1074 * and 5 you would set 'flags' to:
1075 *
1076 * 0x31 (note, bit 0 is least significant bit)
1077 *
1078 * If 'opt' (see below) is OS_OPT_POST_FLAG_CLR, each bit that is set in 'flags' will
1079 * CLEAR the corresponding bit in the event flag group. e.g. to clear bits 0,
1080 * 4 and 5 you would specify 'flags' as:
1081 *
1082 * 0x31 (note, bit 0 is least significant bit)
1083 *
1084 * opt indicates whether the flags will be:
1085 *
1086 * OS_OPT_POST_FLAG_SET set
1087 * OS_OPT_POST_FLAG_CLR cleared
1088 *
1089 * you can also 'add' OS_OPT_POST_NO_SCHED to prevent the scheduler from being called.
1090 *
1091 * ts is the timestamp of the post
1092 *
1093 * p_err is a pointer to an error code and can be:
1094 *
1095 * OS_ERR_NONE The call was successful
1096 * OS_ERR_OBJ_PTR_NULL You passed a NULL pointer
1097 * OS_ERR_OBJ_TYPE You are not pointing to an event flag group
1098 * OS_ERR_OPT_INVALID You specified an invalid option
1099 *
1100 * Returns : the new value of the event flags bits that are still set.
1101 *
1102 * Note(s) : 1) The execution time of this function depends on the number of tasks waiting on the event flag group.
1103 ************************************************************************************************************************
1104 */
1105
1106 OS_FLAGS OS_FlagPost (OS_FLAG_GRP *p_grp,
1107 OS_FLAGS flags,
1108 OS_OPT opt,
1109 CPU_TS ts,
1110 OS_ERR *p_err)
1111 {
1112 OS_FLAGS flags_cur;
1113 OS_FLAGS flags_rdy;
1114 OS_OPT mode;
1115 OS_PEND_DATA *p_pend_data;
1116 OS_PEND_DATA *p_pend_data_next;
1117 OS_PEND_LIST *p_pend_list;
1118 OS_TCB *p_tcb;
1119 CPU_SR_ALLOC();
1120
1121
1122
1123 CPU_CRITICAL_ENTER();
1124 switch (opt) {
1125 case OS_OPT_POST_FLAG_SET:
1126 case OS_OPT_POST_FLAG_SET | OS_OPT_POST_NO_SCHED:
1127 p_grp->Flags |= flags; /* Set the flags specified in the group */
1128 break;
1129
1130 case OS_OPT_POST_FLAG_CLR:
1131 case OS_OPT_POST_FLAG_CLR | OS_OPT_POST_NO_SCHED:
1132 p_grp->Flags &= ~flags; /* Clear the flags specified in the group */
1133 break;
1134
1135 default:
1136 CPU_CRITICAL_EXIT(); /* INVALID option */
1137 *p_err = OS_ERR_OPT_INVALID;
1138 return ((OS_FLAGS)0);
1139 }
1140 p_grp->TS = ts;
1141 p_pend_list = &p_grp->PendList;
1142 if (p_pend_list->NbrEntries == 0u) { /* Any task waiting on event flag group? */
1143 CPU_CRITICAL_EXIT(); /* No */
1144 *p_err = OS_ERR_NONE;
1145 return (p_grp->Flags);
1146 }
1147
1148 OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT();
1149 p_pend_data = p_pend_list->HeadPtr;
1150 p_tcb = p_pend_data->TCBPtr;
1151 while (p_tcb != (OS_TCB *)0) { /* Go through all tasks waiting on event flag(s) */
1152 p_pend_data_next = p_pend_data->NextPtr;
1153 mode = p_tcb->FlagsOpt & OS_OPT_PEND_FLAG_MASK;
1154 switch (mode) {
1155 case OS_OPT_PEND_FLAG_SET_ALL: /* See if all req. flags are set for current node */
1156 flags_rdy = (OS_FLAGS)(p_grp->Flags & p_tcb->FlagsPend);
1157 if (flags_rdy == p_tcb->FlagsPend) {
1158 OS_FlagTaskRdy(p_tcb, /* Make task RTR, event(s) Rx'd */
1159 flags_rdy,
1160 ts);
1161 }
1162 break;
1163
1164 case OS_OPT_PEND_FLAG_SET_ANY: /* See if any flag set */
1165 flags_rdy = (OS_FLAGS)(p_grp->Flags & p_tcb->FlagsPend);
1166 if (flags_rdy != (OS_FLAGS)0) {
1167 OS_FlagTaskRdy(p_tcb, /* Make task RTR, event(s) Rx'd */
1168 flags_rdy,
1169 ts);
1170 }
1171 break;
1172
1173 #if OS_CFG_FLAG_MODE_CLR_EN > 0u
1174 case OS_OPT_PEND_FLAG_CLR_ALL: /* See if all req. flags are set for current node */
1175 flags_rdy = (OS_FLAGS)(~p_grp->Flags & p_tcb->FlagsPend);
1176 if (flags_rdy == p_tcb->FlagsPend) {
1177 OS_FlagTaskRdy(p_tcb, /* Make task RTR, event(s) Rx'd */
1178 flags_rdy,
1179 ts);
1180 }
1181 break;
1182
1183 case OS_OPT_PEND_FLAG_CLR_ANY: /* See if any flag set */
1184 flags_rdy = (OS_FLAGS)(~p_grp->Flags & p_tcb->FlagsPend);
1185 if (flags_rdy != (OS_FLAGS)0) {
1186 OS_FlagTaskRdy(p_tcb, /* Make task RTR, event(s) Rx'd */
1187 flags_rdy,
1188 ts);
1189 }
1190 break;
1191 #endif
1192 default:
1193 OS_CRITICAL_EXIT();
1194 *p_err = OS_ERR_FLAG_PEND_OPT;
1195 return ((OS_FLAGS)0);
1196 }
1197 p_pend_data = p_pend_data_next; /* Point to next task waiting for event flag(s) */
1198 if (p_pend_data != (OS_PEND_DATA *)0) {
1199 p_tcb = p_pend_data->TCBPtr;
1200 } else {
1201 p_tcb = (OS_TCB *)0;
1202 }
1203 }
1204 OS_CRITICAL_EXIT_NO_SCHED();
1205
1206 if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0) {
1207 OSSched();
1208 }
1209
1210 CPU_CRITICAL_ENTER();
1211 flags_cur = p_grp->Flags;
1212 CPU_CRITICAL_EXIT();
1213 *p_err = OS_ERR_NONE;
1214 return (flags_cur);
1215 }
1216
1217 /*$PAGE*/
1218 /*
1219 ************************************************************************************************************************
1220 * MAKE TASK READY-TO-RUN, EVENT(s) OCCURRED
1221 *
1222 * Description: This function is internal to uC/OS-III and is used to make a task ready-to-run because the desired event
1223 * flag bits have been set.
1224 *
1225 * Arguments : p_tcb is a pointer to the OS_TCB of the task to remove
1226 * -----
1227 *
1228 * flags_rdy contains the bit pattern of the event flags that cause the task to become ready-to-run.
1229 *
1230 * ts is a timestamp associated with the post
1231 *
1232 * Returns : none
1233 *
1234 * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
1235 ************************************************************************************************************************
1236 */
1237
1238 void OS_FlagTaskRdy (OS_TCB *p_tcb,
1239 OS_FLAGS flags_rdy,
1240 CPU_TS ts)
1241 {
1242 p_tcb->FlagsRdy = flags_rdy;
1243 p_tcb->PendStatus = OS_STATUS_PEND_OK; /* Clear pend status */
1244 p_tcb->PendOn = OS_TASK_PEND_ON_NOTHING; /* Indicate no longer pending */
1245 p_tcb->TS = ts;
1246 switch (p_tcb->TaskState) {
1247 case OS_TASK_STATE_RDY:
1248 case OS_TASK_STATE_DLY:
1249 case OS_TASK_STATE_DLY_SUSPENDED:
1250 case OS_TASK_STATE_SUSPENDED:
1251 break;
1252
1253 case OS_TASK_STATE_PEND:
1254 case OS_TASK_STATE_PEND_TIMEOUT:
1255 OS_TaskRdy(p_tcb);
1256 p_tcb->TaskState = OS_TASK_STATE_RDY;
1257 break;
1258
1259 case OS_TASK_STATE_PEND_SUSPENDED:
1260 case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
1261 p_tcb->TaskState = OS_TASK_STATE_SUSPENDED;
1262 break;
1263
1264 default:
1265 break;
1266 }
1267 OS_PendListRemove(p_tcb);
1268 }
1269 #endif