os_flag.c 54 KB

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