训练营PLSR题目
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1041 line
42 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. * SEMAPHORE MANAGEMENT
  10. *
  11. * File : OS_SEM.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_sem__c = "$Id: $";
  38. #endif
  39. #if OS_CFG_SEM_EN > 0u
  40. /*
  41. ************************************************************************************************************************
  42. * CREATE A SEMAPHORE
  43. *
  44. * Description: This function creates a semaphore.
  45. *
  46. * Arguments : p_sem is a pointer to the semaphore to initialize. Your application is responsible for
  47. * allocating storage for the semaphore.
  48. *
  49. * p_name is a pointer to the name you would like to give the semaphore.
  50. *
  51. * cnt is the initial value for the semaphore.
  52. * If used to share resources, you should initialize to the number of resources available.
  53. * If used to signal the occurrence of event(s) then you should initialize to 0.
  54. *
  55. * p_err is a pointer to a variable that will contain an error code returned by this function.
  56. *
  57. * OS_ERR_NONE if the call was successful
  58. * OS_ERR_CREATE_ISR if you called this function from an ISR
  59. * OS_ERR_ILLEGAL_CREATE_RUN_TIME if you are trying to create the semaphore after you
  60. * called OSSafetyCriticalStart().
  61. * OS_ERR_NAME if 'p_name' is a NULL pointer
  62. * OS_ERR_OBJ_CREATED if the semaphore has already been created
  63. * OS_ERR_OBJ_PTR_NULL if 'p_sem' is a NULL pointer
  64. * OS_ERR_OBJ_TYPE if 'p_sem' has already been initialized to a different
  65. * object type
  66. *
  67. * Returns : none
  68. ************************************************************************************************************************
  69. */
  70. void OSSemCreate (OS_SEM *p_sem,
  71. CPU_CHAR *p_name,
  72. OS_SEM_CTR cnt,
  73. OS_ERR *p_err)
  74. {
  75. CPU_SR_ALLOC();
  76. #ifdef OS_SAFETY_CRITICAL
  77. if (p_err == (OS_ERR *)0) {
  78. OS_SAFETY_CRITICAL_EXCEPTION();
  79. return;
  80. }
  81. #endif
  82. #ifdef OS_SAFETY_CRITICAL_IEC61508
  83. if (OSSafetyCriticalStartFlag == DEF_TRUE) {
  84. *p_err = OS_ERR_ILLEGAL_CREATE_RUN_TIME;
  85. return;
  86. }
  87. #endif
  88. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  89. if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to be called from an ISR */
  90. *p_err = OS_ERR_CREATE_ISR;
  91. return;
  92. }
  93. #endif
  94. #if OS_CFG_ARG_CHK_EN > 0u
  95. if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */
  96. *p_err = OS_ERR_OBJ_PTR_NULL;
  97. return;
  98. }
  99. #endif
  100. OS_CRITICAL_ENTER();
  101. #if OS_OBJ_TYPE_REQ > 0u
  102. p_sem->Type = OS_OBJ_TYPE_SEM; /* Mark the data structure as a semaphore */
  103. #endif
  104. p_sem->Ctr = cnt; /* Set semaphore value */
  105. p_sem->TS = (CPU_TS)0;
  106. #if OS_CFG_DBG_EN > 0u
  107. p_sem->NamePtr = p_name; /* Save the name of the semaphore */
  108. #else
  109. (void)&p_name;
  110. #endif
  111. OS_PendListInit(&p_sem->PendList); /* Initialize the waiting list */
  112. #if OS_CFG_DBG_EN > 0u
  113. OS_SemDbgListAdd(p_sem);
  114. #endif
  115. OSSemQty++;
  116. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  117. TRACE_OS_SEM_CREATE(p_sem, p_name); /* Record the event. */
  118. #endif
  119. OS_CRITICAL_EXIT_NO_SCHED();
  120. *p_err = OS_ERR_NONE;
  121. }
  122. /*
  123. ************************************************************************************************************************
  124. * DELETE A SEMAPHORE
  125. *
  126. * Description: This function deletes a semaphore.
  127. *
  128. * Arguments : p_sem is a pointer to the semaphore to delete
  129. *
  130. * opt determines delete options as follows:
  131. *
  132. * OS_OPT_DEL_NO_PEND Delete semaphore ONLY if no task pending
  133. * OS_OPT_DEL_ALWAYS Deletes the semaphore even if tasks are waiting.
  134. * In this case, all the tasks pending will be readied.
  135. *
  136. * p_err is a pointer to a variable that will contain an error code returned by this function.
  137. *
  138. * OS_ERR_NONE The call was successful and the semaphore was deleted
  139. * OS_ERR_DEL_ISR If you attempted to delete the semaphore from an ISR
  140. * OS_ERR_OBJ_PTR_NULL If 'p_sem' is a NULL pointer.
  141. * OS_ERR_OBJ_TYPE If 'p_sem' is not pointing at a semaphore
  142. * OS_ERR_OPT_INVALID An invalid option was specified
  143. * OS_ERR_TASK_WAITING One or more tasks were waiting on the semaphore
  144. *
  145. * Returns : == 0 if no tasks were waiting on the semaphore, or upon error.
  146. * > 0 if one or more tasks waiting on the semaphore are now readied and informed.
  147. *
  148. * Note(s) : 1) This function must be used with care. Tasks that would normally expect the presence of the semaphore
  149. * MUST check the return code of OSSemPend().
  150. * 2) OSSemAccept() callers will not know that the intended semaphore has been deleted.
  151. * 3) Because ALL tasks pending on the semaphore will be readied, you MUST be careful in applications where
  152. * the semaphore is used for mutual exclusion because the resource(s) will no longer be guarded by the
  153. * semaphore.
  154. ************************************************************************************************************************
  155. */
  156. #if OS_CFG_SEM_DEL_EN > 0u
  157. OS_OBJ_QTY OSSemDel (OS_SEM *p_sem,
  158. OS_OPT opt,
  159. OS_ERR *p_err)
  160. {
  161. OS_OBJ_QTY cnt;
  162. OS_OBJ_QTY nbr_tasks;
  163. OS_PEND_DATA *p_pend_data;
  164. OS_PEND_LIST *p_pend_list;
  165. OS_TCB *p_tcb;
  166. CPU_TS ts;
  167. CPU_SR_ALLOC();
  168. #ifdef OS_SAFETY_CRITICAL
  169. if (p_err == (OS_ERR *)0) {
  170. OS_SAFETY_CRITICAL_EXCEPTION();
  171. return ((OS_OBJ_QTY)0);
  172. }
  173. #endif
  174. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  175. if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to delete a semaphore from an ISR */
  176. *p_err = OS_ERR_DEL_ISR;
  177. return ((OS_OBJ_QTY)0);
  178. }
  179. #endif
  180. #if OS_CFG_ARG_CHK_EN > 0u
  181. if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */
  182. *p_err = OS_ERR_OBJ_PTR_NULL;
  183. return ((OS_OBJ_QTY)0);
  184. }
  185. switch (opt) { /* Validate 'opt' */
  186. case OS_OPT_DEL_NO_PEND:
  187. case OS_OPT_DEL_ALWAYS:
  188. break;
  189. default:
  190. *p_err = OS_ERR_OPT_INVALID;
  191. return ((OS_OBJ_QTY)0);
  192. }
  193. #endif
  194. #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
  195. if (p_sem->Type != OS_OBJ_TYPE_SEM) { /* Make sure semaphore was created */
  196. *p_err = OS_ERR_OBJ_TYPE;
  197. return ((OS_OBJ_QTY)0);
  198. }
  199. #endif
  200. CPU_CRITICAL_ENTER();
  201. p_pend_list = &p_sem->PendList;
  202. cnt = p_pend_list->NbrEntries;
  203. nbr_tasks = cnt;
  204. switch (opt) {
  205. case OS_OPT_DEL_NO_PEND: /* Delete semaphore only if no task waiting */
  206. if (nbr_tasks == (OS_OBJ_QTY)0) {
  207. #if OS_CFG_DBG_EN > 0u
  208. OS_SemDbgListRemove(p_sem);
  209. #endif
  210. OSSemQty--;
  211. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  212. TRACE_OS_SEM_DEL(p_sem); /* Record the event. */
  213. #endif
  214. OS_SemClr(p_sem);
  215. CPU_CRITICAL_EXIT();
  216. *p_err = OS_ERR_NONE;
  217. } else {
  218. CPU_CRITICAL_EXIT();
  219. *p_err = OS_ERR_TASK_WAITING;
  220. }
  221. break;
  222. case OS_OPT_DEL_ALWAYS: /* Always delete the semaphore */
  223. OS_CRITICAL_ENTER_CPU_EXIT();
  224. ts = OS_TS_GET(); /* Get local time stamp so all tasks get the same time */
  225. while (cnt > 0u) { /* Remove all tasks on the pend list */
  226. p_pend_data = p_pend_list->HeadPtr;
  227. p_tcb = p_pend_data->TCBPtr;
  228. OS_PendObjDel((OS_PEND_OBJ *)((void *)p_sem),
  229. p_tcb,
  230. ts);
  231. cnt--;
  232. }
  233. #if OS_CFG_DBG_EN > 0u
  234. OS_SemDbgListRemove(p_sem);
  235. #endif
  236. OSSemQty--;
  237. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  238. TRACE_OS_SEM_DEL(p_sem); /* Record the event. */
  239. #endif
  240. OS_SemClr(p_sem);
  241. OS_CRITICAL_EXIT_NO_SCHED();
  242. OSSched(); /* Find highest priority task ready to run */
  243. *p_err = OS_ERR_NONE;
  244. break;
  245. default:
  246. CPU_CRITICAL_EXIT();
  247. *p_err = OS_ERR_OPT_INVALID;
  248. break;
  249. }
  250. return ((OS_OBJ_QTY)nbr_tasks);
  251. }
  252. #endif
  253. /*
  254. ************************************************************************************************************************
  255. * PEND ON SEMAPHORE
  256. *
  257. * Description: This function waits for a semaphore.
  258. *
  259. * Arguments : p_sem is a pointer to the semaphore
  260. *
  261. * timeout is an optional timeout period (in clock ticks). If non-zero, your task will wait for the
  262. * resource up to the amount of time (in 'ticks') specified by this argument. If you specify
  263. * 0, however, your task will wait forever at the specified semaphore or, until the resource
  264. * becomes available (or the event occurs).
  265. *
  266. * opt determines whether the user wants to block if the semaphore is available or not:
  267. *
  268. * OS_OPT_PEND_BLOCKING
  269. * OS_OPT_PEND_NON_BLOCKING
  270. *
  271. * p_ts is a pointer to a variable that will receive the timestamp of when the semaphore was posted
  272. * or pend aborted or the semaphore deleted. If you pass a NULL pointer (i.e. (CPU_TS*)0)
  273. * then you will not get the timestamp. In other words, passing a NULL pointer is valid
  274. * and indicates that you don't need the timestamp.
  275. *
  276. * p_err is a pointer to a variable that will contain an error code returned by this function.
  277. *
  278. * OS_ERR_NONE The call was successful and your task owns the resource
  279. * or, the event you are waiting for occurred.
  280. * OS_ERR_OBJ_DEL If 'p_sem' was deleted
  281. * OS_ERR_OBJ_PTR_NULL If 'p_sem' is a NULL pointer.
  282. * OS_ERR_OBJ_TYPE If 'p_sem' is not pointing at a semaphore
  283. * OS_ERR_OPT_INVALID If you specified an invalid value for 'opt'
  284. * OS_ERR_PEND_ABORT If the pend was aborted by another task
  285. * OS_ERR_PEND_ISR If you called this function from an ISR and the result
  286. * would lead to a suspension.
  287. * OS_ERR_PEND_WOULD_BLOCK If you specified non-blocking but the semaphore was not
  288. * available.
  289. * OS_ERR_SCHED_LOCKED If you called this function when the scheduler is locked
  290. * OS_ERR_STATUS_INVALID Pend status is invalid
  291. * OS_ERR_TIMEOUT The semaphore was not received within the specified
  292. * timeout.
  293. *
  294. *
  295. * Returns : The current value of the semaphore counter or 0 if not available.
  296. ************************************************************************************************************************
  297. */
  298. OS_SEM_CTR OSSemPend (OS_SEM *p_sem,
  299. OS_TICK timeout,
  300. OS_OPT opt,
  301. CPU_TS *p_ts,
  302. OS_ERR *p_err)
  303. {
  304. OS_SEM_CTR ctr;
  305. OS_PEND_DATA pend_data;
  306. CPU_SR_ALLOC();
  307. #ifdef OS_SAFETY_CRITICAL
  308. if (p_err == (OS_ERR *)0) {
  309. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  310. TRACE_OS_SEM_PEND_FAILED(p_sem); /* Record the event. */
  311. #endif
  312. OS_SAFETY_CRITICAL_EXCEPTION();
  313. return ((OS_SEM_CTR)0);
  314. }
  315. #endif
  316. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  317. if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Not allowed to call from an ISR */
  318. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  319. TRACE_OS_SEM_PEND_FAILED(p_sem); /* Record the event. */
  320. #endif
  321. *p_err = OS_ERR_PEND_ISR;
  322. return ((OS_SEM_CTR)0);
  323. }
  324. #endif
  325. #if OS_CFG_ARG_CHK_EN > 0u
  326. if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */
  327. *p_err = OS_ERR_OBJ_PTR_NULL;
  328. return ((OS_SEM_CTR)0);
  329. }
  330. switch (opt) { /* Validate 'opt' */
  331. case OS_OPT_PEND_BLOCKING:
  332. case OS_OPT_PEND_NON_BLOCKING:
  333. break;
  334. default:
  335. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  336. TRACE_OS_SEM_PEND_FAILED(p_sem); /* Record the event. */
  337. #endif
  338. *p_err = OS_ERR_OPT_INVALID;
  339. return ((OS_SEM_CTR)0);
  340. }
  341. #endif
  342. #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
  343. if (p_sem->Type != OS_OBJ_TYPE_SEM) { /* Make sure semaphore was created */
  344. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  345. TRACE_OS_SEM_PEND_FAILED(p_sem); /* Record the event. */
  346. #endif
  347. *p_err = OS_ERR_OBJ_TYPE;
  348. return ((OS_SEM_CTR)0);
  349. }
  350. #endif
  351. if (p_ts != (CPU_TS *)0) {
  352. *p_ts = (CPU_TS)0; /* Initialize the returned timestamp */
  353. }
  354. CPU_CRITICAL_ENTER();
  355. if (p_sem->Ctr > (OS_SEM_CTR)0) { /* Resource available? */
  356. p_sem->Ctr--; /* Yes, caller may proceed */
  357. if (p_ts != (CPU_TS *)0) {
  358. *p_ts = p_sem->TS; /* get timestamp of last post */
  359. }
  360. ctr = p_sem->Ctr;
  361. CPU_CRITICAL_EXIT();
  362. *p_err = OS_ERR_NONE;
  363. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  364. TRACE_OS_SEM_PEND(p_sem); /* Record the event. */
  365. #endif
  366. return (ctr);
  367. }
  368. if ((opt & OS_OPT_PEND_NON_BLOCKING) != (OS_OPT)0) { /* Caller wants to block if not available? */
  369. ctr = p_sem->Ctr; /* No */
  370. CPU_CRITICAL_EXIT();
  371. *p_err = OS_ERR_PEND_WOULD_BLOCK;
  372. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  373. TRACE_OS_SEM_PEND_FAILED(p_sem); /* Record the event. */
  374. #endif
  375. return (ctr);
  376. } else { /* Yes */
  377. if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) { /* Can't pend when the scheduler is locked */
  378. CPU_CRITICAL_EXIT();
  379. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  380. TRACE_OS_SEM_PEND_FAILED(p_sem); /* Record the event. */
  381. #endif
  382. *p_err = OS_ERR_SCHED_LOCKED;
  383. return ((OS_SEM_CTR)0);
  384. }
  385. }
  386. /* Lock the scheduler/re-enable interrupts */
  387. OS_CRITICAL_ENTER_CPU_EXIT();
  388. OS_Pend(&pend_data, /* Block task pending on Semaphore */
  389. (OS_PEND_OBJ *)((void *)p_sem),
  390. OS_TASK_PEND_ON_SEM,
  391. timeout);
  392. OS_CRITICAL_EXIT_NO_SCHED();
  393. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  394. TRACE_OS_SEM_PEND_BLOCK(p_sem); /* Record the event. */
  395. #endif
  396. OSSched(); /* Find the next highest priority task ready to run */
  397. CPU_CRITICAL_ENTER();
  398. switch (OSTCBCurPtr->PendStatus) {
  399. case OS_STATUS_PEND_OK: /* We got the semaphore */
  400. if (p_ts != (CPU_TS *)0) {
  401. *p_ts = OSTCBCurPtr->TS;
  402. }
  403. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  404. TRACE_OS_SEM_PEND(p_sem); /* Record the event. */
  405. #endif
  406. *p_err = OS_ERR_NONE;
  407. break;
  408. case OS_STATUS_PEND_ABORT: /* Indicate that we aborted */
  409. if (p_ts != (CPU_TS *)0) {
  410. *p_ts = OSTCBCurPtr->TS;
  411. }
  412. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  413. TRACE_OS_SEM_PEND_FAILED(p_sem); /* Record the event. */
  414. #endif
  415. *p_err = OS_ERR_PEND_ABORT;
  416. break;
  417. case OS_STATUS_PEND_TIMEOUT: /* Indicate that we didn't get semaphore within timeout */
  418. if (p_ts != (CPU_TS *)0) {
  419. *p_ts = (CPU_TS )0;
  420. }
  421. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  422. TRACE_OS_SEM_PEND_FAILED(p_sem); /* Record the event. */
  423. #endif
  424. *p_err = OS_ERR_TIMEOUT;
  425. break;
  426. case OS_STATUS_PEND_DEL: /* Indicate that object pended on has been deleted */
  427. if (p_ts != (CPU_TS *)0) {
  428. *p_ts = OSTCBCurPtr->TS;
  429. }
  430. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  431. TRACE_OS_SEM_PEND_FAILED(p_sem); /* Record the event. */
  432. #endif
  433. *p_err = OS_ERR_OBJ_DEL;
  434. break;
  435. default:
  436. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  437. TRACE_OS_SEM_PEND_FAILED(p_sem); /* Record the event. */
  438. #endif
  439. *p_err = OS_ERR_STATUS_INVALID;
  440. CPU_CRITICAL_EXIT();
  441. return ((OS_SEM_CTR)0);
  442. }
  443. ctr = p_sem->Ctr;
  444. CPU_CRITICAL_EXIT();
  445. return (ctr);
  446. }
  447. /*
  448. ************************************************************************************************************************
  449. * ABORT WAITING ON A SEMAPHORE
  450. *
  451. * Description: This function aborts & readies any tasks currently waiting on a semaphore. This function should be used
  452. * to fault-abort the wait on the semaphore, rather than to normally signal the semaphore via OSSemPost().
  453. *
  454. * Arguments : p_sem is a pointer to the semaphore
  455. *
  456. * opt determines the type of ABORT performed:
  457. *
  458. * OS_OPT_PEND_ABORT_1 ABORT wait for a single task (HPT) waiting on the semaphore
  459. * OS_OPT_PEND_ABORT_ALL ABORT wait for ALL tasks that are waiting on the semaphore
  460. * OS_OPT_POST_NO_SCHED Do not call the scheduler
  461. *
  462. * p_err is a pointer to a variable that will contain an error code returned by this function.
  463. *
  464. * OS_ERR_NONE At least one task waiting on the semaphore was readied and
  465. * informed of the aborted wait; check return value for the
  466. * number of tasks whose wait on the semaphore was aborted.
  467. * OS_ERR_OBJ_PTR_NULL If 'p_sem' is a NULL pointer.
  468. * OS_ERR_OBJ_TYPE If 'p_sem' is not pointing at a semaphore
  469. * OS_ERR_OPT_INVALID If you specified an invalid option
  470. * OS_ERR_PEND_ABORT_ISR If you called this function from an ISR
  471. * OS_ERR_PEND_ABORT_NONE No task were pending
  472. *
  473. * Returns : == 0 if no tasks were waiting on the semaphore, or upon error.
  474. * > 0 if one or more tasks waiting on the semaphore are now readied and informed.
  475. ************************************************************************************************************************
  476. */
  477. #if OS_CFG_SEM_PEND_ABORT_EN > 0u
  478. OS_OBJ_QTY OSSemPendAbort (OS_SEM *p_sem,
  479. OS_OPT opt,
  480. OS_ERR *p_err)
  481. {
  482. OS_PEND_LIST *p_pend_list;
  483. OS_TCB *p_tcb;
  484. CPU_TS ts;
  485. OS_OBJ_QTY nbr_tasks;
  486. CPU_SR_ALLOC();
  487. #ifdef OS_SAFETY_CRITICAL
  488. if (p_err == (OS_ERR *)0) {
  489. OS_SAFETY_CRITICAL_EXCEPTION();
  490. return ((OS_OBJ_QTY)0u);
  491. }
  492. #endif
  493. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  494. if (OSIntNestingCtr > (OS_NESTING_CTR)0u) { /* Not allowed to Pend Abort from an ISR */
  495. *p_err = OS_ERR_PEND_ABORT_ISR;
  496. return ((OS_OBJ_QTY)0u);
  497. }
  498. #endif
  499. #if OS_CFG_ARG_CHK_EN > 0u
  500. if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */
  501. *p_err = OS_ERR_OBJ_PTR_NULL;
  502. return ((OS_OBJ_QTY)0u);
  503. }
  504. switch (opt) { /* Validate 'opt' */
  505. case OS_OPT_PEND_ABORT_1:
  506. case OS_OPT_PEND_ABORT_ALL:
  507. case OS_OPT_PEND_ABORT_1 | OS_OPT_POST_NO_SCHED:
  508. case OS_OPT_PEND_ABORT_ALL | OS_OPT_POST_NO_SCHED:
  509. break;
  510. default:
  511. *p_err = OS_ERR_OPT_INVALID;
  512. return ((OS_OBJ_QTY)0u);
  513. }
  514. #endif
  515. #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
  516. if (p_sem->Type != OS_OBJ_TYPE_SEM) { /* Make sure semaphore was created */
  517. *p_err = OS_ERR_OBJ_TYPE;
  518. return ((OS_OBJ_QTY)0u);
  519. }
  520. #endif
  521. CPU_CRITICAL_ENTER();
  522. p_pend_list = &p_sem->PendList;
  523. if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0u) { /* Any task waiting on semaphore? */
  524. CPU_CRITICAL_EXIT(); /* No */
  525. *p_err = OS_ERR_PEND_ABORT_NONE;
  526. return ((OS_OBJ_QTY)0u);
  527. }
  528. OS_CRITICAL_ENTER_CPU_EXIT();
  529. nbr_tasks = 0u;
  530. ts = OS_TS_GET(); /* Get local time stamp so all tasks get the same time */
  531. while (p_pend_list->NbrEntries > (OS_OBJ_QTY)0u) {
  532. p_tcb = p_pend_list->HeadPtr->TCBPtr;
  533. OS_PendAbort((OS_PEND_OBJ *)((void *)p_sem),
  534. p_tcb,
  535. ts);
  536. nbr_tasks++;
  537. if (opt != OS_OPT_PEND_ABORT_ALL) { /* Pend abort all tasks waiting? */
  538. break; /* No */
  539. }
  540. }
  541. OS_CRITICAL_EXIT_NO_SCHED();
  542. if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0u) {
  543. OSSched(); /* Run the scheduler */
  544. }
  545. *p_err = OS_ERR_NONE;
  546. return (nbr_tasks);
  547. }
  548. #endif
  549. /*
  550. ************************************************************************************************************************
  551. * POST TO A SEMAPHORE
  552. *
  553. * Description: This function signals a semaphore
  554. *
  555. * Arguments : p_sem is a pointer to the semaphore
  556. *
  557. * opt determines the type of POST performed:
  558. *
  559. * OS_OPT_POST_1 POST and ready only the highest priority task waiting on semaphore
  560. * (if tasks are waiting).
  561. * OS_OPT_POST_ALL POST to ALL tasks that are waiting on the semaphore
  562. *
  563. * OS_OPT_POST_NO_SCHED Do not call the scheduler
  564. *
  565. * Note(s): 1) OS_OPT_POST_NO_SCHED can be added with one of the other options.
  566. *
  567. * p_err is a pointer to a variable that will contain an error code returned by this function.
  568. *
  569. * OS_ERR_NONE The call was successful and the semaphore was signaled.
  570. * OS_ERR_OBJ_PTR_NULL If 'p_sem' is a NULL pointer.
  571. * OS_ERR_OBJ_TYPE If 'p_sem' is not pointing at a semaphore
  572. * OS_ERR_SEM_OVF If the post would cause the semaphore count to overflow.
  573. *
  574. * Returns : The current value of the semaphore counter or 0 upon error.
  575. ************************************************************************************************************************
  576. */
  577. OS_SEM_CTR OSSemPost (OS_SEM *p_sem,
  578. OS_OPT opt,
  579. OS_ERR *p_err)
  580. {
  581. OS_SEM_CTR ctr;
  582. CPU_TS ts;
  583. #ifdef OS_SAFETY_CRITICAL
  584. if (p_err == (OS_ERR *)0) {
  585. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  586. TRACE_OS_SEM_POST_FAILED(p_sem); /* Record the event. */
  587. #endif
  588. OS_SAFETY_CRITICAL_EXCEPTION();
  589. return ((OS_SEM_CTR)0);
  590. }
  591. #endif
  592. #if OS_CFG_ARG_CHK_EN > 0u
  593. if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */
  594. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  595. TRACE_OS_SEM_POST_FAILED(p_sem); /* Record the event. */
  596. #endif
  597. *p_err = OS_ERR_OBJ_PTR_NULL;
  598. return ((OS_SEM_CTR)0);
  599. }
  600. switch (opt) { /* Validate 'opt' */
  601. case OS_OPT_POST_1:
  602. case OS_OPT_POST_ALL:
  603. case OS_OPT_POST_1 | OS_OPT_POST_NO_SCHED:
  604. case OS_OPT_POST_ALL | OS_OPT_POST_NO_SCHED:
  605. break;
  606. default:
  607. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  608. TRACE_OS_SEM_POST_FAILED(p_sem); /* Record the event. */
  609. #endif
  610. *p_err = OS_ERR_OPT_INVALID;
  611. return ((OS_SEM_CTR)0u);
  612. }
  613. #endif
  614. #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
  615. if (p_sem->Type != OS_OBJ_TYPE_SEM) { /* Make sure semaphore was created */
  616. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  617. TRACE_OS_SEM_POST_FAILED(p_sem); /* Record the event. */
  618. #endif
  619. *p_err = OS_ERR_OBJ_TYPE;
  620. return ((OS_SEM_CTR)0);
  621. }
  622. #endif
  623. ts = OS_TS_GET(); /* Get timestamp */
  624. #if OS_CFG_ISR_POST_DEFERRED_EN > 0u
  625. if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* See if called from an ISR */
  626. OS_IntQPost((OS_OBJ_TYPE)OS_OBJ_TYPE_SEM, /* Post to ISR queue */
  627. (void *)p_sem,
  628. (void *)0,
  629. (OS_MSG_SIZE)0,
  630. (OS_FLAGS )0,
  631. (OS_OPT )opt,
  632. (CPU_TS )ts,
  633. (OS_ERR *)p_err);
  634. return ((OS_SEM_CTR)0);
  635. }
  636. #endif
  637. #if (defined(TRACE_CFG_EN) && (TRACE_CFG_EN > 0u))
  638. TRACE_OS_SEM_POST(p_sem); /* Record the event. */
  639. #endif
  640. ctr = OS_SemPost(p_sem, /* Post to semaphore */
  641. opt,
  642. ts,
  643. p_err);
  644. return (ctr);
  645. }
  646. /*
  647. ************************************************************************************************************************
  648. * SET SEMAPHORE
  649. *
  650. * Description: This function sets the semaphore count to the value specified as an argument. Typically, this value
  651. * would be 0 but of course, we can set the semaphore to any value.
  652. *
  653. * You would typically use this function when a semaphore is used as a signaling mechanism
  654. * and, you want to reset the count value.
  655. *
  656. * Arguments : p_sem is a pointer to the semaphore
  657. *
  658. * cnt is the new value for the semaphore count. You would pass 0 to reset the semaphore count.
  659. *
  660. * p_err is a pointer to a variable that will contain an error code returned by this function.
  661. *
  662. * OS_ERR_NONE The call was successful and the semaphore value was set.
  663. * OS_ERR_OBJ_PTR_NULL If 'p_sem' is a NULL pointer.
  664. * OS_ERR_OBJ_TYPE If 'p_sem' is not pointing to a semaphore.
  665. * OS_ERR_TASK_WAITING If tasks are waiting on the semaphore.
  666. *
  667. * Returns : None
  668. ************************************************************************************************************************
  669. */
  670. #if OS_CFG_SEM_SET_EN > 0u
  671. void OSSemSet (OS_SEM *p_sem,
  672. OS_SEM_CTR cnt,
  673. OS_ERR *p_err)
  674. {
  675. OS_PEND_LIST *p_pend_list;
  676. CPU_SR_ALLOC();
  677. #ifdef OS_SAFETY_CRITICAL
  678. if (p_err == (OS_ERR *)0) {
  679. OS_SAFETY_CRITICAL_EXCEPTION();
  680. return;
  681. }
  682. #endif
  683. #if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
  684. if (OSIntNestingCtr > (OS_NESTING_CTR)0) { /* Can't call this function from an ISR */
  685. *p_err = OS_ERR_SET_ISR;
  686. return;
  687. }
  688. #endif
  689. #if OS_CFG_ARG_CHK_EN > 0u
  690. if (p_sem == (OS_SEM *)0) { /* Validate 'p_sem' */
  691. *p_err = OS_ERR_OBJ_PTR_NULL;
  692. return;
  693. }
  694. #endif
  695. #if OS_CFG_OBJ_TYPE_CHK_EN > 0u
  696. if (p_sem->Type != OS_OBJ_TYPE_SEM) { /* Make sure semaphore was created */
  697. *p_err = OS_ERR_OBJ_TYPE;
  698. return;
  699. }
  700. #endif
  701. *p_err = OS_ERR_NONE;
  702. CPU_CRITICAL_ENTER();
  703. if (p_sem->Ctr > (OS_SEM_CTR)0) { /* See if semaphore already has a count */
  704. p_sem->Ctr = cnt; /* Yes, set it to the new value specified. */
  705. } else {
  706. p_pend_list = &p_sem->PendList; /* No */
  707. if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0) { /* See if task(s) waiting? */
  708. p_sem->Ctr = cnt; /* No, OK to set the value */
  709. } else {
  710. *p_err = OS_ERR_TASK_WAITING;
  711. }
  712. }
  713. CPU_CRITICAL_EXIT();
  714. }
  715. #endif
  716. /*
  717. ************************************************************************************************************************
  718. * CLEAR THE CONTENTS OF A SEMAPHORE
  719. *
  720. * Description: This function is called by OSSemDel() to clear the contents of a semaphore
  721. *
  722. * Argument(s): p_sem is a pointer to the semaphore to clear
  723. * -----
  724. *
  725. * Returns : none
  726. *
  727. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  728. ************************************************************************************************************************
  729. */
  730. void OS_SemClr (OS_SEM *p_sem)
  731. {
  732. #if OS_OBJ_TYPE_REQ > 0u
  733. p_sem->Type = OS_OBJ_TYPE_NONE; /* Mark the data structure as a NONE */
  734. #endif
  735. p_sem->Ctr = (OS_SEM_CTR)0; /* Set semaphore value */
  736. p_sem->TS = (CPU_TS )0; /* Clear the time stamp */
  737. #if OS_CFG_DBG_EN > 0u
  738. p_sem->NamePtr = (CPU_CHAR *)((void *)"?SEM");
  739. #endif
  740. OS_PendListInit(&p_sem->PendList); /* Initialize the waiting list */
  741. }
  742. /*
  743. ************************************************************************************************************************
  744. * ADD/REMOVE SEMAPHORE TO/FROM DEBUG LIST
  745. *
  746. * Description: These functions are called by uC/OS-III to add or remove a semaphore to/from the debug list.
  747. *
  748. * Arguments : p_sem is a pointer to the semaphore to add/remove
  749. *
  750. * Returns : none
  751. *
  752. * Note(s) : These functions are INTERNAL to uC/OS-III and your application should not call it.
  753. ************************************************************************************************************************
  754. */
  755. #if OS_CFG_DBG_EN > 0u
  756. void OS_SemDbgListAdd (OS_SEM *p_sem)
  757. {
  758. p_sem->DbgNamePtr = (CPU_CHAR *)((void *)" ");
  759. p_sem->DbgPrevPtr = (OS_SEM *)0;
  760. if (OSSemDbgListPtr == (OS_SEM *)0) {
  761. p_sem->DbgNextPtr = (OS_SEM *)0;
  762. } else {
  763. p_sem->DbgNextPtr = OSSemDbgListPtr;
  764. OSSemDbgListPtr->DbgPrevPtr = p_sem;
  765. }
  766. OSSemDbgListPtr = p_sem;
  767. }
  768. void OS_SemDbgListRemove (OS_SEM *p_sem)
  769. {
  770. OS_SEM *p_sem_next;
  771. OS_SEM *p_sem_prev;
  772. p_sem_prev = p_sem->DbgPrevPtr;
  773. p_sem_next = p_sem->DbgNextPtr;
  774. if (p_sem_prev == (OS_SEM *)0) {
  775. OSSemDbgListPtr = p_sem_next;
  776. if (p_sem_next != (OS_SEM *)0) {
  777. p_sem_next->DbgPrevPtr = (OS_SEM *)0;
  778. }
  779. p_sem->DbgNextPtr = (OS_SEM *)0;
  780. } else if (p_sem_next == (OS_SEM *)0) {
  781. p_sem_prev->DbgNextPtr = (OS_SEM *)0;
  782. p_sem->DbgPrevPtr = (OS_SEM *)0;
  783. } else {
  784. p_sem_prev->DbgNextPtr = p_sem_next;
  785. p_sem_next->DbgPrevPtr = p_sem_prev;
  786. p_sem->DbgNextPtr = (OS_SEM *)0;
  787. p_sem->DbgPrevPtr = (OS_SEM *)0;
  788. }
  789. }
  790. #endif
  791. /*
  792. ************************************************************************************************************************
  793. * SEMAPHORE INITIALIZATION
  794. *
  795. * Description: This function is called by OSInit() to initialize the semaphore management.
  796. *
  797. * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
  798. *
  799. * OS_ERR_NONE the call was successful
  800. *
  801. * Returns : none
  802. *
  803. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  804. ************************************************************************************************************************
  805. */
  806. void OS_SemInit (OS_ERR *p_err)
  807. {
  808. #ifdef OS_SAFETY_CRITICAL
  809. if (p_err == (OS_ERR *)0) {
  810. OS_SAFETY_CRITICAL_EXCEPTION();
  811. return;
  812. }
  813. #endif
  814. #if OS_CFG_DBG_EN > 0u
  815. OSSemDbgListPtr = (OS_SEM *)0;
  816. #endif
  817. OSSemQty = (OS_OBJ_QTY)0;
  818. *p_err = OS_ERR_NONE;
  819. }
  820. /*
  821. ************************************************************************************************************************
  822. * POST TO A SEMAPHORE
  823. *
  824. * Description: This function signals a semaphore
  825. *
  826. * Arguments : p_sem is a pointer to the semaphore
  827. *
  828. * opt determines the type of POST performed:
  829. *
  830. * OS_OPT_POST_1 POST to a single waiting task
  831. * OS_OPT_POST_ALL POST to ALL tasks that are waiting on the semaphore
  832. *
  833. * OS_OPT_POST_NO_SCHED Do not call the scheduler
  834. *
  835. * Note(s): 1) OS_OPT_POST_NO_SCHED can be added with one of the other options.
  836. *
  837. * ts is a timestamp indicating when the post occurred.
  838. *
  839. * p_err is a pointer to a variable that will contain an error code returned by this function.
  840. *
  841. * OS_ERR_NONE The call was successful and the semaphore was signaled.
  842. * OS_ERR_OBJ_PTR_NULL If 'p_sem' is a NULL pointer.
  843. * OS_ERR_OBJ_TYPE If 'p_sem' is not pointing at a semaphore
  844. * OS_ERR_SEM_OVF If the post would cause the semaphore count to overflow.
  845. *
  846. * Returns : The current value of the semaphore counter or 0 upon error.
  847. *
  848. * Note(s) : This function is INTERNAL to uC/OS-III and your application should not call it.
  849. ************************************************************************************************************************
  850. */
  851. OS_SEM_CTR OS_SemPost (OS_SEM *p_sem,
  852. OS_OPT opt,
  853. CPU_TS ts,
  854. OS_ERR *p_err)
  855. {
  856. OS_OBJ_QTY cnt;
  857. OS_SEM_CTR ctr;
  858. OS_PEND_LIST *p_pend_list;
  859. OS_PEND_DATA *p_pend_data;
  860. OS_PEND_DATA *p_pend_data_next;
  861. OS_TCB *p_tcb;
  862. CPU_SR_ALLOC();
  863. CPU_CRITICAL_ENTER();
  864. p_pend_list = &p_sem->PendList;
  865. if (p_pend_list->NbrEntries == (OS_OBJ_QTY)0) { /* Any task waiting on semaphore? */
  866. switch (sizeof(OS_SEM_CTR)) {
  867. case 1u:
  868. if (p_sem->Ctr == DEF_INT_08U_MAX_VAL) {
  869. CPU_CRITICAL_EXIT();
  870. *p_err = OS_ERR_SEM_OVF;
  871. return ((OS_SEM_CTR)0);
  872. }
  873. break;
  874. case 2u:
  875. if (p_sem->Ctr == DEF_INT_16U_MAX_VAL) {
  876. CPU_CRITICAL_EXIT();
  877. *p_err = OS_ERR_SEM_OVF;
  878. return ((OS_SEM_CTR)0);
  879. }
  880. break;
  881. case 4u:
  882. if (p_sem->Ctr == DEF_INT_32U_MAX_VAL) {
  883. CPU_CRITICAL_EXIT();
  884. *p_err = OS_ERR_SEM_OVF;
  885. return ((OS_SEM_CTR)0);
  886. }
  887. break;
  888. default:
  889. break;
  890. }
  891. p_sem->Ctr++; /* No */
  892. ctr = p_sem->Ctr;
  893. p_sem->TS = ts; /* Save timestamp in semaphore control block */
  894. CPU_CRITICAL_EXIT();
  895. *p_err = OS_ERR_NONE;
  896. return (ctr);
  897. }
  898. OS_CRITICAL_ENTER_CPU_EXIT();
  899. if ((opt & OS_OPT_POST_ALL) != (OS_OPT)0) { /* Post message to all tasks waiting? */
  900. cnt = p_pend_list->NbrEntries; /* Yes */
  901. } else {
  902. cnt = (OS_OBJ_QTY)1; /* No */
  903. }
  904. p_pend_data = p_pend_list->HeadPtr;
  905. while (cnt > 0u) {
  906. p_tcb = p_pend_data->TCBPtr;
  907. p_pend_data_next = p_pend_data->NextPtr;
  908. OS_Post((OS_PEND_OBJ *)((void *)p_sem),
  909. p_tcb,
  910. (void *)0,
  911. (OS_MSG_SIZE)0,
  912. ts);
  913. p_pend_data = p_pend_data_next;
  914. cnt--;
  915. }
  916. ctr = p_sem->Ctr;
  917. OS_CRITICAL_EXIT_NO_SCHED();
  918. if ((opt & OS_OPT_POST_NO_SCHED) == (OS_OPT)0) {
  919. OSSched(); /* Run the scheduler */
  920. }
  921. *p_err = OS_ERR_NONE;
  922. return (ctr);
  923. }
  924. #endif