训练营PLSR题目
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 
 
 
 

1370 rader
61 KiB

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