训练营PLSR题目
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.
 
 
 
 
 
 

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