os_sem.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  1. /*
  2. *********************************************************************************************************
  3. * uC/OS-II
  4. * The Real-Time Kernel
  5. * SEMAPHORE MANAGEMENT
  6. *
  7. * (c) Copyright 1992-2013, Micrium, Weston, FL
  8. * All Rights Reserved
  9. *
  10. * File : OS_SEM.C
  11. * By : Jean J. Labrosse
  12. * Version : V2.92.11
  13. *
  14. * LICENSING TERMS:
  15. * ---------------
  16. * uC/OS-II is provided in source form for FREE evaluation, for educational use or for peaceful research.
  17. * If you plan on using uC/OS-II in a commercial product you need to contact Micrium to properly license
  18. * its use in your product. We provide ALL the source code for your convenience and to help you experience
  19. * uC/OS-II. The fact that the source is provided does NOT mean that you can use it without paying a
  20. * licensing fee.
  21. *********************************************************************************************************
  22. */
  23. #define MICRIUM_SOURCE
  24. #ifndef OS_MASTER_FILE
  25. #include <ucos_ii.h>
  26. #endif
  27. #if OS_SEM_EN > 0u
  28. /*$PAGE*/
  29. /*
  30. *********************************************************************************************************
  31. * ACCEPT SEMAPHORE
  32. *
  33. * Description: This function checks the semaphore to see if a resource is available or, if an event
  34. * occurred. Unlike OSSemPend(), OSSemAccept() does not suspend the calling task if the
  35. * resource is not available or the event did not occur.
  36. *
  37. * Arguments : pevent is a pointer to the event control block
  38. *
  39. * Returns : > 0 if the resource is available or the event did not occur the semaphore is
  40. * decremented to obtain the resource.
  41. * == 0 if the resource is not available or the event did not occur or,
  42. * if 'pevent' is a NULL pointer or,
  43. * if you didn't pass a pointer to a semaphore
  44. *********************************************************************************************************
  45. */
  46. #if OS_SEM_ACCEPT_EN > 0u
  47. INT16U OSSemAccept (OS_EVENT *pevent)
  48. {
  49. INT16U cnt;
  50. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  51. OS_CPU_SR cpu_sr = 0u;
  52. #endif
  53. #if OS_ARG_CHK_EN > 0u
  54. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  55. return (0u);
  56. }
  57. #endif
  58. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  59. return (0u);
  60. }
  61. OS_ENTER_CRITICAL();
  62. cnt = pevent->OSEventCnt;
  63. if (cnt > 0u) { /* See if resource is available */
  64. pevent->OSEventCnt--; /* Yes, decrement semaphore and notify caller */
  65. }
  66. OS_EXIT_CRITICAL();
  67. return (cnt); /* Return semaphore count */
  68. }
  69. #endif
  70. /*$PAGE*/
  71. /*
  72. *********************************************************************************************************
  73. * CREATE A SEMAPHORE
  74. *
  75. * Description: This function creates a semaphore.
  76. *
  77. * Arguments : cnt is the initial value for the semaphore. If the value is 0, no resource is
  78. * available (or no event has occurred). You initialize the semaphore to a
  79. * non-zero value to specify how many resources are available (e.g. if you have
  80. * 10 resources, you would initialize the semaphore to 10).
  81. *
  82. * Returns : != (void *)0 is a pointer to the event control block (OS_EVENT) associated with the
  83. * created semaphore
  84. * == (void *)0 if no event control blocks were available
  85. *********************************************************************************************************
  86. */
  87. OS_EVENT *OSSemCreate (INT16U cnt)
  88. {
  89. OS_EVENT *pevent;
  90. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  91. OS_CPU_SR cpu_sr = 0u;
  92. #endif
  93. #ifdef OS_SAFETY_CRITICAL_IEC61508
  94. if (OSSafetyCriticalStartFlag == OS_TRUE) {
  95. OS_SAFETY_CRITICAL_EXCEPTION();
  96. return ((OS_EVENT *)0);
  97. }
  98. #endif
  99. if (OSIntNesting > 0u) { /* See if called from ISR ... */
  100. return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
  101. }
  102. OS_ENTER_CRITICAL();
  103. pevent = OSEventFreeList; /* Get next free event control block */
  104. if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
  105. OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
  106. }
  107. OS_EXIT_CRITICAL();
  108. if (pevent != (OS_EVENT *)0) { /* Get an event control block */
  109. pevent->OSEventType = OS_EVENT_TYPE_SEM;
  110. pevent->OSEventCnt = cnt; /* Set semaphore value */
  111. pevent->OSEventPtr = (void *)0; /* Unlink from ECB free list */
  112. #if OS_EVENT_NAME_EN > 0u
  113. pevent->OSEventName = (INT8U *)(void *)"?";
  114. #endif
  115. OS_EventWaitListInit(pevent); /* Initialize to 'nobody waiting' on sem. */
  116. }
  117. return (pevent);
  118. }
  119. /*$PAGE*/
  120. /*
  121. *********************************************************************************************************
  122. * DELETE A SEMAPHORE
  123. *
  124. * Description: This function deletes a semaphore and readies all tasks pending on the semaphore.
  125. *
  126. * Arguments : pevent is a pointer to the event control block associated with the desired
  127. * semaphore.
  128. *
  129. * opt determines delete options as follows:
  130. * opt == OS_DEL_NO_PEND Delete semaphore ONLY if no task pending
  131. * opt == OS_DEL_ALWAYS Deletes the semaphore even if tasks are waiting.
  132. * In this case, all the tasks pending will be readied.
  133. *
  134. * perr is a pointer to an error code that can contain one of the following values:
  135. * OS_ERR_NONE The call was successful and the semaphore was deleted
  136. * OS_ERR_DEL_ISR If you attempted to delete the semaphore from an ISR
  137. * OS_ERR_INVALID_OPT An invalid option was specified
  138. * OS_ERR_TASK_WAITING One or more tasks were waiting on the semaphore
  139. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore
  140. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  141. *
  142. * Returns : pevent upon error
  143. * (OS_EVENT *)0 if the semaphore was successfully deleted.
  144. *
  145. * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of
  146. * the semaphore MUST check the return code of OSSemPend().
  147. * 2) OSSemAccept() callers will not know that the intended semaphore has been deleted unless
  148. * they check 'pevent' to see that it's a NULL pointer.
  149. * 3) This call can potentially disable interrupts for a long time. The interrupt disable
  150. * time is directly proportional to the number of tasks waiting on the semaphore.
  151. * 4) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in
  152. * applications where the semaphore is used for mutual exclusion because the resource(s)
  153. * will no longer be guarded by the semaphore.
  154. * 5) All tasks that were waiting for the semaphore will be readied and returned an
  155. * OS_ERR_PEND_ABORT if OSSemDel() was called with OS_DEL_ALWAYS
  156. *********************************************************************************************************
  157. */
  158. #if OS_SEM_DEL_EN > 0u
  159. OS_EVENT *OSSemDel (OS_EVENT *pevent,
  160. INT8U opt,
  161. INT8U *perr)
  162. {
  163. BOOLEAN tasks_waiting;
  164. OS_EVENT *pevent_return;
  165. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  166. OS_CPU_SR cpu_sr = 0u;
  167. #endif
  168. #ifdef OS_SAFETY_CRITICAL
  169. if (perr == (INT8U *)0) {
  170. OS_SAFETY_CRITICAL_EXCEPTION();
  171. return ((OS_EVENT *)0);
  172. }
  173. #endif
  174. #if OS_ARG_CHK_EN > 0u
  175. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  176. *perr = OS_ERR_PEVENT_NULL;
  177. return (pevent);
  178. }
  179. #endif
  180. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  181. *perr = OS_ERR_EVENT_TYPE;
  182. return (pevent);
  183. }
  184. if (OSIntNesting > 0u) { /* See if called from ISR ... */
  185. *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
  186. return (pevent);
  187. }
  188. OS_ENTER_CRITICAL();
  189. if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on semaphore */
  190. tasks_waiting = OS_TRUE; /* Yes */
  191. } else {
  192. tasks_waiting = OS_FALSE; /* No */
  193. }
  194. switch (opt) {
  195. case OS_DEL_NO_PEND: /* Delete semaphore only if no task waiting */
  196. if (tasks_waiting == OS_FALSE) {
  197. #if OS_EVENT_NAME_EN > 0u
  198. pevent->OSEventName = (INT8U *)(void *)"?";
  199. #endif
  200. pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
  201. pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
  202. pevent->OSEventCnt = 0u;
  203. OSEventFreeList = pevent; /* Get next free event control block */
  204. OS_EXIT_CRITICAL();
  205. *perr = OS_ERR_NONE;
  206. pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */
  207. } else {
  208. OS_EXIT_CRITICAL();
  209. *perr = OS_ERR_TASK_WAITING;
  210. pevent_return = pevent;
  211. }
  212. break;
  213. case OS_DEL_ALWAYS: /* Always delete the semaphore */
  214. while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for semaphore */
  215. (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT);
  216. }
  217. #if OS_EVENT_NAME_EN > 0u
  218. pevent->OSEventName = (INT8U *)(void *)"?";
  219. #endif
  220. pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
  221. pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
  222. pevent->OSEventCnt = 0u;
  223. OSEventFreeList = pevent; /* Get next free event control block */
  224. OS_EXIT_CRITICAL();
  225. if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */
  226. OS_Sched(); /* Find highest priority task ready to run */
  227. }
  228. *perr = OS_ERR_NONE;
  229. pevent_return = (OS_EVENT *)0; /* Semaphore has been deleted */
  230. break;
  231. default:
  232. OS_EXIT_CRITICAL();
  233. *perr = OS_ERR_INVALID_OPT;
  234. pevent_return = pevent;
  235. break;
  236. }
  237. return (pevent_return);
  238. }
  239. #endif
  240. /*$PAGE*/
  241. /*
  242. *********************************************************************************************************
  243. * PEND ON SEMAPHORE
  244. *
  245. * Description: This function waits for a semaphore.
  246. *
  247. * Arguments : pevent is a pointer to the event control block associated with the desired
  248. * semaphore.
  249. *
  250. * timeout is an optional timeout period (in clock ticks). If non-zero, your task will
  251. * wait for the resource up to the amount of time specified by this argument.
  252. * If you specify 0, however, your task will wait forever at the specified
  253. * semaphore or, until the resource becomes available (or the event occurs).
  254. *
  255. * perr is a pointer to where an error message will be deposited. Possible error
  256. * messages are:
  257. *
  258. * OS_ERR_NONE The call was successful and your task owns the resource
  259. * or, the event you are waiting for occurred.
  260. * OS_ERR_TIMEOUT The semaphore was not received within the specified
  261. * 'timeout'.
  262. * OS_ERR_PEND_ABORT The wait on the semaphore was aborted.
  263. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore.
  264. * OS_ERR_PEND_ISR If you called this function from an ISR and the result
  265. * would lead to a suspension.
  266. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  267. * OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked
  268. *
  269. * Returns : none
  270. *********************************************************************************************************
  271. */
  272. /*$PAGE*/
  273. void OSSemPend (OS_EVENT *pevent,
  274. INT32U timeout,
  275. INT8U *perr)
  276. {
  277. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  278. OS_CPU_SR cpu_sr = 0u;
  279. #endif
  280. #ifdef OS_SAFETY_CRITICAL
  281. if (perr == (INT8U *)0) {
  282. OS_SAFETY_CRITICAL_EXCEPTION();
  283. return;
  284. }
  285. #endif
  286. #if OS_ARG_CHK_EN > 0u
  287. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  288. *perr = OS_ERR_PEVENT_NULL;
  289. return;
  290. }
  291. #endif
  292. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  293. *perr = OS_ERR_EVENT_TYPE;
  294. return;
  295. }
  296. if (OSIntNesting > 0u) { /* See if called from ISR ... */
  297. *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
  298. return;
  299. }
  300. if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */
  301. *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
  302. return;
  303. }
  304. OS_ENTER_CRITICAL();
  305. if (pevent->OSEventCnt > 0u) { /* If sem. is positive, resource available ... */
  306. pevent->OSEventCnt--; /* ... decrement semaphore only if positive. */
  307. OS_EXIT_CRITICAL();
  308. *perr = OS_ERR_NONE;
  309. return;
  310. }
  311. /* Otherwise, must wait until event occurs */
  312. OSTCBCur->OSTCBStat |= OS_STAT_SEM; /* Resource not available, pend on semaphore */
  313. OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
  314. OSTCBCur->OSTCBDly = timeout; /* Store pend timeout in TCB */
  315. OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
  316. OS_EXIT_CRITICAL();
  317. OS_Sched(); /* Find next highest priority task ready */
  318. OS_ENTER_CRITICAL();
  319. switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */
  320. case OS_STAT_PEND_OK:
  321. *perr = OS_ERR_NONE;
  322. break;
  323. case OS_STAT_PEND_ABORT:
  324. *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */
  325. break;
  326. case OS_STAT_PEND_TO:
  327. default:
  328. OS_EventTaskRemove(OSTCBCur, pevent);
  329. *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */
  330. break;
  331. }
  332. OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */
  333. OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
  334. OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */
  335. #if (OS_EVENT_MULTI_EN > 0u)
  336. OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
  337. #endif
  338. OS_EXIT_CRITICAL();
  339. }
  340. /*$PAGE*/
  341. /*
  342. *********************************************************************************************************
  343. * ABORT WAITING ON A SEMAPHORE
  344. *
  345. * Description: This function aborts & readies any tasks currently waiting on a semaphore. This function
  346. * should be used to fault-abort the wait on the semaphore, rather than to normally signal
  347. * the semaphore via OSSemPost().
  348. *
  349. * Arguments : pevent is a pointer to the event control block associated with the desired
  350. * semaphore.
  351. *
  352. * opt determines the type of ABORT performed:
  353. * OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the
  354. * semaphore
  355. * OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the
  356. * semaphore
  357. *
  358. * perr is a pointer to where an error message will be deposited. Possible error
  359. * messages are:
  360. *
  361. * OS_ERR_NONE No tasks were waiting on the semaphore.
  362. * OS_ERR_PEND_ABORT At least one task waiting on the semaphore was readied
  363. * and informed of the aborted wait; check return value
  364. * for the number of tasks whose wait on the semaphore
  365. * was aborted.
  366. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore.
  367. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  368. *
  369. * Returns : == 0 if no tasks were waiting on the semaphore, or upon error.
  370. * > 0 if one or more tasks waiting on the semaphore are now readied and informed.
  371. *********************************************************************************************************
  372. */
  373. #if OS_SEM_PEND_ABORT_EN > 0u
  374. INT8U OSSemPendAbort (OS_EVENT *pevent,
  375. INT8U opt,
  376. INT8U *perr)
  377. {
  378. INT8U nbr_tasks;
  379. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  380. OS_CPU_SR cpu_sr = 0u;
  381. #endif
  382. #ifdef OS_SAFETY_CRITICAL
  383. if (perr == (INT8U *)0) {
  384. OS_SAFETY_CRITICAL_EXCEPTION();
  385. return (0u);
  386. }
  387. #endif
  388. #if OS_ARG_CHK_EN > 0u
  389. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  390. *perr = OS_ERR_PEVENT_NULL;
  391. return (0u);
  392. }
  393. #endif
  394. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  395. *perr = OS_ERR_EVENT_TYPE;
  396. return (0u);
  397. }
  398. OS_ENTER_CRITICAL();
  399. if (pevent->OSEventGrp != 0u) { /* See if any task waiting on semaphore? */
  400. nbr_tasks = 0u;
  401. switch (opt) {
  402. case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */
  403. while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on semaphore */
  404. (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT);
  405. nbr_tasks++;
  406. }
  407. break;
  408. case OS_PEND_OPT_NONE:
  409. default: /* No, ready HPT waiting on semaphore */
  410. (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_ABORT);
  411. nbr_tasks++;
  412. break;
  413. }
  414. OS_EXIT_CRITICAL();
  415. OS_Sched(); /* Find HPT ready to run */
  416. *perr = OS_ERR_PEND_ABORT;
  417. return (nbr_tasks);
  418. }
  419. OS_EXIT_CRITICAL();
  420. *perr = OS_ERR_NONE;
  421. return (0u); /* No tasks waiting on semaphore */
  422. }
  423. #endif
  424. /*$PAGE*/
  425. /*
  426. *********************************************************************************************************
  427. * POST TO A SEMAPHORE
  428. *
  429. * Description: This function signals a semaphore
  430. *
  431. * Arguments : pevent is a pointer to the event control block associated with the desired
  432. * semaphore.
  433. *
  434. * Returns : OS_ERR_NONE The call was successful and the semaphore was signaled.
  435. * OS_ERR_SEM_OVF If the semaphore count exceeded its limit. In other words, you have
  436. * signaled the semaphore more often than you waited on it with either
  437. * OSSemAccept() or OSSemPend().
  438. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore
  439. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  440. *********************************************************************************************************
  441. */
  442. INT8U OSSemPost (OS_EVENT *pevent)
  443. {
  444. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  445. OS_CPU_SR cpu_sr = 0u;
  446. #endif
  447. #if OS_ARG_CHK_EN > 0u
  448. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  449. return (OS_ERR_PEVENT_NULL);
  450. }
  451. #endif
  452. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  453. return (OS_ERR_EVENT_TYPE);
  454. }
  455. OS_ENTER_CRITICAL();
  456. if (pevent->OSEventGrp != 0u) { /* See if any task waiting for semaphore */
  457. /* Ready HPT waiting on event */
  458. (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_SEM, OS_STAT_PEND_OK);
  459. OS_EXIT_CRITICAL();
  460. OS_Sched(); /* Find HPT ready to run */
  461. return (OS_ERR_NONE);
  462. }
  463. if (pevent->OSEventCnt < 65535u) { /* Make sure semaphore will not overflow */
  464. pevent->OSEventCnt++; /* Increment semaphore count to register event */
  465. OS_EXIT_CRITICAL();
  466. return (OS_ERR_NONE);
  467. }
  468. OS_EXIT_CRITICAL(); /* Semaphore value has reached its maximum */
  469. return (OS_ERR_SEM_OVF);
  470. }
  471. /*$PAGE*/
  472. /*
  473. *********************************************************************************************************
  474. * QUERY A SEMAPHORE
  475. *
  476. * Description: This function obtains information about a semaphore
  477. *
  478. * Arguments : pevent is a pointer to the event control block associated with the desired
  479. * semaphore
  480. *
  481. * p_sem_data is a pointer to a structure that will contain information about the
  482. * semaphore.
  483. *
  484. * Returns : OS_ERR_NONE The call was successful and the message was sent
  485. * OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non semaphore.
  486. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  487. * OS_ERR_PDATA_NULL If 'p_sem_data' is a NULL pointer
  488. *********************************************************************************************************
  489. */
  490. #if OS_SEM_QUERY_EN > 0u
  491. INT8U OSSemQuery (OS_EVENT *pevent,
  492. OS_SEM_DATA *p_sem_data)
  493. {
  494. INT8U i;
  495. OS_PRIO *psrc;
  496. OS_PRIO *pdest;
  497. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  498. OS_CPU_SR cpu_sr = 0u;
  499. #endif
  500. #if OS_ARG_CHK_EN > 0u
  501. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  502. return (OS_ERR_PEVENT_NULL);
  503. }
  504. if (p_sem_data == (OS_SEM_DATA *)0) { /* Validate 'p_sem_data' */
  505. return (OS_ERR_PDATA_NULL);
  506. }
  507. #endif
  508. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  509. return (OS_ERR_EVENT_TYPE);
  510. }
  511. OS_ENTER_CRITICAL();
  512. p_sem_data->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */
  513. psrc = &pevent->OSEventTbl[0];
  514. pdest = &p_sem_data->OSEventTbl[0];
  515. for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
  516. *pdest++ = *psrc++;
  517. }
  518. p_sem_data->OSCnt = pevent->OSEventCnt; /* Get semaphore count */
  519. OS_EXIT_CRITICAL();
  520. return (OS_ERR_NONE);
  521. }
  522. #endif /* OS_SEM_QUERY_EN */
  523. /*$PAGE*/
  524. /*
  525. *********************************************************************************************************
  526. * SET SEMAPHORE
  527. *
  528. * Description: This function sets the semaphore count to the value specified as an argument. Typically,
  529. * this value would be 0.
  530. *
  531. * You would typically use this function when a semaphore is used as a signaling mechanism
  532. * and, you want to reset the count value.
  533. *
  534. * Arguments : pevent is a pointer to the event control block
  535. *
  536. * cnt is the new value for the semaphore count. You would pass 0 to reset the
  537. * semaphore count.
  538. *
  539. * perr is a pointer to an error code returned by the function as follows:
  540. *
  541. * OS_ERR_NONE The call was successful and the semaphore value was set.
  542. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a semaphore.
  543. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  544. * OS_ERR_TASK_WAITING If tasks are waiting on the semaphore.
  545. *********************************************************************************************************
  546. */
  547. #if OS_SEM_SET_EN > 0u
  548. void OSSemSet (OS_EVENT *pevent,
  549. INT16U cnt,
  550. INT8U *perr)
  551. {
  552. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  553. OS_CPU_SR cpu_sr = 0u;
  554. #endif
  555. #ifdef OS_SAFETY_CRITICAL
  556. if (perr == (INT8U *)0) {
  557. OS_SAFETY_CRITICAL_EXCEPTION();
  558. return;
  559. }
  560. #endif
  561. #if OS_ARG_CHK_EN > 0u
  562. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  563. *perr = OS_ERR_PEVENT_NULL;
  564. return;
  565. }
  566. #endif
  567. if (pevent->OSEventType != OS_EVENT_TYPE_SEM) { /* Validate event block type */
  568. *perr = OS_ERR_EVENT_TYPE;
  569. return;
  570. }
  571. OS_ENTER_CRITICAL();
  572. *perr = OS_ERR_NONE;
  573. if (pevent->OSEventCnt > 0u) { /* See if semaphore already has a count */
  574. pevent->OSEventCnt = cnt; /* Yes, set it to the new value specified. */
  575. } else { /* No */
  576. if (pevent->OSEventGrp == 0u) { /* See if task(s) waiting? */
  577. pevent->OSEventCnt = cnt; /* No, OK to set the value */
  578. } else {
  579. *perr = OS_ERR_TASK_WAITING;
  580. }
  581. }
  582. OS_EXIT_CRITICAL();
  583. }
  584. #endif
  585. #endif /* OS_SEM_EN */