os_flag.c 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215
  1. /*
  2. *********************************************************************************************************
  3. * uC/OS-II
  4. * The Real-Time Kernel
  5. * EVENT FLAG MANAGEMENT
  6. *
  7. * (c) Copyright 1992-2009, Micrium, Weston, FL
  8. * All Rights Reserved
  9. *
  10. * File : OS_FLAG.C
  11. * By : Jean J. Labrosse
  12. * Version : V2.91
  13. *
  14. * LICENSING TERMS:
  15. * ---------------
  16. * uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
  17. * If you plan on using uC/OS-II in a commercial product you need to contact Micriµm to properly license
  18. * its use in your product. We provide ALL the source code for your convenience and to help you experience
  19. * uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
  20. * licensing fee.
  21. *********************************************************************************************************
  22. */
  23. #ifndef OS_MASTER_FILE
  24. #include <ucos_ii.h>
  25. #endif
  26. #if (OS_FLAG_EN > 0u) && (OS_MAX_FLAGS > 0u)
  27. /*
  28. *********************************************************************************************************
  29. * LOCAL PROTOTYPES
  30. *********************************************************************************************************
  31. */
  32. static void OS_FlagBlock(OS_FLAG_GRP *pgrp, OS_FLAG_NODE *pnode, OS_FLAGS flags, INT8U wait_type, INT32U timeout);
  33. static BOOLEAN OS_FlagTaskRdy(OS_FLAG_NODE *pnode, OS_FLAGS flags_rdy);
  34. /*$PAGE*/
  35. /*
  36. *********************************************************************************************************
  37. * CHECK THE STATUS OF FLAGS IN AN EVENT FLAG GROUP
  38. *
  39. * Description: This function is called to check the status of a combination of bits to be set or cleared
  40. * in an event flag group. Your application can check for ANY bit to be set/cleared or ALL
  41. * bits to be set/cleared.
  42. *
  43. * This call does not block if the desired flags are not present.
  44. *
  45. * Arguments : pgrp is a pointer to the desired event flag group.
  46. *
  47. * flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to check.
  48. * The bits you want are specified by setting the corresponding bits in
  49. * 'flags'. e.g. if your application wants to wait for bits 0 and 1 then
  50. * 'flags' would contain 0x03.
  51. *
  52. * wait_type specifies whether you want ALL bits to be set/cleared or ANY of the bits
  53. * to be set/cleared.
  54. * You can specify the following argument:
  55. *
  56. * OS_FLAG_WAIT_CLR_ALL You will check ALL bits in 'flags' to be clear (0)
  57. * OS_FLAG_WAIT_CLR_ANY You will check ANY bit in 'flags' to be clear (0)
  58. * OS_FLAG_WAIT_SET_ALL You will check ALL bits in 'flags' to be set (1)
  59. * OS_FLAG_WAIT_SET_ANY You will check ANY bit in 'flags' to be set (1)
  60. *
  61. * NOTE: Add OS_FLAG_CONSUME if you want the event flag to be 'consumed' by
  62. * the call. Example, to wait for any flag in a group AND then clear
  63. * the flags that are present, set 'wait_type' to:
  64. *
  65. * OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME
  66. *
  67. * perr is a pointer to an error code and can be:
  68. * OS_ERR_NONE No error
  69. * OS_ERR_EVENT_TYPE You are not pointing to an event flag group
  70. * OS_ERR_FLAG_WAIT_TYPE You didn't specify a proper 'wait_type' argument.
  71. * OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer instead of the event flag
  72. * group handle.
  73. * OS_ERR_FLAG_NOT_RDY The desired flags you are waiting for are not
  74. * available.
  75. *
  76. * Returns : The flags in the event flag group that made the task ready or, 0 if a timeout or an error
  77. * occurred.
  78. *
  79. * Called from: Task or ISR
  80. *
  81. * Note(s) : 1) IMPORTANT, the behavior of this function has changed from PREVIOUS versions. The
  82. * function NOW returns the flags that were ready INSTEAD of the current state of the
  83. * event flags.
  84. *********************************************************************************************************
  85. */
  86. #if OS_FLAG_ACCEPT_EN > 0u
  87. OS_FLAGS OSFlagAccept (OS_FLAG_GRP *pgrp,
  88. OS_FLAGS flags,
  89. INT8U wait_type,
  90. INT8U *perr)
  91. {
  92. OS_FLAGS flags_rdy;
  93. INT8U result;
  94. BOOLEAN consume;
  95. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  96. OS_CPU_SR cpu_sr = 0u;
  97. #endif
  98. #ifdef OS_SAFETY_CRITICAL
  99. if (perr == (INT8U *)0) {
  100. OS_SAFETY_CRITICAL_EXCEPTION();
  101. }
  102. #endif
  103. #if OS_ARG_CHK_EN > 0u
  104. if (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */
  105. *perr = OS_ERR_FLAG_INVALID_PGRP;
  106. return ((OS_FLAGS)0);
  107. }
  108. #endif
  109. if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event block type */
  110. *perr = OS_ERR_EVENT_TYPE;
  111. return ((OS_FLAGS)0);
  112. }
  113. result = (INT8U)(wait_type & OS_FLAG_CONSUME);
  114. if (result != (INT8U)0) { /* See if we need to consume the flags */
  115. wait_type &= ~OS_FLAG_CONSUME;
  116. consume = OS_TRUE;
  117. } else {
  118. consume = OS_FALSE;
  119. }
  120. /*$PAGE*/
  121. *perr = OS_ERR_NONE; /* Assume NO error until proven otherwise. */
  122. OS_ENTER_CRITICAL();
  123. switch (wait_type) {
  124. case OS_FLAG_WAIT_SET_ALL: /* See if all required flags are set */
  125. flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /* Extract only the bits we want */
  126. if (flags_rdy == flags) { /* Must match ALL the bits that we want */
  127. if (consume == OS_TRUE) { /* See if we need to consume the flags */
  128. pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /* Clear ONLY the flags we wanted */
  129. }
  130. } else {
  131. *perr = OS_ERR_FLAG_NOT_RDY;
  132. }
  133. OS_EXIT_CRITICAL();
  134. break;
  135. case OS_FLAG_WAIT_SET_ANY:
  136. flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /* Extract only the bits we want */
  137. if (flags_rdy != (OS_FLAGS)0) { /* See if any flag set */
  138. if (consume == OS_TRUE) { /* See if we need to consume the flags */
  139. pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /* Clear ONLY the flags we got */
  140. }
  141. } else {
  142. *perr = OS_ERR_FLAG_NOT_RDY;
  143. }
  144. OS_EXIT_CRITICAL();
  145. break;
  146. #if OS_FLAG_WAIT_CLR_EN > 0u
  147. case OS_FLAG_WAIT_CLR_ALL: /* See if all required flags are cleared */
  148. flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */
  149. if (flags_rdy == flags) { /* Must match ALL the bits that we want */
  150. if (consume == OS_TRUE) { /* See if we need to consume the flags */
  151. pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we wanted */
  152. }
  153. } else {
  154. *perr = OS_ERR_FLAG_NOT_RDY;
  155. }
  156. OS_EXIT_CRITICAL();
  157. break;
  158. case OS_FLAG_WAIT_CLR_ANY:
  159. flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */
  160. if (flags_rdy != (OS_FLAGS)0) { /* See if any flag cleared */
  161. if (consume == OS_TRUE) { /* See if we need to consume the flags */
  162. pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we got */
  163. }
  164. } else {
  165. *perr = OS_ERR_FLAG_NOT_RDY;
  166. }
  167. OS_EXIT_CRITICAL();
  168. break;
  169. #endif
  170. default:
  171. OS_EXIT_CRITICAL();
  172. flags_rdy = (OS_FLAGS)0;
  173. *perr = OS_ERR_FLAG_WAIT_TYPE;
  174. break;
  175. }
  176. return (flags_rdy);
  177. }
  178. #endif
  179. /*$PAGE*/
  180. /*
  181. *********************************************************************************************************
  182. * CREATE AN EVENT FLAG
  183. *
  184. * Description: This function is called to create an event flag group.
  185. *
  186. * Arguments : flags Contains the initial value to store in the event flag group.
  187. *
  188. * perr is a pointer to an error code which will be returned to your application:
  189. * OS_ERR_NONE if the call was successful.
  190. * OS_ERR_CREATE_ISR if you attempted to create an Event Flag from an
  191. * ISR.
  192. * OS_ERR_FLAG_GRP_DEPLETED if there are no more event flag groups
  193. *
  194. * Returns : A pointer to an event flag group or a NULL pointer if no more groups are available.
  195. *
  196. * Called from: Task ONLY
  197. *********************************************************************************************************
  198. */
  199. OS_FLAG_GRP *OSFlagCreate (OS_FLAGS flags,
  200. INT8U *perr)
  201. {
  202. OS_FLAG_GRP *pgrp;
  203. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  204. OS_CPU_SR cpu_sr = 0u;
  205. #endif
  206. #ifdef OS_SAFETY_CRITICAL
  207. if (perr == (INT8U *)0) {
  208. OS_SAFETY_CRITICAL_EXCEPTION();
  209. }
  210. #endif
  211. #ifdef OS_SAFETY_CRITICAL_IEC61508
  212. if (OSSafetyCriticalStartFlag == OS_TRUE) {
  213. OS_SAFETY_CRITICAL_EXCEPTION();
  214. }
  215. #endif
  216. if (OSIntNesting > 0u) { /* See if called from ISR ... */
  217. *perr = OS_ERR_CREATE_ISR; /* ... can't CREATE from an ISR */
  218. return ((OS_FLAG_GRP *)0);
  219. }
  220. OS_ENTER_CRITICAL();
  221. pgrp = OSFlagFreeList; /* Get next free event flag */
  222. if (pgrp != (OS_FLAG_GRP *)0) { /* See if we have event flag groups available */
  223. /* Adjust free list */
  224. OSFlagFreeList = (OS_FLAG_GRP *)OSFlagFreeList->OSFlagWaitList;
  225. pgrp->OSFlagType = OS_EVENT_TYPE_FLAG; /* Set to event flag group type */
  226. pgrp->OSFlagFlags = flags; /* Set to desired initial value */
  227. pgrp->OSFlagWaitList = (void *)0; /* Clear list of tasks waiting on flags */
  228. #if OS_FLAG_NAME_EN > 0u
  229. pgrp->OSFlagName = (INT8U *)(void *)"?";
  230. #endif
  231. OS_EXIT_CRITICAL();
  232. *perr = OS_ERR_NONE;
  233. } else {
  234. OS_EXIT_CRITICAL();
  235. *perr = OS_ERR_FLAG_GRP_DEPLETED;
  236. }
  237. return (pgrp); /* Return pointer to event flag group */
  238. }
  239. /*$PAGE*/
  240. /*
  241. *********************************************************************************************************
  242. * DELETE AN EVENT FLAG GROUP
  243. *
  244. * Description: This function deletes an event flag group and readies all tasks pending on the event flag
  245. * group.
  246. *
  247. * Arguments : pgrp is a pointer to the desired event flag group.
  248. *
  249. * opt determines delete options as follows:
  250. * opt == OS_DEL_NO_PEND Deletes the event flag group ONLY if no task pending
  251. * opt == OS_DEL_ALWAYS Deletes the event flag group even if tasks are
  252. * waiting. In this case, all the tasks pending will be
  253. * readied.
  254. *
  255. * perr is a pointer to an error code that can contain one of the following values:
  256. * OS_ERR_NONE The call was successful and the event flag group was
  257. * deleted
  258. * OS_ERR_DEL_ISR If you attempted to delete the event flag group from
  259. * an ISR
  260. * OS_ERR_FLAG_INVALID_PGRP If 'pgrp' is a NULL pointer.
  261. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to an event flag group
  262. * OS_ERR_INVALID_OPT An invalid option was specified
  263. * OS_ERR_TASK_WAITING One or more tasks were waiting on the event flag
  264. * group.
  265. *
  266. * Returns : pgrp upon error
  267. * (OS_EVENT *)0 if the event flag group was successfully deleted.
  268. *
  269. * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
  270. * the event flag group MUST check the return code of OSFlagAccept() and OSFlagPend().
  271. * 2) This call can potentially disable interrupts for a long time. The interrupt disable
  272. * time is directly proportional to the number of tasks waiting on the event flag group.
  273. *********************************************************************************************************
  274. */
  275. #if OS_FLAG_DEL_EN > 0u
  276. OS_FLAG_GRP *OSFlagDel (OS_FLAG_GRP *pgrp,
  277. INT8U opt,
  278. INT8U *perr)
  279. {
  280. BOOLEAN tasks_waiting;
  281. OS_FLAG_NODE *pnode;
  282. OS_FLAG_GRP *pgrp_return;
  283. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  284. OS_CPU_SR cpu_sr = 0u;
  285. #endif
  286. #ifdef OS_SAFETY_CRITICAL
  287. if (perr == (INT8U *)0) {
  288. OS_SAFETY_CRITICAL_EXCEPTION();
  289. }
  290. #endif
  291. #if OS_ARG_CHK_EN > 0u
  292. if (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */
  293. *perr = OS_ERR_FLAG_INVALID_PGRP;
  294. return (pgrp);
  295. }
  296. #endif
  297. if (OSIntNesting > 0u) { /* See if called from ISR ... */
  298. *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
  299. return (pgrp);
  300. }
  301. if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event group type */
  302. *perr = OS_ERR_EVENT_TYPE;
  303. return (pgrp);
  304. }
  305. OS_ENTER_CRITICAL();
  306. if (pgrp->OSFlagWaitList != (void *)0) { /* See if any tasks waiting on event flags */
  307. tasks_waiting = OS_TRUE; /* Yes */
  308. } else {
  309. tasks_waiting = OS_FALSE; /* No */
  310. }
  311. switch (opt) {
  312. case OS_DEL_NO_PEND: /* Delete group if no task waiting */
  313. if (tasks_waiting == OS_FALSE) {
  314. #if OS_FLAG_NAME_EN > 0u
  315. pgrp->OSFlagName = (INT8U *)(void *)"?";
  316. #endif
  317. pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED;
  318. pgrp->OSFlagWaitList = (void *)OSFlagFreeList; /* Return group to free list */
  319. pgrp->OSFlagFlags = (OS_FLAGS)0;
  320. OSFlagFreeList = pgrp;
  321. OS_EXIT_CRITICAL();
  322. *perr = OS_ERR_NONE;
  323. pgrp_return = (OS_FLAG_GRP *)0; /* Event Flag Group has been deleted */
  324. } else {
  325. OS_EXIT_CRITICAL();
  326. *perr = OS_ERR_TASK_WAITING;
  327. pgrp_return = pgrp;
  328. }
  329. break;
  330. case OS_DEL_ALWAYS: /* Always delete the event flag group */
  331. pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;
  332. while (pnode != (OS_FLAG_NODE *)0) { /* Ready ALL tasks waiting for flags */
  333. (void)OS_FlagTaskRdy(pnode, (OS_FLAGS)0);
  334. pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext;
  335. }
  336. #if OS_FLAG_NAME_EN > 0u
  337. pgrp->OSFlagName = (INT8U *)(void *)"?";
  338. #endif
  339. pgrp->OSFlagType = OS_EVENT_TYPE_UNUSED;
  340. pgrp->OSFlagWaitList = (void *)OSFlagFreeList;/* Return group to free list */
  341. pgrp->OSFlagFlags = (OS_FLAGS)0;
  342. OSFlagFreeList = pgrp;
  343. OS_EXIT_CRITICAL();
  344. if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */
  345. OS_Sched(); /* Find highest priority task ready to run */
  346. }
  347. *perr = OS_ERR_NONE;
  348. pgrp_return = (OS_FLAG_GRP *)0; /* Event Flag Group has been deleted */
  349. break;
  350. default:
  351. OS_EXIT_CRITICAL();
  352. *perr = OS_ERR_INVALID_OPT;
  353. pgrp_return = pgrp;
  354. break;
  355. }
  356. return (pgrp_return);
  357. }
  358. #endif
  359. /*$PAGE*/
  360. /*
  361. *********************************************************************************************************
  362. * GET THE NAME OF AN EVENT FLAG GROUP
  363. *
  364. * Description: This function is used to obtain the name assigned to an event flag group
  365. *
  366. * Arguments : pgrp is a pointer to the event flag group.
  367. *
  368. * pname is pointer to a pointer to an ASCII string that will receive the name of the event flag
  369. * group.
  370. *
  371. * perr is a pointer to an error code that can contain one of the following values:
  372. *
  373. * OS_ERR_NONE if the requested task is resumed
  374. * OS_ERR_EVENT_TYPE if 'pevent' is not pointing to an event flag group
  375. * OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname'
  376. * OS_ERR_FLAG_INVALID_PGRP if you passed a NULL pointer for 'pgrp'
  377. * OS_ERR_NAME_GET_ISR if you called this function from an ISR
  378. *
  379. * Returns : The length of the string or 0 if the 'pgrp' is a NULL pointer.
  380. *********************************************************************************************************
  381. */
  382. #if OS_FLAG_NAME_EN > 0u
  383. INT8U OSFlagNameGet (OS_FLAG_GRP *pgrp,
  384. INT8U **pname,
  385. INT8U *perr)
  386. {
  387. INT8U len;
  388. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  389. OS_CPU_SR cpu_sr = 0u;
  390. #endif
  391. #ifdef OS_SAFETY_CRITICAL
  392. if (perr == (INT8U *)0) {
  393. OS_SAFETY_CRITICAL_EXCEPTION();
  394. }
  395. #endif
  396. #if OS_ARG_CHK_EN > 0u
  397. if (pgrp == (OS_FLAG_GRP *)0) { /* Is 'pgrp' a NULL pointer? */
  398. *perr = OS_ERR_FLAG_INVALID_PGRP;
  399. return (0u);
  400. }
  401. if (pname == (INT8U **)0) { /* Is 'pname' a NULL pointer? */
  402. *perr = OS_ERR_PNAME_NULL;
  403. return (0u);
  404. }
  405. #endif
  406. if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
  407. *perr = OS_ERR_NAME_GET_ISR;
  408. return (0u);
  409. }
  410. OS_ENTER_CRITICAL();
  411. if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) {
  412. OS_EXIT_CRITICAL();
  413. *perr = OS_ERR_EVENT_TYPE;
  414. return (0u);
  415. }
  416. *pname = pgrp->OSFlagName;
  417. len = OS_StrLen(*pname);
  418. OS_EXIT_CRITICAL();
  419. *perr = OS_ERR_NONE;
  420. return (len);
  421. }
  422. #endif
  423. /*$PAGE*/
  424. /*
  425. *********************************************************************************************************
  426. * ASSIGN A NAME TO AN EVENT FLAG GROUP
  427. *
  428. * Description: This function assigns a name to an event flag group.
  429. *
  430. * Arguments : pgrp is a pointer to the event flag group.
  431. *
  432. * pname is a pointer to an ASCII string that will be used as the name of the event flag
  433. * group.
  434. *
  435. * perr is a pointer to an error code that can contain one of the following values:
  436. *
  437. * OS_ERR_NONE if the requested task is resumed
  438. * OS_ERR_EVENT_TYPE if 'pevent' is not pointing to an event flag group
  439. * OS_ERR_PNAME_NULL You passed a NULL pointer for 'pname'
  440. * OS_ERR_FLAG_INVALID_PGRP if you passed a NULL pointer for 'pgrp'
  441. * OS_ERR_NAME_SET_ISR if you called this function from an ISR
  442. *
  443. * Returns : None
  444. *********************************************************************************************************
  445. */
  446. #if OS_FLAG_NAME_EN > 0u
  447. void OSFlagNameSet (OS_FLAG_GRP *pgrp,
  448. INT8U *pname,
  449. INT8U *perr)
  450. {
  451. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  452. OS_CPU_SR cpu_sr = 0u;
  453. #endif
  454. #ifdef OS_SAFETY_CRITICAL
  455. if (perr == (INT8U *)0) {
  456. OS_SAFETY_CRITICAL_EXCEPTION();
  457. }
  458. #endif
  459. #if OS_ARG_CHK_EN > 0u
  460. if (pgrp == (OS_FLAG_GRP *)0) { /* Is 'pgrp' a NULL pointer? */
  461. *perr = OS_ERR_FLAG_INVALID_PGRP;
  462. return;
  463. }
  464. if (pname == (INT8U *)0) { /* Is 'pname' a NULL pointer? */
  465. *perr = OS_ERR_PNAME_NULL;
  466. return;
  467. }
  468. #endif
  469. if (OSIntNesting > 0u) { /* See if trying to call from an ISR */
  470. *perr = OS_ERR_NAME_SET_ISR;
  471. return;
  472. }
  473. OS_ENTER_CRITICAL();
  474. if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) {
  475. OS_EXIT_CRITICAL();
  476. *perr = OS_ERR_EVENT_TYPE;
  477. return;
  478. }
  479. pgrp->OSFlagName = pname;
  480. OS_EXIT_CRITICAL();
  481. *perr = OS_ERR_NONE;
  482. return;
  483. }
  484. #endif
  485. /*$PAGE*/
  486. /*
  487. *********************************************************************************************************
  488. * WAIT ON AN EVENT FLAG GROUP
  489. *
  490. * Description: This function is called to wait for a combination of bits to be set in an event flag
  491. * group. Your application can wait for ANY bit to be set or ALL bits to be set.
  492. *
  493. * Arguments : pgrp is a pointer to the desired event flag group.
  494. *
  495. * flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to wait for.
  496. * The bits you want are specified by setting the corresponding bits in
  497. * 'flags'. e.g. if your application wants to wait for bits 0 and 1 then
  498. * 'flags' would contain 0x03.
  499. *
  500. * wait_type specifies whether you want ALL bits to be set or ANY of the bits to be set.
  501. * You can specify the following argument:
  502. *
  503. * OS_FLAG_WAIT_CLR_ALL You will wait for ALL bits in 'mask' to be clear (0)
  504. * OS_FLAG_WAIT_SET_ALL You will wait for ALL bits in 'mask' to be set (1)
  505. * OS_FLAG_WAIT_CLR_ANY You will wait for ANY bit in 'mask' to be clear (0)
  506. * OS_FLAG_WAIT_SET_ANY You will wait for ANY bit in 'mask' to be set (1)
  507. *
  508. * NOTE: Add OS_FLAG_CONSUME if you want the event flag to be 'consumed' by
  509. * the call. Example, to wait for any flag in a group AND then clear
  510. * the flags that are present, set 'wait_type' to:
  511. *
  512. * OS_FLAG_WAIT_SET_ANY + OS_FLAG_CONSUME
  513. *
  514. * timeout is an optional timeout (in clock ticks) that your task will wait for the
  515. * desired bit combination. If you specify 0, however, your task will wait
  516. * forever at the specified event flag group or, until a message arrives.
  517. *
  518. * perr is a pointer to an error code and can be:
  519. * OS_ERR_NONE The desired bits have been set within the specified
  520. * 'timeout'.
  521. * OS_ERR_PEND_ISR If you tried to PEND from an ISR
  522. * OS_ERR_FLAG_INVALID_PGRP If 'pgrp' is a NULL pointer.
  523. * OS_ERR_EVENT_TYPE You are not pointing to an event flag group
  524. * OS_ERR_TIMEOUT The bit(s) have not been set in the specified
  525. * 'timeout'.
  526. * OS_ERR_PEND_ABORT The wait on the flag was aborted.
  527. * OS_ERR_FLAG_WAIT_TYPE You didn't specify a proper 'wait_type' argument.
  528. *
  529. * Returns : The flags in the event flag group that made the task ready or, 0 if a timeout or an error
  530. * occurred.
  531. *
  532. * Called from: Task ONLY
  533. *
  534. * Note(s) : 1) IMPORTANT, the behavior of this function has changed from PREVIOUS versions. The
  535. * function NOW returns the flags that were ready INSTEAD of the current state of the
  536. * event flags.
  537. *********************************************************************************************************
  538. */
  539. OS_FLAGS OSFlagPend (OS_FLAG_GRP *pgrp,
  540. OS_FLAGS flags,
  541. INT8U wait_type,
  542. INT32U timeout,
  543. INT8U *perr)
  544. {
  545. OS_FLAG_NODE node;
  546. OS_FLAGS flags_rdy;
  547. INT8U result;
  548. INT8U pend_stat;
  549. BOOLEAN consume;
  550. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  551. OS_CPU_SR cpu_sr = 0u;
  552. #endif
  553. #ifdef OS_SAFETY_CRITICAL
  554. if (perr == (INT8U *)0) {
  555. OS_SAFETY_CRITICAL_EXCEPTION();
  556. }
  557. #endif
  558. #if OS_ARG_CHK_EN > 0u
  559. if (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */
  560. *perr = OS_ERR_FLAG_INVALID_PGRP;
  561. return ((OS_FLAGS)0);
  562. }
  563. #endif
  564. if (OSIntNesting > 0u) { /* See if called from ISR ... */
  565. *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
  566. return ((OS_FLAGS)0);
  567. }
  568. if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */
  569. *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
  570. return ((OS_FLAGS)0);
  571. }
  572. if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event block type */
  573. *perr = OS_ERR_EVENT_TYPE;
  574. return ((OS_FLAGS)0);
  575. }
  576. result = (INT8U)(wait_type & OS_FLAG_CONSUME);
  577. if (result != (INT8U)0) { /* See if we need to consume the flags */
  578. wait_type &= (INT8U)~(INT8U)OS_FLAG_CONSUME;
  579. consume = OS_TRUE;
  580. } else {
  581. consume = OS_FALSE;
  582. }
  583. /*$PAGE*/
  584. OS_ENTER_CRITICAL();
  585. switch (wait_type) {
  586. case OS_FLAG_WAIT_SET_ALL: /* See if all required flags are set */
  587. flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /* Extract only the bits we want */
  588. if (flags_rdy == flags) { /* Must match ALL the bits that we want */
  589. if (consume == OS_TRUE) { /* See if we need to consume the flags */
  590. pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /* Clear ONLY the flags we wanted */
  591. }
  592. OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */
  593. OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */
  594. *perr = OS_ERR_NONE;
  595. return (flags_rdy);
  596. } else { /* Block task until events occur or timeout */
  597. OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);
  598. OS_EXIT_CRITICAL();
  599. }
  600. break;
  601. case OS_FLAG_WAIT_SET_ANY:
  602. flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & flags); /* Extract only the bits we want */
  603. if (flags_rdy != (OS_FLAGS)0) { /* See if any flag set */
  604. if (consume == OS_TRUE) { /* See if we need to consume the flags */
  605. pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy; /* Clear ONLY the flags that we got */
  606. }
  607. OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */
  608. OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */
  609. *perr = OS_ERR_NONE;
  610. return (flags_rdy);
  611. } else { /* Block task until events occur or timeout */
  612. OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);
  613. OS_EXIT_CRITICAL();
  614. }
  615. break;
  616. #if OS_FLAG_WAIT_CLR_EN > 0u
  617. case OS_FLAG_WAIT_CLR_ALL: /* See if all required flags are cleared */
  618. flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */
  619. if (flags_rdy == flags) { /* Must match ALL the bits that we want */
  620. if (consume == OS_TRUE) { /* See if we need to consume the flags */
  621. pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we wanted */
  622. }
  623. OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */
  624. OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */
  625. *perr = OS_ERR_NONE;
  626. return (flags_rdy);
  627. } else { /* Block task until events occur or timeout */
  628. OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);
  629. OS_EXIT_CRITICAL();
  630. }
  631. break;
  632. case OS_FLAG_WAIT_CLR_ANY:
  633. flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & flags; /* Extract only the bits we want */
  634. if (flags_rdy != (OS_FLAGS)0) { /* See if any flag cleared */
  635. if (consume == OS_TRUE) { /* See if we need to consume the flags */
  636. pgrp->OSFlagFlags |= flags_rdy; /* Set ONLY the flags that we got */
  637. }
  638. OSTCBCur->OSTCBFlagsRdy = flags_rdy; /* Save flags that were ready */
  639. OS_EXIT_CRITICAL(); /* Yes, condition met, return to caller */
  640. *perr = OS_ERR_NONE;
  641. return (flags_rdy);
  642. } else { /* Block task until events occur or timeout */
  643. OS_FlagBlock(pgrp, &node, flags, wait_type, timeout);
  644. OS_EXIT_CRITICAL();
  645. }
  646. break;
  647. #endif
  648. default:
  649. OS_EXIT_CRITICAL();
  650. flags_rdy = (OS_FLAGS)0;
  651. *perr = OS_ERR_FLAG_WAIT_TYPE;
  652. return (flags_rdy);
  653. }
  654. /*$PAGE*/
  655. OS_Sched(); /* Find next HPT ready to run */
  656. OS_ENTER_CRITICAL();
  657. if (OSTCBCur->OSTCBStatPend != OS_STAT_PEND_OK) { /* Have we timed-out or aborted? */
  658. pend_stat = OSTCBCur->OSTCBStatPend;
  659. OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
  660. OS_FlagUnlink(&node);
  661. OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Yes, make task ready-to-run */
  662. OS_EXIT_CRITICAL();
  663. flags_rdy = (OS_FLAGS)0;
  664. switch (pend_stat) {
  665. case OS_STAT_PEND_ABORT:
  666. *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted waiting */
  667. break;
  668. case OS_STAT_PEND_TO:
  669. default:
  670. *perr = OS_ERR_TIMEOUT; /* Indicate that we timed-out waiting */
  671. break;
  672. }
  673. return (flags_rdy);
  674. }
  675. flags_rdy = OSTCBCur->OSTCBFlagsRdy;
  676. if (consume == OS_TRUE) { /* See if we need to consume the flags */
  677. switch (wait_type) {
  678. case OS_FLAG_WAIT_SET_ALL:
  679. case OS_FLAG_WAIT_SET_ANY: /* Clear ONLY the flags we got */
  680. pgrp->OSFlagFlags &= (OS_FLAGS)~flags_rdy;
  681. break;
  682. #if OS_FLAG_WAIT_CLR_EN > 0u
  683. case OS_FLAG_WAIT_CLR_ALL:
  684. case OS_FLAG_WAIT_CLR_ANY: /* Set ONLY the flags we got */
  685. pgrp->OSFlagFlags |= flags_rdy;
  686. break;
  687. #endif
  688. default:
  689. OS_EXIT_CRITICAL();
  690. *perr = OS_ERR_FLAG_WAIT_TYPE;
  691. return ((OS_FLAGS)0);
  692. }
  693. }
  694. OS_EXIT_CRITICAL();
  695. *perr = OS_ERR_NONE; /* Event(s) must have occurred */
  696. return (flags_rdy);
  697. }
  698. /*$PAGE*/
  699. /*
  700. *********************************************************************************************************
  701. * GET FLAGS WHO CAUSED TASK TO BECOME READY
  702. *
  703. * Description: This function is called to obtain the flags that caused the task to become ready to run.
  704. * In other words, this function allows you to tell "Who done it!".
  705. *
  706. * Arguments : None
  707. *
  708. * Returns : The flags that caused the task to be ready.
  709. *
  710. * Called from: Task ONLY
  711. *********************************************************************************************************
  712. */
  713. OS_FLAGS OSFlagPendGetFlagsRdy (void)
  714. {
  715. OS_FLAGS flags;
  716. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  717. OS_CPU_SR cpu_sr = 0u;
  718. #endif
  719. OS_ENTER_CRITICAL();
  720. flags = OSTCBCur->OSTCBFlagsRdy;
  721. OS_EXIT_CRITICAL();
  722. return (flags);
  723. }
  724. /*$PAGE*/
  725. /*
  726. *********************************************************************************************************
  727. * POST EVENT FLAG BIT(S)
  728. *
  729. * Description: This function is called to set or clear some bits in an event flag group. The bits to
  730. * set or clear are specified by a 'bit mask'.
  731. *
  732. * Arguments : pgrp is a pointer to the desired event flag group.
  733. *
  734. * flags If 'opt' (see below) is OS_FLAG_SET, each bit that is set in 'flags' will
  735. * set the corresponding bit in the event flag group. e.g. to set bits 0, 4
  736. * and 5 you would set 'flags' to:
  737. *
  738. * 0x31 (note, bit 0 is least significant bit)
  739. *
  740. * If 'opt' (see below) is OS_FLAG_CLR, each bit that is set in 'flags' will
  741. * CLEAR the corresponding bit in the event flag group. e.g. to clear bits 0,
  742. * 4 and 5 you would specify 'flags' as:
  743. *
  744. * 0x31 (note, bit 0 is least significant bit)
  745. *
  746. * opt indicates whether the flags will be:
  747. * set (OS_FLAG_SET) or
  748. * cleared (OS_FLAG_CLR)
  749. *
  750. * perr is a pointer to an error code and can be:
  751. * OS_ERR_NONE The call was successfull
  752. * OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer
  753. * OS_ERR_EVENT_TYPE You are not pointing to an event flag group
  754. * OS_ERR_FLAG_INVALID_OPT You specified an invalid option
  755. *
  756. * Returns : the new value of the event flags bits that are still set.
  757. *
  758. * Called From: Task or ISR
  759. *
  760. * WARNING(s) : 1) The execution time of this function depends on the number of tasks waiting on the event
  761. * flag group.
  762. * 2) The amount of time interrupts are DISABLED depends on the number of tasks waiting on
  763. * the event flag group.
  764. *********************************************************************************************************
  765. */
  766. OS_FLAGS OSFlagPost (OS_FLAG_GRP *pgrp,
  767. OS_FLAGS flags,
  768. INT8U opt,
  769. INT8U *perr)
  770. {
  771. OS_FLAG_NODE *pnode;
  772. BOOLEAN sched;
  773. OS_FLAGS flags_cur;
  774. OS_FLAGS flags_rdy;
  775. BOOLEAN rdy;
  776. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  777. OS_CPU_SR cpu_sr = 0u;
  778. #endif
  779. #ifdef OS_SAFETY_CRITICAL
  780. if (perr == (INT8U *)0) {
  781. OS_SAFETY_CRITICAL_EXCEPTION();
  782. }
  783. #endif
  784. #if OS_ARG_CHK_EN > 0u
  785. if (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */
  786. *perr = OS_ERR_FLAG_INVALID_PGRP;
  787. return ((OS_FLAGS)0);
  788. }
  789. #endif
  790. if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Make sure we are pointing to an event flag grp */
  791. *perr = OS_ERR_EVENT_TYPE;
  792. return ((OS_FLAGS)0);
  793. }
  794. /*$PAGE*/
  795. OS_ENTER_CRITICAL();
  796. switch (opt) {
  797. case OS_FLAG_CLR:
  798. pgrp->OSFlagFlags &= (OS_FLAGS)~flags; /* Clear the flags specified in the group */
  799. break;
  800. case OS_FLAG_SET:
  801. pgrp->OSFlagFlags |= flags; /* Set the flags specified in the group */
  802. break;
  803. default:
  804. OS_EXIT_CRITICAL(); /* INVALID option */
  805. *perr = OS_ERR_FLAG_INVALID_OPT;
  806. return ((OS_FLAGS)0);
  807. }
  808. sched = OS_FALSE; /* Indicate that we don't need rescheduling */
  809. pnode = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;
  810. while (pnode != (OS_FLAG_NODE *)0) { /* Go through all tasks waiting on event flag(s) */
  811. switch (pnode->OSFlagNodeWaitType) {
  812. case OS_FLAG_WAIT_SET_ALL: /* See if all req. flags are set for current node */
  813. flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & pnode->OSFlagNodeFlags);
  814. if (flags_rdy == pnode->OSFlagNodeFlags) {
  815. rdy = OS_FlagTaskRdy(pnode, flags_rdy); /* Make task RTR, event(s) Rx'd */
  816. if (rdy == OS_TRUE) {
  817. sched = OS_TRUE; /* When done we will reschedule */
  818. }
  819. }
  820. break;
  821. case OS_FLAG_WAIT_SET_ANY: /* See if any flag set */
  822. flags_rdy = (OS_FLAGS)(pgrp->OSFlagFlags & pnode->OSFlagNodeFlags);
  823. if (flags_rdy != (OS_FLAGS)0) {
  824. rdy = OS_FlagTaskRdy(pnode, flags_rdy); /* Make task RTR, event(s) Rx'd */
  825. if (rdy == OS_TRUE) {
  826. sched = OS_TRUE; /* When done we will reschedule */
  827. }
  828. }
  829. break;
  830. #if OS_FLAG_WAIT_CLR_EN > 0u
  831. case OS_FLAG_WAIT_CLR_ALL: /* See if all req. flags are set for current node */
  832. flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags;
  833. if (flags_rdy == pnode->OSFlagNodeFlags) {
  834. rdy = OS_FlagTaskRdy(pnode, flags_rdy); /* Make task RTR, event(s) Rx'd */
  835. if (rdy == OS_TRUE) {
  836. sched = OS_TRUE; /* When done we will reschedule */
  837. }
  838. }
  839. break;
  840. case OS_FLAG_WAIT_CLR_ANY: /* See if any flag set */
  841. flags_rdy = (OS_FLAGS)~pgrp->OSFlagFlags & pnode->OSFlagNodeFlags;
  842. if (flags_rdy != (OS_FLAGS)0) {
  843. rdy = OS_FlagTaskRdy(pnode, flags_rdy); /* Make task RTR, event(s) Rx'd */
  844. if (rdy == OS_TRUE) {
  845. sched = OS_TRUE; /* When done we will reschedule */
  846. }
  847. }
  848. break;
  849. #endif
  850. default:
  851. OS_EXIT_CRITICAL();
  852. *perr = OS_ERR_FLAG_WAIT_TYPE;
  853. return ((OS_FLAGS)0);
  854. }
  855. pnode = (OS_FLAG_NODE *)pnode->OSFlagNodeNext; /* Point to next task waiting for event flag(s) */
  856. }
  857. OS_EXIT_CRITICAL();
  858. if (sched == OS_TRUE) {
  859. OS_Sched();
  860. }
  861. OS_ENTER_CRITICAL();
  862. flags_cur = pgrp->OSFlagFlags;
  863. OS_EXIT_CRITICAL();
  864. *perr = OS_ERR_NONE;
  865. return (flags_cur);
  866. }
  867. /*$PAGE*/
  868. /*
  869. *********************************************************************************************************
  870. * QUERY EVENT FLAG
  871. *
  872. * Description: This function is used to check the value of the event flag group.
  873. *
  874. * Arguments : pgrp is a pointer to the desired event flag group.
  875. *
  876. * perr is a pointer to an error code returned to the called:
  877. * OS_ERR_NONE The call was successfull
  878. * OS_ERR_FLAG_INVALID_PGRP You passed a NULL pointer
  879. * OS_ERR_EVENT_TYPE You are not pointing to an event flag group
  880. *
  881. * Returns : The current value of the event flag group.
  882. *
  883. * Called From: Task or ISR
  884. *********************************************************************************************************
  885. */
  886. #if OS_FLAG_QUERY_EN > 0u
  887. OS_FLAGS OSFlagQuery (OS_FLAG_GRP *pgrp,
  888. INT8U *perr)
  889. {
  890. OS_FLAGS flags;
  891. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  892. OS_CPU_SR cpu_sr = 0u;
  893. #endif
  894. #ifdef OS_SAFETY_CRITICAL
  895. if (perr == (INT8U *)0) {
  896. OS_SAFETY_CRITICAL_EXCEPTION();
  897. }
  898. #endif
  899. #if OS_ARG_CHK_EN > 0u
  900. if (pgrp == (OS_FLAG_GRP *)0) { /* Validate 'pgrp' */
  901. *perr = OS_ERR_FLAG_INVALID_PGRP;
  902. return ((OS_FLAGS)0);
  903. }
  904. #endif
  905. if (pgrp->OSFlagType != OS_EVENT_TYPE_FLAG) { /* Validate event block type */
  906. *perr = OS_ERR_EVENT_TYPE;
  907. return ((OS_FLAGS)0);
  908. }
  909. OS_ENTER_CRITICAL();
  910. flags = pgrp->OSFlagFlags;
  911. OS_EXIT_CRITICAL();
  912. *perr = OS_ERR_NONE;
  913. return (flags); /* Return the current value of the event flags */
  914. }
  915. #endif
  916. /*$PAGE*/
  917. /*
  918. *********************************************************************************************************
  919. * SUSPEND TASK UNTIL EVENT FLAG(s) RECEIVED OR TIMEOUT OCCURS
  920. *
  921. * Description: This function is internal to uC/OS-II and is used to put a task to sleep until the desired
  922. * event flag bit(s) are set.
  923. *
  924. * Arguments : pgrp is a pointer to the desired event flag group.
  925. *
  926. * pnode is a pointer to a structure which contains data about the task waiting for
  927. * event flag bit(s) to be set.
  928. *
  929. * flags Is a bit pattern indicating which bit(s) (i.e. flags) you wish to check.
  930. * The bits you want are specified by setting the corresponding bits in
  931. * 'flags'. e.g. if your application wants to wait for bits 0 and 1 then
  932. * 'flags' would contain 0x03.
  933. *
  934. * wait_type specifies whether you want ALL bits to be set/cleared or ANY of the bits
  935. * to be set/cleared.
  936. * You can specify the following argument:
  937. *
  938. * OS_FLAG_WAIT_CLR_ALL You will check ALL bits in 'mask' to be clear (0)
  939. * OS_FLAG_WAIT_CLR_ANY You will check ANY bit in 'mask' to be clear (0)
  940. * OS_FLAG_WAIT_SET_ALL You will check ALL bits in 'mask' to be set (1)
  941. * OS_FLAG_WAIT_SET_ANY You will check ANY bit in 'mask' to be set (1)
  942. *
  943. * timeout is the desired amount of time that the task will wait for the event flag
  944. * bit(s) to be set.
  945. *
  946. * Returns : none
  947. *
  948. * Called by : OSFlagPend() OS_FLAG.C
  949. *
  950. * Note(s) : This function is INTERNAL to uC/OS-II and your application should not call it.
  951. *********************************************************************************************************
  952. */
  953. static void OS_FlagBlock (OS_FLAG_GRP *pgrp,
  954. OS_FLAG_NODE *pnode,
  955. OS_FLAGS flags,
  956. INT8U wait_type,
  957. INT32U timeout)
  958. {
  959. OS_FLAG_NODE *pnode_next;
  960. INT8U y;
  961. OSTCBCur->OSTCBStat |= OS_STAT_FLAG;
  962. OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
  963. OSTCBCur->OSTCBDly = timeout; /* Store timeout in task's TCB */
  964. #if OS_TASK_DEL_EN > 0u
  965. OSTCBCur->OSTCBFlagNode = pnode; /* TCB to link to node */
  966. #endif
  967. pnode->OSFlagNodeFlags = flags; /* Save the flags that we need to wait for */
  968. pnode->OSFlagNodeWaitType = wait_type; /* Save the type of wait we are doing */
  969. pnode->OSFlagNodeTCB = (void *)OSTCBCur; /* Link to task's TCB */
  970. pnode->OSFlagNodeNext = pgrp->OSFlagWaitList; /* Add node at beginning of event flag wait list */
  971. pnode->OSFlagNodePrev = (void *)0;
  972. pnode->OSFlagNodeFlagGrp = (void *)pgrp; /* Link to Event Flag Group */
  973. pnode_next = (OS_FLAG_NODE *)pgrp->OSFlagWaitList;
  974. if (pnode_next != (void *)0) { /* Is this the first NODE to insert? */
  975. pnode_next->OSFlagNodePrev = pnode; /* No, link in doubly linked list */
  976. }
  977. pgrp->OSFlagWaitList = (void *)pnode;
  978. y = OSTCBCur->OSTCBY; /* Suspend current task until flag(s) received */
  979. OSRdyTbl[y] &= (OS_PRIO)~OSTCBCur->OSTCBBitX;
  980. if (OSRdyTbl[y] == 0x00u) {
  981. OSRdyGrp &= (OS_PRIO)~OSTCBCur->OSTCBBitY;
  982. }
  983. }
  984. /*$PAGE*/
  985. /*
  986. *********************************************************************************************************
  987. * INITIALIZE THE EVENT FLAG MODULE
  988. *
  989. * Description: This function is called by uC/OS-II to initialize the event flag module. Your application
  990. * MUST NOT call this function. In other words, this function is internal to uC/OS-II.
  991. *
  992. * Arguments : none
  993. *
  994. * Returns : none
  995. *
  996. * WARNING : You MUST NOT call this function from your code. This is an INTERNAL function to uC/OS-II.
  997. *********************************************************************************************************
  998. */
  999. void OS_FlagInit (void)
  1000. {
  1001. #if OS_MAX_FLAGS == 1u
  1002. OSFlagFreeList = (OS_FLAG_GRP *)&OSFlagTbl[0]; /* Only ONE event flag group! */
  1003. OSFlagFreeList->OSFlagType = OS_EVENT_TYPE_UNUSED;
  1004. OSFlagFreeList->OSFlagWaitList = (void *)0;
  1005. OSFlagFreeList->OSFlagFlags = (OS_FLAGS)0;
  1006. #if OS_FLAG_NAME_EN > 0u
  1007. OSFlagFreeList->OSFlagName = (INT8U *)"?";
  1008. #endif
  1009. #endif
  1010. #if OS_MAX_FLAGS >= 2u
  1011. INT16U ix;
  1012. INT16U ix_next;
  1013. OS_FLAG_GRP *pgrp1;
  1014. OS_FLAG_GRP *pgrp2;
  1015. OS_MemClr((INT8U *)&OSFlagTbl[0], sizeof(OSFlagTbl)); /* Clear the flag group table */
  1016. for (ix = 0u; ix < (OS_MAX_FLAGS - 1u); ix++) { /* Init. list of free EVENT FLAGS */
  1017. ix_next = ix + 1u;
  1018. pgrp1 = &OSFlagTbl[ix];
  1019. pgrp2 = &OSFlagTbl[ix_next];
  1020. pgrp1->OSFlagType = OS_EVENT_TYPE_UNUSED;
  1021. pgrp1->OSFlagWaitList = (void *)pgrp2;
  1022. #if OS_FLAG_NAME_EN > 0u
  1023. pgrp1->OSFlagName = (INT8U *)(void *)"?"; /* Unknown name */
  1024. #endif
  1025. }
  1026. pgrp1 = &OSFlagTbl[ix];
  1027. pgrp1->OSFlagType = OS_EVENT_TYPE_UNUSED;
  1028. pgrp1->OSFlagWaitList = (void *)0;
  1029. #if OS_FLAG_NAME_EN > 0u
  1030. pgrp1->OSFlagName = (INT8U *)(void *)"?"; /* Unknown name */
  1031. #endif
  1032. OSFlagFreeList = &OSFlagTbl[0];
  1033. #endif
  1034. }
  1035. /*$PAGE*/
  1036. /*
  1037. *********************************************************************************************************
  1038. * MAKE TASK READY-TO-RUN, EVENT(s) OCCURRED
  1039. *
  1040. * Description: This function is internal to uC/OS-II and is used to make a task ready-to-run because the
  1041. * desired event flag bits have been set.
  1042. *
  1043. * Arguments : pnode is a pointer to a structure which contains data about the task waiting for
  1044. * event flag bit(s) to be set.
  1045. *
  1046. * flags_rdy contains the bit pattern of the event flags that cause the task to become
  1047. * ready-to-run.
  1048. *
  1049. * Returns : OS_TRUE If the task has been placed in the ready list and thus needs scheduling
  1050. * OS_FALSE The task is still not ready to run and thus scheduling is not necessary
  1051. *
  1052. * Called by : OSFlagsPost() OS_FLAG.C
  1053. *
  1054. * Note(s) : 1) This function assumes that interrupts are disabled.
  1055. * 2) This function is INTERNAL to uC/OS-II and your application should not call it.
  1056. *********************************************************************************************************
  1057. */
  1058. static BOOLEAN OS_FlagTaskRdy (OS_FLAG_NODE *pnode,
  1059. OS_FLAGS flags_rdy)
  1060. {
  1061. OS_TCB *ptcb;
  1062. BOOLEAN sched;
  1063. ptcb = (OS_TCB *)pnode->OSFlagNodeTCB; /* Point to TCB of waiting task */
  1064. ptcb->OSTCBDly = 0u;
  1065. ptcb->OSTCBFlagsRdy = flags_rdy;
  1066. ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_FLAG;
  1067. ptcb->OSTCBStatPend = OS_STAT_PEND_OK;
  1068. if (ptcb->OSTCBStat == OS_STAT_RDY) { /* Task now ready? */
  1069. OSRdyGrp |= ptcb->OSTCBBitY; /* Put task into ready list */
  1070. OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;
  1071. sched = OS_TRUE;
  1072. } else {
  1073. sched = OS_FALSE;
  1074. }
  1075. OS_FlagUnlink(pnode);
  1076. return (sched);
  1077. }
  1078. /*$PAGE*/
  1079. /*
  1080. *********************************************************************************************************
  1081. * UNLINK EVENT FLAG NODE FROM WAITING LIST
  1082. *
  1083. * Description: This function is internal to uC/OS-II and is used to unlink an event flag node from a
  1084. * list of tasks waiting for the event flag.
  1085. *
  1086. * Arguments : pnode is a pointer to a structure which contains data about the task waiting for
  1087. * event flag bit(s) to be set.
  1088. *
  1089. * Returns : none
  1090. *
  1091. * Called by : OS_FlagTaskRdy() OS_FLAG.C
  1092. * OSFlagPend() OS_FLAG.C
  1093. * OSTaskDel() OS_TASK.C
  1094. *
  1095. * Note(s) : 1) This function assumes that interrupts are disabled.
  1096. * 2) This function is INTERNAL to uC/OS-II and your application should not call it.
  1097. *********************************************************************************************************
  1098. */
  1099. void OS_FlagUnlink (OS_FLAG_NODE *pnode)
  1100. {
  1101. #if OS_TASK_DEL_EN > 0u
  1102. OS_TCB *ptcb;
  1103. #endif
  1104. OS_FLAG_GRP *pgrp;
  1105. OS_FLAG_NODE *pnode_prev;
  1106. OS_FLAG_NODE *pnode_next;
  1107. pnode_prev = (OS_FLAG_NODE *)pnode->OSFlagNodePrev;
  1108. pnode_next = (OS_FLAG_NODE *)pnode->OSFlagNodeNext;
  1109. if (pnode_prev == (OS_FLAG_NODE *)0) { /* Is it first node in wait list? */
  1110. pgrp = (OS_FLAG_GRP *)pnode->OSFlagNodeFlagGrp;
  1111. pgrp->OSFlagWaitList = (void *)pnode_next; /* Update list for new 1st node */
  1112. if (pnode_next != (OS_FLAG_NODE *)0) {
  1113. pnode_next->OSFlagNodePrev = (OS_FLAG_NODE *)0; /* Link new 1st node PREV to NULL */
  1114. }
  1115. } else { /* No, A node somewhere in the list */
  1116. pnode_prev->OSFlagNodeNext = pnode_next; /* Link around the node to unlink */
  1117. if (pnode_next != (OS_FLAG_NODE *)0) { /* Was this the LAST node? */
  1118. pnode_next->OSFlagNodePrev = pnode_prev; /* No, Link around current node */
  1119. }
  1120. }
  1121. #if OS_TASK_DEL_EN > 0u
  1122. ptcb = (OS_TCB *)pnode->OSFlagNodeTCB;
  1123. ptcb->OSTCBFlagNode = (OS_FLAG_NODE *)0;
  1124. #endif
  1125. }
  1126. #endif