25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1287 lines
56 KiB

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