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.
 
 
 
 
 

709 lines
31 KiB

  1. /*
  2. *********************************************************************************************************
  3. * uC/OS-II
  4. * The Real-Time Kernel
  5. *
  6. * Copyright 1992-2021 Silicon Laboratories Inc. www.silabs.com
  7. *
  8. * SPDX-License-Identifier: APACHE-2.0
  9. *
  10. * This software is subject to an open source license and is distributed by
  11. * Silicon Laboratories Inc. pursuant to the terms of the Apache License,
  12. * Version 2.0 available at www.apache.org/licenses/LICENSE-2.0.
  13. *
  14. *********************************************************************************************************
  15. */
  16. /*
  17. *********************************************************************************************************
  18. *
  19. * MESSAGE MAILBOX MANAGEMENT
  20. *
  21. * Filename : os_mbox.c
  22. * Version : V2.93.01
  23. *********************************************************************************************************
  24. */
  25. #ifndef OS_MBOX_C
  26. #define OS_MBOX_C
  27. #define MICRIUM_SOURCE
  28. #ifndef OS_MASTER_FILE
  29. #include <ucos_ii.h>
  30. #endif
  31. #if OS_MBOX_EN > 0u
  32. /*
  33. *********************************************************************************************************
  34. * ACCEPT MESSAGE FROM MAILBOX
  35. *
  36. * Description: This function checks the mailbox to see if a message is available. Unlike OSMboxPend(),
  37. * OSMboxAccept() does not suspend the calling task if a message is not available.
  38. *
  39. * Arguments : pevent is a pointer to the event control block
  40. *
  41. * Returns : != (void *)0 is the message in the mailbox if one is available. The mailbox is cleared
  42. * so the next time OSMboxAccept() is called, the mailbox will be empty.
  43. * == (void *)0 if the mailbox is empty or,
  44. * if 'pevent' is a NULL pointer or,
  45. * if you didn't pass the proper event pointer.
  46. *********************************************************************************************************
  47. */
  48. #if OS_MBOX_ACCEPT_EN > 0u
  49. void *OSMboxAccept (OS_EVENT *pevent)
  50. {
  51. void *pmsg;
  52. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  53. OS_CPU_SR cpu_sr = 0u;
  54. #endif
  55. #if OS_ARG_CHK_EN > 0u
  56. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  57. return ((void *)0);
  58. }
  59. #endif
  60. if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
  61. return ((void *)0);
  62. }
  63. OS_ENTER_CRITICAL();
  64. pmsg = pevent->OSEventPtr;
  65. pevent->OSEventPtr = (void *)0; /* Clear the mailbox */
  66. OS_EXIT_CRITICAL();
  67. return (pmsg); /* Return the message received (or NULL) */
  68. }
  69. #endif
  70. /*
  71. *********************************************************************************************************
  72. * CREATE A MESSAGE MAILBOX
  73. *
  74. * Description: This function creates a message mailbox if free event control blocks are available.
  75. *
  76. * Arguments : pmsg is a pointer to a message that you wish to deposit in the mailbox. If
  77. * you set this value to the NULL pointer (i.e. (void *)0) then the mailbox
  78. * will be considered empty.
  79. *
  80. * Returns : != (OS_EVENT *)0 is a pointer to the event control clock (OS_EVENT) associated with the
  81. * created mailbox
  82. * == (OS_EVENT *)0 if no event control blocks were available
  83. *********************************************************************************************************
  84. */
  85. OS_EVENT *OSMboxCreate (void *pmsg)
  86. {
  87. OS_EVENT *pevent;
  88. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  89. OS_CPU_SR cpu_sr = 0u;
  90. #endif
  91. #ifdef OS_SAFETY_CRITICAL_IEC61508
  92. if (OSSafetyCriticalStartFlag == OS_TRUE) {
  93. OS_SAFETY_CRITICAL_EXCEPTION();
  94. return ((OS_EVENT *)0);
  95. }
  96. #endif
  97. if (OSIntNesting > 0u) { /* See if called from ISR ... */
  98. return ((OS_EVENT *)0); /* ... can't CREATE from an ISR */
  99. }
  100. OS_ENTER_CRITICAL();
  101. pevent = OSEventFreeList; /* Get next free event control block */
  102. if (OSEventFreeList != (OS_EVENT *)0) { /* See if pool of free ECB pool was empty */
  103. OSEventFreeList = (OS_EVENT *)OSEventFreeList->OSEventPtr;
  104. }
  105. OS_EXIT_CRITICAL();
  106. if (pevent != (OS_EVENT *)0) {
  107. pevent->OSEventType = OS_EVENT_TYPE_MBOX;
  108. pevent->OSEventCnt = 0u;
  109. pevent->OSEventPtr = pmsg; /* Deposit message in event control block */
  110. #if OS_EVENT_NAME_EN > 0u
  111. pevent->OSEventName = (INT8U *)(void *)"?";
  112. #endif
  113. OS_EventWaitListInit(pevent);
  114. OS_TRACE_MBOX_CREATE(pevent, pevent->OSEventName);
  115. }
  116. return (pevent); /* Return pointer to event control block */
  117. }
  118. /*
  119. *********************************************************************************************************
  120. * DELETE A MAIBOX
  121. *
  122. * Description: This function deletes a mailbox and readies all tasks pending on the mailbox.
  123. *
  124. * Arguments : pevent is a pointer to the event control block associated with the desired
  125. * mailbox.
  126. *
  127. * opt determines delete options as follows:
  128. * opt == OS_DEL_NO_PEND Delete the mailbox ONLY if no task pending
  129. * opt == OS_DEL_ALWAYS Deletes the mailbox even if tasks are waiting.
  130. * In this case, all the tasks pending will be readied.
  131. *
  132. * perr is a pointer to an error code that can contain one of the following values:
  133. * OS_ERR_NONE The call was successful and the mailbox was deleted
  134. * OS_ERR_DEL_ISR If you attempted to delete the mailbox from an ISR
  135. * OS_ERR_INVALID_OPT An invalid option was specified
  136. * OS_ERR_ILLEGAL_DEL_RUN_TIME If you tried to delete a mailbox after safety
  137. * critical operation started.
  138. * OS_ERR_TASK_WAITING One or more tasks were waiting on the mailbox
  139. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mailbox
  140. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  141. *
  142. * Returns : pevent upon error
  143. * (OS_EVENT *)0 if the mailbox 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 mailbox MUST check the return code of OSMboxPend().
  147. * 2) OSMboxAccept() callers will not know that the intended mailbox has been deleted!
  148. * 3) This call can potentially disable interrupts for a long time. The interrupt disable
  149. * time is directly proportional to the number of tasks waiting on the mailbox.
  150. * 4) Because ALL tasks pending on the mailbox will be readied, you MUST be careful in
  151. * applications where the mailbox is used for mutual exclusion because the resource(s)
  152. * will no longer be guarded by the mailbox.
  153. * 5) All tasks that were waiting for the mailbox will be readied and returned an
  154. * OS_ERR_PEND_ABORT if OSMboxDel() was called with OS_DEL_ALWAYS
  155. *********************************************************************************************************
  156. */
  157. #if OS_MBOX_DEL_EN > 0u
  158. OS_EVENT *OSMboxDel (OS_EVENT *pevent,
  159. INT8U opt,
  160. INT8U *perr)
  161. {
  162. BOOLEAN tasks_waiting;
  163. OS_EVENT *pevent_return;
  164. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  165. OS_CPU_SR cpu_sr = 0u;
  166. #endif
  167. #ifdef OS_SAFETY_CRITICAL
  168. if (perr == (INT8U *)0) {
  169. OS_SAFETY_CRITICAL_EXCEPTION();
  170. return ((OS_EVENT *)0);
  171. }
  172. #endif
  173. #ifdef OS_SAFETY_CRITICAL_IEC61508
  174. if (OSSafetyCriticalStartFlag == OS_TRUE) {
  175. OS_SAFETY_CRITICAL_EXCEPTION();
  176. *perr = OS_ERR_ILLEGAL_DEL_RUN_TIME;
  177. return ((OS_EVENT *)0);
  178. }
  179. #endif
  180. #if OS_ARG_CHK_EN > 0u
  181. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  182. *perr = OS_ERR_PEVENT_NULL;
  183. return (pevent);
  184. }
  185. #endif
  186. OS_TRACE_MBOX_DEL_ENTER(pevent, opt);
  187. if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
  188. *perr = OS_ERR_EVENT_TYPE;
  189. OS_TRACE_MBOX_DEL_EXIT(*perr);
  190. return (pevent);
  191. }
  192. if (OSIntNesting > 0u) { /* See if called from ISR ... */
  193. *perr = OS_ERR_DEL_ISR; /* ... can't DELETE from an ISR */
  194. OS_TRACE_MBOX_DEL_EXIT(*perr);
  195. return (pevent);
  196. }
  197. OS_ENTER_CRITICAL();
  198. if (pevent->OSEventGrp != 0u) { /* See if any tasks waiting on mailbox */
  199. tasks_waiting = OS_TRUE; /* Yes */
  200. } else {
  201. tasks_waiting = OS_FALSE; /* No */
  202. }
  203. switch (opt) {
  204. case OS_DEL_NO_PEND: /* Delete mailbox only if no task waiting */
  205. if (tasks_waiting == OS_FALSE) {
  206. #if OS_EVENT_NAME_EN > 0u
  207. pevent->OSEventName = (INT8U *)(void *)"?";
  208. #endif
  209. pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
  210. pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
  211. pevent->OSEventCnt = 0u;
  212. OSEventFreeList = pevent; /* Get next free event control block */
  213. OS_EXIT_CRITICAL();
  214. *perr = OS_ERR_NONE;
  215. pevent_return = (OS_EVENT *)0; /* Mailbox has been deleted */
  216. } else {
  217. OS_EXIT_CRITICAL();
  218. *perr = OS_ERR_TASK_WAITING;
  219. pevent_return = pevent;
  220. }
  221. break;
  222. case OS_DEL_ALWAYS: /* Always delete the mailbox */
  223. while (pevent->OSEventGrp != 0u) { /* Ready ALL tasks waiting for mailbox */
  224. (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);
  225. }
  226. #if OS_EVENT_NAME_EN > 0u
  227. pevent->OSEventName = (INT8U *)(void *)"?";
  228. #endif
  229. pevent->OSEventType = OS_EVENT_TYPE_UNUSED;
  230. pevent->OSEventPtr = OSEventFreeList; /* Return Event Control Block to free list */
  231. pevent->OSEventCnt = 0u;
  232. OSEventFreeList = pevent; /* Get next free event control block */
  233. OS_EXIT_CRITICAL();
  234. if (tasks_waiting == OS_TRUE) { /* Reschedule only if task(s) were waiting */
  235. OS_Sched(); /* Find highest priority task ready to run */
  236. }
  237. *perr = OS_ERR_NONE;
  238. pevent_return = (OS_EVENT *)0; /* Mailbox has been deleted */
  239. break;
  240. default:
  241. OS_EXIT_CRITICAL();
  242. *perr = OS_ERR_INVALID_OPT;
  243. pevent_return = pevent;
  244. break;
  245. }
  246. OS_TRACE_MBOX_DEL_EXIT(*perr);
  247. return (pevent_return);
  248. }
  249. #endif
  250. /*
  251. *********************************************************************************************************
  252. * PEND ON MAILBOX FOR A MESSAGE
  253. *
  254. * Description: This function waits for a message to be sent to a mailbox
  255. *
  256. * Arguments : pevent is a pointer to the event control block associated with the desired mailbox
  257. *
  258. * timeout is an optional timeout period (in clock ticks). If non-zero, your task will
  259. * wait for a message to arrive at the mailbox up to the amount of time
  260. * specified by this argument. If you specify 0, however, your task will wait
  261. * forever at the specified mailbox or, until a message arrives.
  262. *
  263. * perr is a pointer to where an error message will be deposited. Possible error
  264. * messages are:
  265. *
  266. * OS_ERR_NONE The call was successful and your task received a
  267. * message.
  268. * OS_ERR_TIMEOUT A message was not received within the specified 'timeout'.
  269. * OS_ERR_PEND_ABORT The wait on the mailbox was aborted.
  270. * OS_ERR_EVENT_TYPE Invalid event type
  271. * OS_ERR_PEND_ISR If you called this function from an ISR and the result
  272. * would lead to a suspension.
  273. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
  274. * OS_ERR_PEND_LOCKED If you called this function when the scheduler is locked
  275. *
  276. * Returns : != (void *)0 is a pointer to the message received
  277. * == (void *)0 if no message was received or,
  278. * if 'pevent' is a NULL pointer or,
  279. * if you didn't pass the proper pointer to the event control block.
  280. *********************************************************************************************************
  281. */
  282. void *OSMboxPend (OS_EVENT *pevent,
  283. INT32U timeout,
  284. INT8U *perr)
  285. {
  286. void *pmsg;
  287. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  288. OS_CPU_SR cpu_sr = 0u;
  289. #endif
  290. #ifdef OS_SAFETY_CRITICAL
  291. if (perr == (INT8U *)0) {
  292. OS_SAFETY_CRITICAL_EXCEPTION();
  293. return ((void *)0);
  294. }
  295. #endif
  296. #if OS_ARG_CHK_EN > 0u
  297. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  298. *perr = OS_ERR_PEVENT_NULL;
  299. return ((void *)0);
  300. }
  301. #endif
  302. OS_TRACE_MBOX_PEND_ENTER(pevent, timeout);
  303. if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
  304. *perr = OS_ERR_EVENT_TYPE;
  305. OS_TRACE_MBOX_PEND_EXIT(*perr);
  306. return ((void *)0);
  307. }
  308. if (OSIntNesting > 0u) { /* See if called from ISR ... */
  309. *perr = OS_ERR_PEND_ISR; /* ... can't PEND from an ISR */
  310. OS_TRACE_MBOX_PEND_EXIT(*perr);
  311. return ((void *)0);
  312. }
  313. if (OSLockNesting > 0u) { /* See if called with scheduler locked ... */
  314. *perr = OS_ERR_PEND_LOCKED; /* ... can't PEND when locked */
  315. OS_TRACE_MBOX_PEND_EXIT(*perr);
  316. return ((void *)0);
  317. }
  318. OS_ENTER_CRITICAL();
  319. pmsg = pevent->OSEventPtr;
  320. if (pmsg != (void *)0) { /* See if there is already a message */
  321. pevent->OSEventPtr = (void *)0; /* Clear the mailbox */
  322. OS_EXIT_CRITICAL();
  323. *perr = OS_ERR_NONE;
  324. OS_TRACE_MBOX_PEND_EXIT(*perr);
  325. return (pmsg); /* Return the message received (or NULL) */
  326. }
  327. OSTCBCur->OSTCBStat |= OS_STAT_MBOX; /* Message not available, task will pend */
  328. OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK;
  329. OSTCBCur->OSTCBDly = timeout; /* Load timeout in TCB */
  330. OS_EventTaskWait(pevent); /* Suspend task until event or timeout occurs */
  331. OS_EXIT_CRITICAL();
  332. OS_Sched(); /* Find next highest priority task ready to run */
  333. OS_ENTER_CRITICAL();
  334. switch (OSTCBCur->OSTCBStatPend) { /* See if we timed-out or aborted */
  335. case OS_STAT_PEND_OK:
  336. pmsg = OSTCBCur->OSTCBMsg;
  337. *perr = OS_ERR_NONE;
  338. break;
  339. case OS_STAT_PEND_ABORT:
  340. pmsg = (void *)0;
  341. *perr = OS_ERR_PEND_ABORT; /* Indicate that we aborted */
  342. break;
  343. case OS_STAT_PEND_TO:
  344. default:
  345. OS_EventTaskRemove(OSTCBCur, pevent);
  346. pmsg = (void *)0;
  347. *perr = OS_ERR_TIMEOUT; /* Indicate that we didn't get event within TO */
  348. break;
  349. }
  350. OSTCBCur->OSTCBStat = OS_STAT_RDY; /* Set task status to ready */
  351. OSTCBCur->OSTCBStatPend = OS_STAT_PEND_OK; /* Clear pend status */
  352. OSTCBCur->OSTCBEventPtr = (OS_EVENT *)0; /* Clear event pointers */
  353. #if (OS_EVENT_MULTI_EN > 0u)
  354. OSTCBCur->OSTCBEventMultiPtr = (OS_EVENT **)0;
  355. OSTCBCur->OSTCBEventMultiRdy = (OS_EVENT *)0;
  356. #endif
  357. OSTCBCur->OSTCBMsg = (void *)0; /* Clear received message */
  358. OS_EXIT_CRITICAL();
  359. OS_TRACE_MBOX_PEND_EXIT(*perr);
  360. return (pmsg); /* Return received message */
  361. }
  362. /*
  363. *********************************************************************************************************
  364. * ABORT WAITING ON A MESSAGE MAILBOX
  365. *
  366. * Description: This function aborts & readies any tasks currently waiting on a mailbox. This function
  367. * should be used to fault-abort the wait on the mailbox, rather than to normally signal
  368. * the mailbox via OSMboxPost() or OSMboxPostOpt().
  369. *
  370. * Arguments : pevent is a pointer to the event control block associated with the desired mailbox.
  371. *
  372. * opt determines the type of ABORT performed:
  373. * OS_PEND_OPT_NONE ABORT wait for a single task (HPT) waiting on the
  374. * mailbox
  375. * OS_PEND_OPT_BROADCAST ABORT wait for ALL tasks that are waiting on the
  376. * mailbox
  377. *
  378. * perr is a pointer to where an error message will be deposited. Possible error
  379. * messages are:
  380. *
  381. * OS_ERR_NONE No tasks were waiting on the mailbox.
  382. * OS_ERR_PEND_ABORT At least one task waiting on the mailbox was readied
  383. * and informed of the aborted wait; check return value
  384. * for the number of tasks whose wait on the mailbox
  385. * was aborted.
  386. * OS_ERR_EVENT_TYPE If you didn't pass a pointer to a mailbox.
  387. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer.
  388. *
  389. * Returns : == 0 if no tasks were waiting on the mailbox, or upon error.
  390. * > 0 if one or more tasks waiting on the mailbox are now readied and informed.
  391. *********************************************************************************************************
  392. */
  393. #if OS_MBOX_PEND_ABORT_EN > 0u
  394. INT8U OSMboxPendAbort (OS_EVENT *pevent,
  395. INT8U opt,
  396. INT8U *perr)
  397. {
  398. INT8U nbr_tasks;
  399. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  400. OS_CPU_SR cpu_sr = 0u;
  401. #endif
  402. #ifdef OS_SAFETY_CRITICAL
  403. if (perr == (INT8U *)0) {
  404. OS_SAFETY_CRITICAL_EXCEPTION();
  405. return (0u);
  406. }
  407. #endif
  408. #if OS_ARG_CHK_EN > 0u
  409. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  410. *perr = OS_ERR_PEVENT_NULL;
  411. return (0u);
  412. }
  413. #endif
  414. if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
  415. *perr = OS_ERR_EVENT_TYPE;
  416. return (0u);
  417. }
  418. OS_ENTER_CRITICAL();
  419. if (pevent->OSEventGrp != 0u) { /* See if any task waiting on mailbox? */
  420. nbr_tasks = 0u;
  421. switch (opt) {
  422. case OS_PEND_OPT_BROADCAST: /* Do we need to abort ALL waiting tasks? */
  423. while (pevent->OSEventGrp != 0u) { /* Yes, ready ALL tasks waiting on mailbox */
  424. (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);
  425. nbr_tasks++;
  426. }
  427. break;
  428. case OS_PEND_OPT_NONE:
  429. default: /* No, ready HPT waiting on mailbox */
  430. (void)OS_EventTaskRdy(pevent, (void *)0, OS_STAT_MBOX, OS_STAT_PEND_ABORT);
  431. nbr_tasks++;
  432. break;
  433. }
  434. OS_EXIT_CRITICAL();
  435. OS_Sched(); /* Find HPT ready to run */
  436. *perr = OS_ERR_PEND_ABORT;
  437. return (nbr_tasks);
  438. }
  439. OS_EXIT_CRITICAL();
  440. *perr = OS_ERR_NONE;
  441. return (0u); /* No tasks waiting on mailbox */
  442. }
  443. #endif
  444. /*
  445. *********************************************************************************************************
  446. * POST MESSAGE TO A MAILBOX
  447. *
  448. * Description: This function sends a message to a mailbox
  449. *
  450. * Arguments : pevent is a pointer to the event control block associated with the desired mailbox
  451. *
  452. * pmsg is a pointer to the message to send. You MUST NOT send a NULL pointer.
  453. *
  454. * Returns : OS_ERR_NONE The call was successful and the message was sent
  455. * OS_ERR_MBOX_FULL If the mailbox already contains a message. You can can only send one
  456. * message at a time and thus, the message MUST be consumed before you
  457. * are allowed to send another one.
  458. * OS_ERR_EVENT_TYPE If you are attempting to post to a non mailbox.
  459. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
  460. * OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer
  461. *
  462. * Note(s) : 1) HPT means Highest Priority Task
  463. *********************************************************************************************************
  464. */
  465. #if OS_MBOX_POST_EN > 0u
  466. INT8U OSMboxPost (OS_EVENT *pevent,
  467. void *pmsg)
  468. {
  469. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  470. OS_CPU_SR cpu_sr = 0u;
  471. #endif
  472. #if OS_ARG_CHK_EN > 0u
  473. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  474. return (OS_ERR_PEVENT_NULL);
  475. }
  476. if (pmsg == (void *)0) { /* Make sure we are not posting a NULL pointer */
  477. return (OS_ERR_POST_NULL_PTR);
  478. }
  479. #endif
  480. OS_TRACE_MBOX_POST_ENTER(pevent);
  481. if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
  482. OS_TRACE_MBOX_POST_EXIT(OS_ERR_EVENT_TYPE);
  483. return (OS_ERR_EVENT_TYPE);
  484. }
  485. OS_ENTER_CRITICAL();
  486. if (pevent->OSEventGrp != 0u) { /* See if any task pending on mailbox */
  487. /* Ready HPT waiting on event */
  488. (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
  489. OS_EXIT_CRITICAL();
  490. OS_Sched(); /* Find highest priority task ready to run */
  491. OS_TRACE_MBOX_POST_EXIT(OS_ERR_NONE);
  492. return (OS_ERR_NONE);
  493. }
  494. if (pevent->OSEventPtr != (void *)0) { /* Make sure mailbox doesn't already have a msg */
  495. OS_EXIT_CRITICAL();
  496. OS_TRACE_MBOX_POST_EXIT(OS_ERR_MBOX_FULL);
  497. return (OS_ERR_MBOX_FULL);
  498. }
  499. pevent->OSEventPtr = pmsg; /* Place message in mailbox */
  500. OS_EXIT_CRITICAL();
  501. OS_TRACE_MBOX_POST_EXIT(OS_ERR_NONE);
  502. return (OS_ERR_NONE);
  503. }
  504. #endif
  505. /*
  506. *********************************************************************************************************
  507. * POST MESSAGE TO A MAILBOX
  508. *
  509. * Description: This function sends a message to a mailbox
  510. *
  511. * Arguments : pevent is a pointer to the event control block associated with the desired mailbox
  512. *
  513. * pmsg is a pointer to the message to send. You MUST NOT send a NULL pointer.
  514. *
  515. * opt determines the type of POST performed:
  516. * OS_POST_OPT_NONE POST to a single waiting task
  517. * (Identical to OSMboxPost())
  518. * OS_POST_OPT_BROADCAST POST to ALL tasks that are waiting on the mailbox
  519. *
  520. * OS_POST_OPT_NO_SCHED Indicates that the scheduler will NOT be invoked
  521. *
  522. * Returns : OS_ERR_NONE The call was successful and the message was sent
  523. * OS_ERR_MBOX_FULL If the mailbox already contains a message. You can can only send one
  524. * message at a time and thus, the message MUST be consumed before you
  525. * are allowed to send another one.
  526. * OS_ERR_EVENT_TYPE If you are attempting to post to a non mailbox.
  527. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
  528. * OS_ERR_POST_NULL_PTR If you are attempting to post a NULL pointer
  529. *
  530. * Note(s) : 1) HPT means Highest Priority Task
  531. *
  532. * Warning : Interrupts can be disabled for a long time if you do a 'broadcast'. In fact, the
  533. * interrupt disable time is proportional to the number of tasks waiting on the mailbox.
  534. *********************************************************************************************************
  535. */
  536. #if OS_MBOX_POST_OPT_EN > 0u
  537. INT8U OSMboxPostOpt (OS_EVENT *pevent,
  538. void *pmsg,
  539. INT8U opt)
  540. {
  541. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  542. OS_CPU_SR cpu_sr = 0u;
  543. #endif
  544. #if OS_ARG_CHK_EN > 0u
  545. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  546. return (OS_ERR_PEVENT_NULL);
  547. }
  548. if (pmsg == (void *)0) { /* Make sure we are not posting a NULL pointer */
  549. return (OS_ERR_POST_NULL_PTR);
  550. }
  551. #endif
  552. OS_TRACE_MBOX_POST_OPT_ENTER(pevent, opt);
  553. if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
  554. OS_TRACE_MBOX_POST_OPT_EXIT(OS_ERR_EVENT_TYPE);
  555. return (OS_ERR_EVENT_TYPE);
  556. }
  557. OS_ENTER_CRITICAL();
  558. if (pevent->OSEventGrp != 0u) { /* See if any task pending on mailbox */
  559. if ((opt & OS_POST_OPT_BROADCAST) != 0x00u) { /* Do we need to post msg to ALL waiting tasks ? */
  560. while (pevent->OSEventGrp != 0u) { /* Yes, Post to ALL tasks waiting on mailbox */
  561. (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
  562. }
  563. } else { /* No, Post to HPT waiting on mbox */
  564. (void)OS_EventTaskRdy(pevent, pmsg, OS_STAT_MBOX, OS_STAT_PEND_OK);
  565. }
  566. OS_EXIT_CRITICAL();
  567. if ((opt & OS_POST_OPT_NO_SCHED) == 0u) { /* See if scheduler needs to be invoked */
  568. OS_Sched(); /* Find HPT ready to run */
  569. }
  570. OS_TRACE_MBOX_POST_OPT_EXIT(OS_ERR_NONE);
  571. return (OS_ERR_NONE);
  572. }
  573. if (pevent->OSEventPtr != (void *)0) { /* Make sure mailbox doesn't already have a msg */
  574. OS_EXIT_CRITICAL();
  575. OS_TRACE_MBOX_POST_OPT_EXIT(OS_ERR_MBOX_FULL);
  576. return (OS_ERR_MBOX_FULL);
  577. }
  578. pevent->OSEventPtr = pmsg; /* Place message in mailbox */
  579. OS_EXIT_CRITICAL();
  580. OS_TRACE_MBOX_POST_OPT_EXIT(OS_ERR_NONE);
  581. return (OS_ERR_NONE);
  582. }
  583. #endif
  584. /*
  585. *********************************************************************************************************
  586. * QUERY A MESSAGE MAILBOX
  587. *
  588. * Description: This function obtains information about a message mailbox.
  589. *
  590. * Arguments : pevent is a pointer to the event control block associated with the desired mailbox
  591. *
  592. * p_mbox_data is a pointer to a structure that will contain information about the message
  593. * mailbox.
  594. *
  595. * Returns : OS_ERR_NONE The call was successful and the message was sent
  596. * OS_ERR_EVENT_TYPE If you are attempting to obtain data from a non mailbox.
  597. * OS_ERR_PEVENT_NULL If 'pevent' is a NULL pointer
  598. * OS_ERR_PDATA_NULL If 'p_mbox_data' is a NULL pointer
  599. *********************************************************************************************************
  600. */
  601. #if OS_MBOX_QUERY_EN > 0u
  602. INT8U OSMboxQuery (OS_EVENT *pevent,
  603. OS_MBOX_DATA *p_mbox_data)
  604. {
  605. INT8U i;
  606. OS_PRIO *psrc;
  607. OS_PRIO *pdest;
  608. #if OS_CRITICAL_METHOD == 3u /* Allocate storage for CPU status register */
  609. OS_CPU_SR cpu_sr = 0u;
  610. #endif
  611. #if OS_ARG_CHK_EN > 0u
  612. if (pevent == (OS_EVENT *)0) { /* Validate 'pevent' */
  613. return (OS_ERR_PEVENT_NULL);
  614. }
  615. if (p_mbox_data == (OS_MBOX_DATA *)0) { /* Validate 'p_mbox_data' */
  616. return (OS_ERR_PDATA_NULL);
  617. }
  618. #endif
  619. if (pevent->OSEventType != OS_EVENT_TYPE_MBOX) { /* Validate event block type */
  620. return (OS_ERR_EVENT_TYPE);
  621. }
  622. OS_ENTER_CRITICAL();
  623. p_mbox_data->OSEventGrp = pevent->OSEventGrp; /* Copy message mailbox wait list */
  624. psrc = &pevent->OSEventTbl[0];
  625. pdest = &p_mbox_data->OSEventTbl[0];
  626. for (i = 0u; i < OS_EVENT_TBL_SIZE; i++) {
  627. *pdest++ = *psrc++;
  628. }
  629. p_mbox_data->OSMsg = pevent->OSEventPtr; /* Get message from mailbox */
  630. OS_EXIT_CRITICAL();
  631. return (OS_ERR_NONE);
  632. }
  633. #endif /* OS_MBOX_QUERY_EN */
  634. #endif /* OS_MBOX_EN */
  635. #endif /* OS_MBOX_C */