os_msg.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*
  2. *********************************************************************************************************
  3. * uC/OS-III
  4. * The Real-Time Kernel
  5. *
  6. * Copyright 2009-2022 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. * MESSAGE HANDLING SERVICES
  19. *
  20. * File : os_msg.c
  21. * Version : V3.08.02
  22. *********************************************************************************************************
  23. */
  24. #define MICRIUM_SOURCE
  25. #include "os.h"
  26. #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
  27. const CPU_CHAR *os_msg__c = "$Id: $";
  28. #endif
  29. #if (OS_MSG_EN > 0u)
  30. /*
  31. ************************************************************************************************************************
  32. * INITIALIZE THE POOL OF 'OS_MSG'
  33. *
  34. * Description: This function is called by OSInit() to initialize the free list of OS_MSGs.
  35. *
  36. * Argument(s): p_err is a pointer to a variable that will contain an error code returned by this function.
  37. *
  38. * OS_ERR_MSG_POOL_NULL_PTR
  39. * OS_ERR_MSG_POOL_EMPTY
  40. * OS_ERR_NONE
  41. *
  42. * Returns : none
  43. *
  44. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  45. ************************************************************************************************************************
  46. */
  47. void OS_MsgPoolInit (OS_ERR *p_err)
  48. {
  49. OS_MSG *p_msg1;
  50. OS_MSG *p_msg2;
  51. OS_MSG_QTY i;
  52. OS_MSG_QTY loops;
  53. #if (OS_CFG_ARG_CHK_EN > 0u)
  54. if (OSCfg_MsgPoolBasePtr == (OS_MSG *)0) {
  55. *p_err = OS_ERR_MSG_POOL_NULL_PTR;
  56. return;
  57. }
  58. if (OSCfg_MsgPoolSize == 0u) {
  59. *p_err = OS_ERR_MSG_POOL_EMPTY;
  60. return;
  61. }
  62. #endif
  63. p_msg1 = OSCfg_MsgPoolBasePtr;
  64. p_msg2 = OSCfg_MsgPoolBasePtr;
  65. p_msg2++;
  66. loops = OSCfg_MsgPoolSize - 1u;
  67. for (i = 0u; i < loops; i++) { /* Init. list of free OS_MSGs */
  68. p_msg1->NextPtr = p_msg2;
  69. p_msg1->MsgPtr = (void *)0;
  70. p_msg1->MsgSize = 0u;
  71. #if (OS_CFG_TS_EN > 0u)
  72. p_msg1->MsgTS = 0u;
  73. #endif
  74. p_msg1++;
  75. p_msg2++;
  76. }
  77. p_msg1->NextPtr = (OS_MSG *)0; /* Last OS_MSG */
  78. p_msg1->MsgPtr = (void *)0;
  79. p_msg1->MsgSize = 0u;
  80. #if (OS_CFG_TS_EN > 0u)
  81. p_msg1->MsgTS = 0u;
  82. #endif
  83. OSMsgPool.NextPtr = OSCfg_MsgPoolBasePtr;
  84. OSMsgPool.NbrFree = OSCfg_MsgPoolSize;
  85. OSMsgPool.NbrUsed = 0u;
  86. #if (OS_CFG_DBG_EN > 0u)
  87. OSMsgPool.NbrUsedMax = 0u;
  88. #endif
  89. *p_err = OS_ERR_NONE;
  90. }
  91. /*
  92. ************************************************************************************************************************
  93. * RELEASE ALL MESSAGE IN MESSAGE QUEUE
  94. *
  95. * Description: This function returns all the messages in a message queue to the free list.
  96. *
  97. * Arguments : p_msg_q is a pointer to the OS_MSG_Q structure containing messages to free.
  98. * -------
  99. *
  100. * Returns : the number of OS_MSGs returned to the free list
  101. *
  102. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  103. ************************************************************************************************************************
  104. */
  105. OS_MSG_QTY OS_MsgQFreeAll (OS_MSG_Q *p_msg_q)
  106. {
  107. OS_MSG *p_msg;
  108. OS_MSG_QTY qty;
  109. qty = p_msg_q->NbrEntries; /* Get the number of OS_MSGs being freed */
  110. if (p_msg_q->NbrEntries > 0u) {
  111. p_msg = p_msg_q->InPtr; /* Point to end of message chain */
  112. p_msg->NextPtr = OSMsgPool.NextPtr;
  113. OSMsgPool.NextPtr = p_msg_q->OutPtr; /* Point to beginning of message chain */
  114. OSMsgPool.NbrUsed -= p_msg_q->NbrEntries; /* Update statistics for free list of messages */
  115. OSMsgPool.NbrFree += p_msg_q->NbrEntries;
  116. p_msg_q->NbrEntries = 0u; /* Flush the message queue */
  117. #if (OS_CFG_DBG_EN > 0u)
  118. p_msg_q->NbrEntriesMax = 0u;
  119. #endif
  120. p_msg_q->InPtr = (OS_MSG *)0;
  121. p_msg_q->OutPtr = (OS_MSG *)0;
  122. }
  123. return (qty);
  124. }
  125. /*
  126. ************************************************************************************************************************
  127. * INITIALIZE A MESSAGE QUEUE
  128. *
  129. * Description: This function is called to initialize a message queue
  130. *
  131. * Arguments : p_msg_q is a pointer to the message queue to initialize
  132. * -------
  133. *
  134. * size is the maximum number of entries that a message queue can have.
  135. *
  136. * Returns : none
  137. *
  138. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  139. ************************************************************************************************************************
  140. */
  141. void OS_MsgQInit (OS_MSG_Q *p_msg_q,
  142. OS_MSG_QTY size)
  143. {
  144. p_msg_q->NbrEntriesSize = size;
  145. p_msg_q->NbrEntries = 0u;
  146. #if (OS_CFG_DBG_EN > 0u)
  147. p_msg_q->NbrEntriesMax = 0u;
  148. #endif
  149. p_msg_q->InPtr = (OS_MSG *)0;
  150. p_msg_q->OutPtr = (OS_MSG *)0;
  151. }
  152. /*
  153. ************************************************************************************************************************
  154. * RETRIEVE MESSAGE FROM MESSAGE QUEUE
  155. *
  156. * Description: This function retrieves a message from a message queue
  157. *
  158. * Arguments : p_msg_q is a pointer to the message queue where we want to extract the message from
  159. * -------
  160. *
  161. * p_msg_size is a pointer to where the size (in bytes) of the message will be placed
  162. *
  163. * p_ts is a pointer to where the time stamp will be placed
  164. *
  165. * p_err is a pointer to an error code that will be returned from this call.
  166. *
  167. * OS_ERR_Q_EMPTY
  168. * OS_ERR_NONE
  169. *
  170. * Returns : The message (a pointer)
  171. *
  172. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  173. ************************************************************************************************************************
  174. */
  175. void *OS_MsgQGet (OS_MSG_Q *p_msg_q,
  176. OS_MSG_SIZE *p_msg_size,
  177. CPU_TS *p_ts,
  178. OS_ERR *p_err)
  179. {
  180. OS_MSG *p_msg;
  181. void *p_void;
  182. #if (OS_CFG_TS_EN == 0u)
  183. (void)p_ts; /* Prevent compiler warning for not using 'ts' */
  184. #endif
  185. if (p_msg_q->NbrEntries == 0u) { /* Is the queue empty? */
  186. *p_msg_size = 0u; /* Yes */
  187. #if (OS_CFG_TS_EN > 0u)
  188. if (p_ts != (CPU_TS *)0) {
  189. *p_ts = 0u;
  190. }
  191. #endif
  192. *p_err = OS_ERR_Q_EMPTY;
  193. return ((void *)0);
  194. }
  195. p_msg = p_msg_q->OutPtr; /* No, get the next message to extract from the queue */
  196. p_void = p_msg->MsgPtr;
  197. *p_msg_size = p_msg->MsgSize;
  198. #if (OS_CFG_TS_EN > 0u)
  199. if (p_ts != (CPU_TS *)0) {
  200. *p_ts = p_msg->MsgTS;
  201. }
  202. #endif
  203. p_msg_q->OutPtr = p_msg->NextPtr; /* Point to next message to extract */
  204. if (p_msg_q->OutPtr == (OS_MSG *)0) { /* Are there any more messages in the queue? */
  205. p_msg_q->InPtr = (OS_MSG *)0; /* No */
  206. p_msg_q->NbrEntries = 0u;
  207. } else {
  208. p_msg_q->NbrEntries--; /* Yes, One less message in the queue */
  209. }
  210. p_msg->NextPtr = OSMsgPool.NextPtr; /* Return message control block to free list */
  211. OSMsgPool.NextPtr = p_msg;
  212. OSMsgPool.NbrFree++;
  213. OSMsgPool.NbrUsed--;
  214. *p_err = OS_ERR_NONE;
  215. return (p_void);
  216. }
  217. /*
  218. ************************************************************************************************************************
  219. * DEPOSIT MESSAGE IN MESSAGE QUEUE
  220. *
  221. * Description: This function places a message in a message queue
  222. *
  223. * Arguments : p_msg_q is a pointer to the OS_TCB of the task to post the message to
  224. * -------
  225. *
  226. * p_void is a pointer to the message to send.
  227. *
  228. * msg_size is the size of the message (in bytes)
  229. *
  230. * opt specifies whether the message will be posted in FIFO or LIFO order
  231. *
  232. * OS_OPT_POST_FIFO
  233. * OS_OPT_POST_LIFO
  234. *
  235. * ts is a timestamp as to when the message was posted
  236. *
  237. * p_err is a pointer to a variable that will contain an error code returned by this function.
  238. *
  239. * OS_ERR_Q_MAX if the queue is full
  240. * OS_ERR_MSG_POOL_EMPTY if we no longer have any OS_MSG to use
  241. * OS_ERR_NONE the message was deposited in the queue
  242. *
  243. * Returns : none
  244. *
  245. * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application MUST NOT call it.
  246. ************************************************************************************************************************
  247. */
  248. void OS_MsgQPut (OS_MSG_Q *p_msg_q,
  249. void *p_void,
  250. OS_MSG_SIZE msg_size,
  251. OS_OPT opt,
  252. CPU_TS ts,
  253. OS_ERR *p_err)
  254. {
  255. OS_MSG *p_msg;
  256. OS_MSG *p_msg_in;
  257. #if (OS_CFG_TS_EN == 0u)
  258. (void)ts; /* Prevent compiler warning for not using 'ts' */
  259. #endif
  260. if (p_msg_q->NbrEntries >= p_msg_q->NbrEntriesSize) {
  261. *p_err = OS_ERR_Q_MAX; /* Message queue cannot accept any more messages */
  262. return;
  263. }
  264. if (OSMsgPool.NbrFree == 0u) {
  265. *p_err = OS_ERR_MSG_POOL_EMPTY; /* No more OS_MSG to use */
  266. return;
  267. }
  268. p_msg = OSMsgPool.NextPtr; /* Remove message control block from free list */
  269. OSMsgPool.NextPtr = p_msg->NextPtr;
  270. OSMsgPool.NbrFree--;
  271. OSMsgPool.NbrUsed++;
  272. #if (OS_CFG_DBG_EN > 0u)
  273. if (OSMsgPool.NbrUsedMax < OSMsgPool.NbrUsed) {
  274. OSMsgPool.NbrUsedMax = OSMsgPool.NbrUsed;
  275. }
  276. #endif
  277. if (p_msg_q->NbrEntries == 0u) { /* Is this first message placed in the queue? */
  278. p_msg_q->InPtr = p_msg; /* Yes */
  279. p_msg_q->OutPtr = p_msg;
  280. p_msg_q->NbrEntries = 1u;
  281. p_msg->NextPtr = (OS_MSG *)0;
  282. } else { /* No */
  283. if ((opt & OS_OPT_POST_LIFO) == OS_OPT_POST_FIFO) { /* Is it FIFO or LIFO? */
  284. p_msg_in = p_msg_q->InPtr; /* FIFO, add to the head */
  285. p_msg_in->NextPtr = p_msg;
  286. p_msg_q->InPtr = p_msg;
  287. p_msg->NextPtr = (OS_MSG *)0;
  288. } else {
  289. p_msg->NextPtr = p_msg_q->OutPtr; /* LIFO, add to the tail */
  290. p_msg_q->OutPtr = p_msg;
  291. }
  292. p_msg_q->NbrEntries++;
  293. }
  294. #if (OS_CFG_DBG_EN > 0u)
  295. if (p_msg_q->NbrEntriesMax < p_msg_q->NbrEntries) {
  296. p_msg_q->NbrEntriesMax = p_msg_q->NbrEntries;
  297. }
  298. #endif
  299. p_msg->MsgPtr = p_void; /* Deposit message in the message queue entry */
  300. p_msg->MsgSize = msg_size;
  301. #if (OS_CFG_TS_EN > 0u)
  302. p_msg->MsgTS = ts;
  303. #endif
  304. *p_err = OS_ERR_NONE;
  305. }
  306. #endif