os_msg.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  1. /*
  2. ************************************************************************************************************************
  3. * uC/OS-III
  4. * The Real-Time Kernel
  5. *
  6. * (c) Copyright 2009-2011; Micrium, Inc.; Weston, FL
  7. * All rights reserved. Protected by international copyright laws.
  8. *
  9. * MESSAGE HANDLING SERVICES
  10. *
  11. * File : OS_MSG.C
  12. * By : JJL
  13. * Version : V3.02.00
  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 contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
  30. ************************************************************************************************************************
  31. */
  32. #include <os.h>
  33. #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
  34. const CPU_CHAR *os_msg__c = "$Id: $";
  35. #endif
  36. #if OS_MSG_EN > 0u
  37. /*
  38. ************************************************************************************************************************
  39. * EXTEND THE POOL OF 'OS_MSG'
  40. *
  41. * Description: This function is called by your application to add OS_MSGs to the free list of OS_MSGs
  42. *
  43. * Arguments : p_msg is a pointer to the base address of an array of OS_MSG and should be declared as follows:
  44. *
  45. * OS_MSG MyNewMsgTbl[size];
  46. *
  47. * size is the size of the above array
  48. *
  49. * p_err is a pointer to a variable that will contain an error code returned by this function.
  50. *
  51. * OS_ERR_MSG_POOL_NULL_PTR
  52. * OS_ERR_MSG_POOL_EMPTY
  53. * OS_ERR_NONE
  54. *
  55. * Returns : none
  56. ************************************************************************************************************************
  57. */
  58. void OSMsgPoolExtend (OS_MSG *p_msg,
  59. OS_MSG_QTY size,
  60. OS_ERR *p_err)
  61. {
  62. #ifdef OS_SAFETY_CRITICAL
  63. if (p_err == (OS_ERR *)0) {
  64. OS_SAFETY_CRITICAL_EXCEPTION();
  65. return;
  66. }
  67. #endif
  68. #if OS_CFG_ARG_CHK_EN > 0u
  69. if (p_msg == (OS_MSG *)0) {
  70. *p_err = OS_ERR_MSG_POOL_NULL_PTR;
  71. return;
  72. }
  73. if (size == (OS_MSG_QTY)0) {
  74. *p_err = OS_ERR_MSG_POOL_EMPTY;
  75. return;
  76. }
  77. #endif
  78. OS_MsgPoolCreate(p_msg, /* Create the singly linked list */
  79. size);
  80. p_msg[size - 1u].NextPtr = OSMsgPool.NextPtr; /* Link last OS_MSG of new list to current pool */
  81. OSMsgPool.NextPtr = p_msg;
  82. OSMsgPool.NbrFree += size; /* All new OS_MSGs are now available */
  83. *p_err = OS_ERR_NONE;
  84. }
  85. /*$PAGE*/
  86. /*
  87. ************************************************************************************************************************
  88. * CREATE A LINKED LIST OF 'OS_MSG'
  89. *
  90. * Description: This function is called to create a singly linked list of OS_MSGs which is used as a pool of available
  91. * OS_MSGs to be used for sending messages.
  92. *
  93. * Arguments : p_msg is a pointer to the base address of an array of OS_MSG and should be declared as follows:
  94. * -----
  95. * OS_MSG MyMsgTbl[size];
  96. *
  97. * size is the size of the above array
  98. *
  99. * Returns : none
  100. *
  101. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  102. ************************************************************************************************************************
  103. */
  104. void OS_MsgPoolCreate (OS_MSG *p_msg,
  105. OS_MSG_QTY size)
  106. {
  107. OS_MSG *p_msg1;
  108. OS_MSG *p_msg2;
  109. OS_MSG_QTY i;
  110. OS_MSG_QTY loops;
  111. p_msg1 = p_msg;
  112. p_msg2 = p_msg;
  113. p_msg2++;
  114. loops = size - 1u;
  115. for (i = 0u; i < loops; i++) { /* Init. list of free OS_MSGs */
  116. p_msg1->NextPtr = p_msg2;
  117. p_msg1->MsgPtr = (void *)0;
  118. p_msg1->MsgSize = (OS_MSG_SIZE)0u;
  119. p_msg1->MsgTS = (CPU_TS )0u;
  120. p_msg1++;
  121. p_msg2++;
  122. }
  123. p_msg1->NextPtr = (OS_MSG *)0; /* Last OS_MSG */
  124. p_msg1->MsgPtr = (void *)0;
  125. p_msg1->MsgSize = (OS_MSG_SIZE)0u;
  126. p_msg1->MsgTS = (CPU_TS )0u;
  127. }
  128. /*$PAGE*/
  129. /*
  130. ************************************************************************************************************************
  131. * INITIALIZE THE POOL OF 'OS_MSG'
  132. *
  133. * Description: This function is called by OSInit() to initialize the free list of OS_MSGs.
  134. *
  135. * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
  136. *
  137. * OS_ERR_MSG_POOL_NULL_PTR
  138. * OS_ERR_MSG_POOL_EMPTY
  139. * OS_ERR_NONE
  140. *
  141. * Returns : none
  142. *
  143. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  144. ************************************************************************************************************************
  145. */
  146. void OS_MsgPoolInit (OS_ERR *p_err)
  147. {
  148. #ifdef OS_SAFETY_CRITICAL
  149. if (p_err == (OS_ERR *)0) {
  150. OS_SAFETY_CRITICAL_EXCEPTION();
  151. return;
  152. }
  153. #endif
  154. #if OS_CFG_ARG_CHK_EN > 0u
  155. if (OSCfg_MsgPoolBasePtr == (OS_MSG *)0) {
  156. *p_err = OS_ERR_MSG_POOL_NULL_PTR;
  157. return;
  158. }
  159. if (OSCfg_MsgPoolSize == (OS_MSG_QTY)0) {
  160. *p_err = OS_ERR_MSG_POOL_EMPTY;
  161. return;
  162. }
  163. #endif
  164. OS_MsgPoolCreate(OSCfg_MsgPoolBasePtr,
  165. OSCfg_MsgPoolSize);
  166. OSMsgPool.NextPtr = OSCfg_MsgPoolBasePtr;
  167. OSMsgPool.NbrFree = OSCfg_MsgPoolSize;
  168. OSMsgPool.NbrUsed = (OS_MSG_QTY)0;
  169. *p_err = OS_ERR_NONE;
  170. }
  171. /*$PAGE*/
  172. /*
  173. ************************************************************************************************************************
  174. * RESET MESSAGE QUEUE ENTRIES PEAK TRACKING
  175. *
  176. * Description: This function clear the peak detection mechanism of the message queue
  177. *
  178. * Arguments : p_msg_q is a pointer to the OS_MSG_Q structure
  179. * -------
  180. *
  181. * Returns : none
  182. *
  183. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  184. ************************************************************************************************************************
  185. */
  186. void OS_MsgQEntriesPeakReset (OS_MSG_Q *p_msg_q)
  187. {
  188. CPU_SR_ALLOC();
  189. CPU_CRITICAL_ENTER();
  190. p_msg_q->NbrEntriesMax = (OS_MSG_QTY)0;
  191. CPU_CRITICAL_EXIT();
  192. }
  193. /*$PAGE*/
  194. /*
  195. ************************************************************************************************************************
  196. * RELEASE ALL MESSAGE IN MESSAGE QUEUE
  197. *
  198. * Description: This function returns all the messages in a message queue to the free list.
  199. *
  200. * Arguments : p_msg_q is a pointer to the OS_MSG_Q structure containing messages to free.
  201. * -------
  202. *
  203. * Returns : the number of OS_MSGs returned to the free list
  204. *
  205. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  206. ************************************************************************************************************************
  207. */
  208. OS_MSG_QTY OS_MsgQFreeAll (OS_MSG_Q *p_msg_q)
  209. {
  210. OS_MSG *p_msg;
  211. OS_MSG_QTY qty;
  212. qty = p_msg_q->NbrEntries; /* Get the number of OS_MSGs being freed */
  213. if (p_msg_q->NbrEntries > (OS_MSG_QTY)0) {
  214. p_msg = p_msg_q->InPtr; /* Point to end of message chain */
  215. p_msg->NextPtr = OSMsgPool.NextPtr;
  216. OSMsgPool.NextPtr = p_msg_q->OutPtr; /* Point to beginning of message chain */
  217. OSMsgPool.NbrUsed -= p_msg_q->NbrEntries; /* Update statistics for free list of messages */
  218. OSMsgPool.NbrFree += p_msg_q->NbrEntries;
  219. p_msg_q->NbrEntries = (OS_MSG_QTY)0; /* Flush the message queue */
  220. p_msg_q->NbrEntriesMax = (OS_MSG_QTY)0;
  221. p_msg_q->InPtr = (OS_MSG *)0;
  222. p_msg_q->OutPtr = (OS_MSG *)0;
  223. }
  224. return (qty);
  225. }
  226. /*$PAGE*/
  227. /*
  228. ************************************************************************************************************************
  229. * INITIALIZE A MESSAGE QUEUE
  230. *
  231. * Description: This function is called to initialize a message queue
  232. *
  233. * Arguments : p_msg_q is a pointer to the message queue to initialize
  234. * -------
  235. *
  236. * max is the maximum number of entries that a message queue can have.
  237. *
  238. * Returns : none
  239. *
  240. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  241. ************************************************************************************************************************
  242. */
  243. void OS_MsgQInit (OS_MSG_Q *p_msg_q,
  244. OS_MSG_QTY size)
  245. {
  246. p_msg_q->NbrEntriesSize = (OS_MSG_QTY)size;
  247. p_msg_q->NbrEntries = (OS_MSG_QTY)0;
  248. p_msg_q->NbrEntriesMax = (OS_MSG_QTY)0;
  249. p_msg_q->InPtr = (OS_MSG *)0;
  250. p_msg_q->OutPtr = (OS_MSG *)0;
  251. }
  252. /*$PAGE*/
  253. /*
  254. ************************************************************************************************************************
  255. * RETRIEVE MESSAGE FROM MESSAGE QUEUE
  256. *
  257. * Description: This function retrieves a message from a message queue
  258. *
  259. * Arguments : p_msg_q is a pointer to the message queue where we want to extract the message from
  260. * -------
  261. *
  262. * p_msg_size is a pointer to where the size (in bytes) of the message will be placed
  263. *
  264. * p_ts is a pointer to where the time stamp will be placed
  265. *
  266. * p_err is a pointer to an error code that will be returned from this call.
  267. *
  268. * OS_ERR_Q_EMPTY
  269. * OS_ERR_NONE
  270. *
  271. * Returns : The message (a pointer)
  272. *
  273. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  274. ************************************************************************************************************************
  275. */
  276. void *OS_MsgQGet (OS_MSG_Q *p_msg_q,
  277. OS_MSG_SIZE *p_msg_size,
  278. CPU_TS *p_ts,
  279. OS_ERR *p_err)
  280. {
  281. OS_MSG *p_msg;
  282. void *p_void;
  283. #ifdef OS_SAFETY_CRITICAL
  284. if (p_err == (OS_ERR *)0) {
  285. OS_SAFETY_CRITICAL_EXCEPTION();
  286. return ((void *)0);
  287. }
  288. #endif
  289. if (p_msg_q->NbrEntries == (OS_MSG_QTY)0) {
  290. *p_msg_size = (OS_MSG_SIZE)0;
  291. if (p_ts != (CPU_TS *)0) {
  292. *p_ts = (CPU_TS )0;
  293. }
  294. *p_err = OS_ERR_Q_EMPTY;
  295. return ((void *)0);
  296. }
  297. p_msg = p_msg_q->OutPtr;
  298. p_void = p_msg->MsgPtr;
  299. *p_msg_size = p_msg->MsgSize;
  300. if (p_ts != (CPU_TS *)0) {
  301. *p_ts = p_msg->MsgTS;
  302. }
  303. p_msg_q->OutPtr = p_msg->NextPtr;
  304. if (p_msg_q->OutPtr == (OS_MSG *)0) {
  305. p_msg_q->InPtr = (OS_MSG *)0;
  306. p_msg_q->NbrEntries = (OS_MSG_QTY)0;
  307. } else {
  308. p_msg_q->NbrEntries--;
  309. }
  310. p_msg->NextPtr = OSMsgPool.NextPtr; /* Return message control block to free list */
  311. OSMsgPool.NextPtr = p_msg;
  312. OSMsgPool.NbrFree++;
  313. OSMsgPool.NbrUsed--;
  314. *p_err = OS_ERR_NONE;
  315. return (p_void);
  316. }
  317. /*
  318. ************************************************************************************************************************
  319. * DEPOSIT MESSAGE IN MESSAGE QUEUE
  320. *
  321. * Description: This function places a message in a message queue
  322. *
  323. * Arguments : p_msg_q is a pointer to the OS_TCB of the task to post the message to
  324. * -------
  325. *
  326. * p_void is a pointer to the message to send.
  327. *
  328. * msg_size is the size of the message (in bytes)
  329. *
  330. * opt specifies whether the message will be posted in FIFO or LIFO order
  331. *
  332. * OS_OPT_POST_FIFO
  333. * OS_OPT_POST_LIFO
  334. *
  335. * ts is a timestamp as to when the message was posted
  336. *
  337. * p_err is a pointer to a variable that will contain an error code returned by this function.
  338. *
  339. * OS_ERR_Q_MAX if the queue is full
  340. * OS_ERR_MSG_POOL_EMPTY if we no longer have any OS_MSG to use
  341. * OS_ERR_NONE the message was deposited in the queue
  342. *
  343. * Returns : none
  344. *
  345. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  346. ************************************************************************************************************************
  347. */
  348. void OS_MsgQPut (OS_MSG_Q *p_msg_q,
  349. void *p_void,
  350. OS_MSG_SIZE msg_size,
  351. OS_OPT opt,
  352. CPU_TS ts,
  353. OS_ERR *p_err)
  354. {
  355. OS_MSG *p_msg;
  356. OS_MSG *p_msg_in;
  357. #ifdef OS_SAFETY_CRITICAL
  358. if (p_err == (OS_ERR *)0) {
  359. OS_SAFETY_CRITICAL_EXCEPTION();
  360. return;
  361. }
  362. #endif
  363. if (p_msg_q->NbrEntries >= p_msg_q->NbrEntriesSize) {
  364. *p_err = OS_ERR_Q_MAX; /* Message queue cannot accept any more messages */
  365. return;
  366. }
  367. if (OSMsgPool.NbrFree == (OS_MSG_QTY)0) {
  368. *p_err = OS_ERR_MSG_POOL_EMPTY; /* No more OS_MSG to use */
  369. return;
  370. }
  371. p_msg = OSMsgPool.NextPtr; /* Remove message control block from free list */
  372. OSMsgPool.NextPtr = p_msg->NextPtr;
  373. OSMsgPool.NbrFree--;
  374. OSMsgPool.NbrUsed++;
  375. if (p_msg_q->NbrEntries == (OS_MSG_QTY)0) { /* Is this first message placed in the queue? */
  376. p_msg_q->InPtr = p_msg; /* Yes */
  377. p_msg_q->OutPtr = p_msg;
  378. p_msg_q->NbrEntries = (OS_MSG_QTY)1;
  379. } else {
  380. if ((opt & OS_OPT_POST_LIFO) == OS_OPT_POST_FIFO) { /* Assume FIFO if not LIFO */
  381. p_msg_in = p_msg_q->InPtr; /* FIFO */
  382. p_msg_in->NextPtr = p_msg;
  383. p_msg->NextPtr = (OS_MSG *)0;
  384. p_msg_q->InPtr = p_msg;
  385. } else {
  386. p_msg->NextPtr = p_msg_q->OutPtr; /* LIFO */
  387. p_msg_q->OutPtr = p_msg;
  388. }
  389. p_msg_q->NbrEntries++;
  390. }
  391. if (p_msg_q->NbrEntries > p_msg_q->NbrEntriesMax) {
  392. p_msg_q->NbrEntriesMax = p_msg_q->NbrEntries;
  393. }
  394. p_msg->MsgPtr = p_void; /* Deposit message in the message queue entry */
  395. p_msg->MsgSize = msg_size;
  396. p_msg->MsgTS = ts;
  397. *p_err = OS_ERR_NONE;
  398. }
  399. #endif