rtx_msgqueue.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044
  1. /*
  2. * Copyright (c) 2013-2018 Arm Limited. All rights reserved.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the License); you may
  7. * not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an AS IS BASIS, WITHOUT
  14. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. *
  18. * -----------------------------------------------------------------------------
  19. *
  20. * Project: CMSIS-RTOS RTX
  21. * Title: Message Queue functions
  22. *
  23. * -----------------------------------------------------------------------------
  24. */
  25. #include "rtx_lib.h"
  26. // OS Runtime Object Memory Usage
  27. #if ((defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0)))
  28. osRtxObjectMemUsage_t osRtxMessageQueueMemUsage \
  29. __attribute__((section(".data.os.msgqueue.obj"))) =
  30. { 0U, 0U, 0U };
  31. #endif
  32. // ==== Helper functions ====
  33. /// Put a Message into Queue sorted by Priority (Highest at Head).
  34. /// \param[in] mq message queue object.
  35. /// \param[in] msg message object.
  36. static void MessageQueuePut (os_message_queue_t *mq, os_message_t *msg) {
  37. #if (EXCLUSIVE_ACCESS == 0)
  38. uint32_t primask = __get_PRIMASK();
  39. #endif
  40. os_message_t *prev, *next;
  41. if (mq->msg_last != NULL) {
  42. prev = mq->msg_last;
  43. next = NULL;
  44. while ((prev != NULL) && (prev->priority < msg->priority)) {
  45. next = prev;
  46. prev = prev->prev;
  47. }
  48. msg->prev = prev;
  49. msg->next = next;
  50. if (prev != NULL) {
  51. prev->next = msg;
  52. } else {
  53. mq->msg_first = msg;
  54. }
  55. if (next != NULL) {
  56. next->prev = msg;
  57. } else {
  58. mq->msg_last = msg;
  59. }
  60. } else {
  61. msg->prev = NULL;
  62. msg->next = NULL;
  63. mq->msg_first= msg;
  64. mq->msg_last = msg;
  65. }
  66. #if (EXCLUSIVE_ACCESS == 0)
  67. __disable_irq();
  68. mq->msg_count++;
  69. if (primask == 0U) {
  70. __enable_irq();
  71. }
  72. #else
  73. (void)atomic_inc32(&mq->msg_count);
  74. #endif
  75. }
  76. /// Get a Message from Queue with Highest Priority.
  77. /// \param[in] mq message queue object.
  78. /// \return message object or NULL.
  79. static os_message_t *MessageQueueGet (os_message_queue_t *mq) {
  80. #if (EXCLUSIVE_ACCESS == 0)
  81. uint32_t primask = __get_PRIMASK();
  82. #endif
  83. os_message_t *msg;
  84. uint32_t count;
  85. uint8_t flags;
  86. #if (EXCLUSIVE_ACCESS == 0)
  87. __disable_irq();
  88. count = mq->msg_count;
  89. if (count != 0U) {
  90. mq->msg_count--;
  91. }
  92. if (primask == 0U) {
  93. __enable_irq();
  94. }
  95. #else
  96. count = atomic_dec32_nz(&mq->msg_count);
  97. #endif
  98. if (count != 0U) {
  99. msg = mq->msg_first;
  100. while (msg != NULL) {
  101. #if (EXCLUSIVE_ACCESS == 0)
  102. __disable_irq();
  103. flags = msg->flags;
  104. msg->flags = 1U;
  105. if (primask == 0U) {
  106. __enable_irq();
  107. }
  108. #else
  109. flags = atomic_wr8(&msg->flags, 1U);
  110. #endif
  111. if (flags == 0U) {
  112. break;
  113. }
  114. msg = msg->next;
  115. }
  116. } else {
  117. msg = NULL;
  118. }
  119. return msg;
  120. }
  121. /// Remove a Message from Queue
  122. /// \param[in] mq message queue object.
  123. /// \param[in] msg message object.
  124. static void MessageQueueRemove (os_message_queue_t *mq, const os_message_t *msg) {
  125. if (msg->prev != NULL) {
  126. msg->prev->next = msg->next;
  127. } else {
  128. mq->msg_first = msg->next;
  129. }
  130. if (msg->next != NULL) {
  131. msg->next->prev = msg->prev;
  132. } else {
  133. mq->msg_last = msg->prev;
  134. }
  135. }
  136. // ==== Post ISR processing ====
  137. /// Message Queue post ISR processing.
  138. /// \param[in] msg message object.
  139. static void osRtxMessageQueuePostProcess (os_message_t *msg) {
  140. os_message_queue_t *mq;
  141. os_message_t *msg0;
  142. os_thread_t *thread;
  143. const uint32_t *reg;
  144. const void *ptr_src;
  145. void *ptr_dst;
  146. if (msg->state == osRtxObjectInactive) {
  147. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  148. return;
  149. }
  150. if (msg->flags != 0U) {
  151. // Remove Message
  152. //lint -e{9079} -e{9087} "cast between pointers to different object types"
  153. mq = *((os_message_queue_t **)(void *)&msg[1]);
  154. if (mq->state == osRtxObjectInactive) {
  155. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  156. return;
  157. }
  158. MessageQueueRemove(mq, msg);
  159. // Free memory
  160. msg->state = osRtxObjectInactive;
  161. (void)osRtxMemoryPoolFree(&mq->mp_info, msg);
  162. // Check if Thread is waiting to send a Message
  163. if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessagePut)) {
  164. // Try to allocate memory
  165. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  166. msg0 = osRtxMemoryPoolAlloc(&mq->mp_info);
  167. if (msg0 != NULL) {
  168. // Wakeup waiting Thread with highest Priority
  169. thread = osRtxThreadListGet(osRtxObject(mq));
  170. osRtxThreadWaitExit(thread, (uint32_t)osOK, FALSE);
  171. // Copy Message (R2: const void *msg_ptr, R3: uint8_t msg_prio)
  172. reg = osRtxThreadRegPtr(thread);
  173. //lint -e{923} "cast from unsigned int to pointer"
  174. ptr_src = (const void *)reg[2];
  175. memcpy(&msg0[1], ptr_src, mq->msg_size);
  176. // Store Message into Queue
  177. msg0->id = osRtxIdMessage;
  178. msg0->state = osRtxObjectActive;
  179. msg0->flags = 0U;
  180. msg0->priority = (uint8_t)reg[3];
  181. MessageQueuePut(mq, msg0);
  182. EvrRtxMessageQueueInserted(mq, ptr_src);
  183. }
  184. }
  185. } else {
  186. // New Message
  187. //lint -e{9079} -e{9087} "cast between pointers to different object types"
  188. mq = (void *)msg->next;
  189. if (mq->state == osRtxObjectInactive) {
  190. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  191. return;
  192. }
  193. //lint -e{9087} "cast between pointers to different object types"
  194. ptr_src = (const void *)msg->prev;
  195. // Check if Thread is waiting to receive a Message
  196. if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessageGet)) {
  197. EvrRtxMessageQueueInserted(mq, ptr_src);
  198. // Wakeup waiting Thread with highest Priority
  199. thread = osRtxThreadListGet(osRtxObject(mq));
  200. osRtxThreadWaitExit(thread, (uint32_t)osOK, FALSE);
  201. // Copy Message (R2: void *msg_ptr, R3: uint8_t *msg_prio)
  202. reg = osRtxThreadRegPtr(thread);
  203. //lint -e{923} "cast from unsigned int to pointer"
  204. ptr_dst = (void *)reg[2];
  205. memcpy(ptr_dst, &msg[1], mq->msg_size);
  206. if (reg[3] != 0U) {
  207. //lint -e{923} -e{9078} "cast from unsigned int to pointer"
  208. *((uint8_t *)reg[3]) = msg->priority;
  209. }
  210. EvrRtxMessageQueueRetrieved(mq, ptr_dst);
  211. // Free memory
  212. msg->state = osRtxObjectInactive;
  213. (void)osRtxMemoryPoolFree(&mq->mp_info, msg);
  214. } else {
  215. EvrRtxMessageQueueInserted(mq, ptr_src);
  216. MessageQueuePut(mq, msg);
  217. }
  218. }
  219. }
  220. // ==== Service Calls ====
  221. /// Create and Initialize a Message Queue object.
  222. /// \note API identical to osMessageQueueNew
  223. static osMessageQueueId_t svcRtxMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) {
  224. os_message_queue_t *mq;
  225. void *mq_mem;
  226. uint32_t mq_size;
  227. uint32_t block_size;
  228. uint32_t size;
  229. uint8_t flags;
  230. const char *name;
  231. // Check parameters
  232. if ((msg_count == 0U) || (msg_size == 0U)) {
  233. EvrRtxMessageQueueError(NULL, (int32_t)osErrorParameter);
  234. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  235. return NULL;
  236. }
  237. block_size = ((msg_size + 3U) & ~3UL) + sizeof(os_message_t);
  238. if ((__CLZ(msg_count) + __CLZ(block_size)) < 32U) {
  239. EvrRtxMessageQueueError(NULL, (int32_t)osErrorParameter);
  240. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  241. return NULL;
  242. }
  243. size = msg_count * block_size;
  244. // Process attributes
  245. if (attr != NULL) {
  246. name = attr->name;
  247. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
  248. mq = attr->cb_mem;
  249. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 6]
  250. mq_mem = attr->mq_mem;
  251. mq_size = attr->mq_size;
  252. if (mq != NULL) {
  253. //lint -e(923) -e(9078) "cast from pointer to unsigned int" [MISRA Note 7]
  254. if ((((uint32_t)mq & 3U) != 0U) || (attr->cb_size < sizeof(os_message_queue_t))) {
  255. EvrRtxMessageQueueError(NULL, osRtxErrorInvalidControlBlock);
  256. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  257. return NULL;
  258. }
  259. } else {
  260. if (attr->cb_size != 0U) {
  261. EvrRtxMessageQueueError(NULL, osRtxErrorInvalidControlBlock);
  262. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  263. return NULL;
  264. }
  265. }
  266. if (mq_mem != NULL) {
  267. //lint -e(923) -e(9078) "cast from pointer to unsigned int" [MISRA Note 7]
  268. if ((((uint32_t)mq_mem & 3U) != 0U) || (mq_size < size)) {
  269. EvrRtxMessageQueueError(NULL, osRtxErrorInvalidDataMemory);
  270. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  271. return NULL;
  272. }
  273. } else {
  274. if (mq_size != 0U) {
  275. EvrRtxMessageQueueError(NULL, osRtxErrorInvalidDataMemory);
  276. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  277. return NULL;
  278. }
  279. }
  280. } else {
  281. name = NULL;
  282. mq = NULL;
  283. mq_mem = NULL;
  284. }
  285. // Allocate object memory if not provided
  286. if (mq == NULL) {
  287. if (osRtxInfo.mpi.message_queue != NULL) {
  288. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  289. mq = osRtxMemoryPoolAlloc(osRtxInfo.mpi.message_queue);
  290. } else {
  291. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  292. mq = osRtxMemoryAlloc(osRtxInfo.mem.common, sizeof(os_message_queue_t), 1U);
  293. }
  294. #if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))
  295. if (mq != NULL) {
  296. uint32_t used;
  297. osRtxMessageQueueMemUsage.cnt_alloc++;
  298. used = osRtxMessageQueueMemUsage.cnt_alloc - osRtxMessageQueueMemUsage.cnt_free;
  299. if (osRtxMessageQueueMemUsage.max_used < used) {
  300. osRtxMessageQueueMemUsage.max_used = used;
  301. }
  302. }
  303. #endif
  304. flags = osRtxFlagSystemObject;
  305. } else {
  306. flags = 0U;
  307. }
  308. // Allocate data memory if not provided
  309. if ((mq != NULL) && (mq_mem == NULL)) {
  310. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  311. mq_mem = osRtxMemoryAlloc(osRtxInfo.mem.mq_data, size, 0U);
  312. if (mq_mem == NULL) {
  313. if ((flags & osRtxFlagSystemObject) != 0U) {
  314. if (osRtxInfo.mpi.message_queue != NULL) {
  315. (void)osRtxMemoryPoolFree(osRtxInfo.mpi.message_queue, mq);
  316. } else {
  317. (void)osRtxMemoryFree(osRtxInfo.mem.common, mq);
  318. }
  319. #if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))
  320. osRtxMessageQueueMemUsage.cnt_free++;
  321. #endif
  322. }
  323. mq = NULL;
  324. } else {
  325. memset(mq_mem, 0, size);
  326. }
  327. flags |= osRtxFlagSystemMemory;
  328. }
  329. if (mq != NULL) {
  330. // Initialize control block
  331. mq->id = osRtxIdMessageQueue;
  332. mq->state = osRtxObjectActive;
  333. mq->flags = flags;
  334. mq->name = name;
  335. mq->thread_list = NULL;
  336. mq->msg_size = msg_size;
  337. mq->msg_count = 0U;
  338. mq->msg_first = NULL;
  339. mq->msg_last = NULL;
  340. (void)osRtxMemoryPoolInit(&mq->mp_info, msg_count, block_size, mq_mem);
  341. // Register post ISR processing function
  342. osRtxInfo.post_process.message = osRtxMessageQueuePostProcess;
  343. EvrRtxMessageQueueCreated(mq, mq->name);
  344. } else {
  345. EvrRtxMessageQueueError(NULL, (int32_t)osErrorNoMemory);
  346. }
  347. return mq;
  348. }
  349. /// Get name of a Message Queue object.
  350. /// \note API identical to osMessageQueueGetName
  351. static const char *svcRtxMessageQueueGetName (osMessageQueueId_t mq_id) {
  352. os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
  353. // Check parameters
  354. if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
  355. EvrRtxMessageQueueGetName(mq, NULL);
  356. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  357. return NULL;
  358. }
  359. // Check object state
  360. if (mq->state == osRtxObjectInactive) {
  361. EvrRtxMessageQueueGetName(mq, NULL);
  362. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  363. return NULL;
  364. }
  365. EvrRtxMessageQueueGetName(mq, mq->name);
  366. return mq->name;
  367. }
  368. /// Put a Message into a Queue or timeout if Queue is full.
  369. /// \note API identical to osMessageQueuePut
  370. static osStatus_t svcRtxMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
  371. os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
  372. os_message_t *msg;
  373. os_thread_t *thread;
  374. uint32_t *reg;
  375. void *ptr;
  376. osStatus_t status;
  377. // Check parameters
  378. if ((mq == NULL) || (mq->id != osRtxIdMessageQueue) || (msg_ptr == NULL)) {
  379. EvrRtxMessageQueueError(mq, (int32_t)osErrorParameter);
  380. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  381. return osErrorParameter;
  382. }
  383. // Check object state
  384. if (mq->state == osRtxObjectInactive) {
  385. EvrRtxMessageQueueError(mq, (int32_t)osErrorResource);
  386. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  387. return osErrorResource;
  388. }
  389. // Check if Thread is waiting to receive a Message
  390. if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessageGet)) {
  391. EvrRtxMessageQueueInserted(mq, msg_ptr);
  392. // Wakeup waiting Thread with highest Priority
  393. thread = osRtxThreadListGet(osRtxObject(mq));
  394. osRtxThreadWaitExit(thread, (uint32_t)osOK, TRUE);
  395. // Copy Message (R2: void *msg_ptr, R3: uint8_t *msg_prio)
  396. reg = osRtxThreadRegPtr(thread);
  397. //lint -e{923} "cast from unsigned int to pointer"
  398. ptr = (void *)reg[2];
  399. memcpy(ptr, msg_ptr, mq->msg_size);
  400. if (reg[3] != 0U) {
  401. //lint -e{923} -e{9078} "cast from unsigned int to pointer"
  402. *((uint8_t *)reg[3]) = msg_prio;
  403. }
  404. EvrRtxMessageQueueRetrieved(mq, ptr);
  405. status = osOK;
  406. } else {
  407. // Try to allocate memory
  408. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  409. msg = osRtxMemoryPoolAlloc(&mq->mp_info);
  410. if (msg != NULL) {
  411. // Copy Message
  412. memcpy(&msg[1], msg_ptr, mq->msg_size);
  413. // Put Message into Queue
  414. msg->id = osRtxIdMessage;
  415. msg->state = osRtxObjectActive;
  416. msg->flags = 0U;
  417. msg->priority = msg_prio;
  418. MessageQueuePut(mq, msg);
  419. EvrRtxMessageQueueInserted(mq, msg_ptr);
  420. status = osOK;
  421. } else {
  422. // No memory available
  423. if (timeout != 0U) {
  424. EvrRtxMessageQueuePutPending(mq, msg_ptr, timeout);
  425. // Suspend current Thread
  426. if (osRtxThreadWaitEnter(osRtxThreadWaitingMessagePut, timeout)) {
  427. osRtxThreadListPut(osRtxObject(mq), osRtxThreadGetRunning());
  428. // Save arguments (R2: const void *msg_ptr, R3: uint8_t msg_prio)
  429. //lint -e{923} -e{9078} "cast from unsigned int to pointer"
  430. reg = (uint32_t *)(__get_PSP());
  431. //lint -e{923} -e{9078} "cast from pointer to unsigned int"
  432. reg[2] = (uint32_t)msg_ptr;
  433. //lint -e{923} -e{9078} "cast from pointer to unsigned int"
  434. reg[3] = (uint32_t)msg_prio;
  435. } else {
  436. EvrRtxMessageQueuePutTimeout(mq);
  437. }
  438. status = osErrorTimeout;
  439. } else {
  440. EvrRtxMessageQueueNotInserted(mq, msg_ptr);
  441. status = osErrorResource;
  442. }
  443. }
  444. }
  445. return status;
  446. }
  447. /// Get a Message from a Queue or timeout if Queue is empty.
  448. /// \note API identical to osMessageQueueGet
  449. static osStatus_t svcRtxMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
  450. os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
  451. os_message_t *msg;
  452. os_thread_t *thread;
  453. uint32_t *reg;
  454. const void *ptr;
  455. osStatus_t status;
  456. // Check parameters
  457. if ((mq == NULL) || (mq->id != osRtxIdMessageQueue) || (msg_ptr == NULL)) {
  458. EvrRtxMessageQueueError(mq, (int32_t)osErrorParameter);
  459. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  460. return osErrorParameter;
  461. }
  462. // Check object state
  463. if (mq->state == osRtxObjectInactive) {
  464. EvrRtxMessageQueueError(mq, (int32_t)osErrorResource);
  465. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  466. return osErrorResource;
  467. }
  468. // Get Message from Queue
  469. msg = MessageQueueGet(mq);
  470. if (msg != NULL) {
  471. MessageQueueRemove(mq, msg);
  472. // Copy Message
  473. memcpy(msg_ptr, &msg[1], mq->msg_size);
  474. if (msg_prio != NULL) {
  475. *msg_prio = msg->priority;
  476. }
  477. EvrRtxMessageQueueRetrieved(mq, msg_ptr);
  478. // Free memory
  479. msg->state = osRtxObjectInactive;
  480. (void)osRtxMemoryPoolFree(&mq->mp_info, msg);
  481. // Check if Thread is waiting to send a Message
  482. if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessagePut)) {
  483. // Try to allocate memory
  484. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  485. msg = osRtxMemoryPoolAlloc(&mq->mp_info);
  486. if (msg != NULL) {
  487. // Wakeup waiting Thread with highest Priority
  488. thread = osRtxThreadListGet(osRtxObject(mq));
  489. osRtxThreadWaitExit(thread, (uint32_t)osOK, TRUE);
  490. // Copy Message (R2: const void *msg_ptr, R3: uint8_t msg_prio)
  491. reg = osRtxThreadRegPtr(thread);
  492. //lint -e{923} "cast from unsigned int to pointer"
  493. ptr = (const void *)reg[2];
  494. memcpy(&msg[1], ptr, mq->msg_size);
  495. // Store Message into Queue
  496. msg->id = osRtxIdMessage;
  497. msg->state = osRtxObjectActive;
  498. msg->flags = 0U;
  499. msg->priority = (uint8_t)reg[3];
  500. MessageQueuePut(mq, msg);
  501. EvrRtxMessageQueueInserted(mq, ptr);
  502. }
  503. }
  504. status = osOK;
  505. } else {
  506. // No Message available
  507. if (timeout != 0U) {
  508. EvrRtxMessageQueueGetPending(mq, msg_ptr, timeout);
  509. // Suspend current Thread
  510. if (osRtxThreadWaitEnter(osRtxThreadWaitingMessageGet, timeout)) {
  511. osRtxThreadListPut(osRtxObject(mq), osRtxThreadGetRunning());
  512. // Save arguments (R2: void *msg_ptr, R3: uint8_t *msg_prio)
  513. //lint -e{923} -e{9078} "cast from unsigned int to pointer"
  514. reg = (uint32_t *)(__get_PSP());
  515. //lint -e{923} -e{9078} "cast from pointer to unsigned int"
  516. reg[2] = (uint32_t)msg_ptr;
  517. //lint -e{923} -e{9078} "cast from pointer to unsigned int"
  518. reg[3] = (uint32_t)msg_prio;
  519. } else {
  520. EvrRtxMessageQueueGetTimeout(mq);
  521. }
  522. status = osErrorTimeout;
  523. } else {
  524. EvrRtxMessageQueueNotRetrieved(mq, msg_ptr);
  525. status = osErrorResource;
  526. }
  527. }
  528. return status;
  529. }
  530. /// Get maximum number of messages in a Message Queue.
  531. /// \note API identical to osMessageGetCapacity
  532. static uint32_t svcRtxMessageQueueGetCapacity (osMessageQueueId_t mq_id) {
  533. os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
  534. // Check parameters
  535. if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
  536. EvrRtxMessageQueueGetCapacity(mq, 0U);
  537. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  538. return 0U;
  539. }
  540. // Check object state
  541. if (mq->state == osRtxObjectInactive) {
  542. EvrRtxMessageQueueGetCapacity(mq, 0U);
  543. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  544. return 0U;
  545. }
  546. EvrRtxMessageQueueGetCapacity(mq, mq->mp_info.max_blocks);
  547. return mq->mp_info.max_blocks;
  548. }
  549. /// Get maximum message size in a Memory Pool.
  550. /// \note API identical to osMessageGetMsgSize
  551. static uint32_t svcRtxMessageQueueGetMsgSize (osMessageQueueId_t mq_id) {
  552. os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
  553. // Check parameters
  554. if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
  555. EvrRtxMessageQueueGetMsgSize(mq, 0U);
  556. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  557. return 0U;
  558. }
  559. // Check object state
  560. if (mq->state == osRtxObjectInactive) {
  561. EvrRtxMessageQueueGetMsgSize(mq, 0U);
  562. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  563. return 0U;
  564. }
  565. EvrRtxMessageQueueGetMsgSize(mq, mq->msg_size);
  566. return mq->msg_size;
  567. }
  568. /// Get number of queued messages in a Message Queue.
  569. /// \note API identical to osMessageGetCount
  570. static uint32_t svcRtxMessageQueueGetCount (osMessageQueueId_t mq_id) {
  571. os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
  572. // Check parameters
  573. if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
  574. EvrRtxMessageQueueGetCount(mq, 0U);
  575. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  576. return 0U;
  577. }
  578. // Check object state
  579. if (mq->state == osRtxObjectInactive) {
  580. EvrRtxMessageQueueGetCount(mq, 0U);
  581. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  582. return 0U;
  583. }
  584. EvrRtxMessageQueueGetCount(mq, mq->msg_count);
  585. return mq->msg_count;
  586. }
  587. /// Get number of available slots for messages in a Message Queue.
  588. /// \note API identical to osMessageGetSpace
  589. static uint32_t svcRtxMessageQueueGetSpace (osMessageQueueId_t mq_id) {
  590. os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
  591. // Check parameters
  592. if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
  593. EvrRtxMessageQueueGetSpace(mq, 0U);
  594. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  595. return 0U;
  596. }
  597. // Check object state
  598. if (mq->state == osRtxObjectInactive) {
  599. EvrRtxMessageQueueGetSpace(mq, 0U);
  600. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  601. return 0U;
  602. }
  603. EvrRtxMessageQueueGetSpace(mq, mq->mp_info.max_blocks - mq->msg_count);
  604. return (mq->mp_info.max_blocks - mq->msg_count);
  605. }
  606. /// Reset a Message Queue to initial empty state.
  607. /// \note API identical to osMessageQueueReset
  608. static osStatus_t svcRtxMessageQueueReset (osMessageQueueId_t mq_id) {
  609. os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
  610. os_message_t *msg;
  611. os_thread_t *thread;
  612. const uint32_t *reg;
  613. const void *ptr;
  614. // Check parameters
  615. if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
  616. EvrRtxMessageQueueError(mq, (int32_t)osErrorParameter);
  617. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  618. return osErrorParameter;
  619. }
  620. // Check object state
  621. if (mq->state == osRtxObjectInactive) {
  622. EvrRtxMessageQueueError(mq, (int32_t)osErrorResource);
  623. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  624. return osErrorResource;
  625. }
  626. // Remove Messages from Queue
  627. for (;;) {
  628. // Get Message from Queue
  629. msg = MessageQueueGet(mq);
  630. if (msg == NULL) {
  631. break;
  632. }
  633. MessageQueueRemove(mq, msg);
  634. EvrRtxMessageQueueRetrieved(mq, NULL);
  635. // Free memory
  636. msg->state = osRtxObjectInactive;
  637. (void)osRtxMemoryPoolFree(&mq->mp_info, msg);
  638. }
  639. // Check if Threads are waiting to send Messages
  640. if ((mq->thread_list != NULL) && (mq->thread_list->state == osRtxThreadWaitingMessagePut)) {
  641. do {
  642. // Try to allocate memory
  643. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  644. msg = osRtxMemoryPoolAlloc(&mq->mp_info);
  645. if (msg != NULL) {
  646. // Wakeup waiting Thread with highest Priority
  647. thread = osRtxThreadListGet(osRtxObject(mq));
  648. osRtxThreadWaitExit(thread, (uint32_t)osOK, FALSE);
  649. // Copy Message (R2: const void *msg_ptr, R3: uint8_t msg_prio)
  650. reg = osRtxThreadRegPtr(thread);
  651. //lint -e{923} "cast from unsigned int to pointer"
  652. ptr = (const void *)reg[2];
  653. memcpy(&msg[1], ptr, mq->msg_size);
  654. // Store Message into Queue
  655. msg->id = osRtxIdMessage;
  656. msg->state = osRtxObjectActive;
  657. msg->flags = 0U;
  658. msg->priority = (uint8_t)reg[3];
  659. MessageQueuePut(mq, msg);
  660. EvrRtxMessageQueueInserted(mq, ptr);
  661. }
  662. } while ((msg != NULL) && (mq->thread_list != NULL));
  663. osRtxThreadDispatch(NULL);
  664. }
  665. EvrRtxMessageQueueResetDone(mq);
  666. return osOK;
  667. }
  668. /// Delete a Message Queue object.
  669. /// \note API identical to osMessageQueueDelete
  670. static osStatus_t svcRtxMessageQueueDelete (osMessageQueueId_t mq_id) {
  671. os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
  672. os_thread_t *thread;
  673. // Check parameters
  674. if ((mq == NULL) || (mq->id != osRtxIdMessageQueue)) {
  675. EvrRtxMessageQueueError(mq, (int32_t)osErrorParameter);
  676. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  677. return osErrorParameter;
  678. }
  679. // Check object state
  680. if (mq->state == osRtxObjectInactive) {
  681. EvrRtxMessageQueueError(mq, (int32_t)osErrorResource);
  682. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  683. return osErrorResource;
  684. }
  685. // Mark object as inactive
  686. mq->state = osRtxObjectInactive;
  687. // Unblock waiting threads
  688. if (mq->thread_list != NULL) {
  689. do {
  690. thread = osRtxThreadListGet(osRtxObject(mq));
  691. osRtxThreadWaitExit(thread, (uint32_t)osErrorResource, FALSE);
  692. } while (mq->thread_list != NULL);
  693. osRtxThreadDispatch(NULL);
  694. }
  695. // Free data memory
  696. if ((mq->flags & osRtxFlagSystemMemory) != 0U) {
  697. (void)osRtxMemoryFree(osRtxInfo.mem.mq_data, mq->mp_info.block_base);
  698. }
  699. // Free object memory
  700. if ((mq->flags & osRtxFlagSystemObject) != 0U) {
  701. if (osRtxInfo.mpi.message_queue != NULL) {
  702. (void)osRtxMemoryPoolFree(osRtxInfo.mpi.message_queue, mq);
  703. } else {
  704. (void)osRtxMemoryFree(osRtxInfo.mem.common, mq);
  705. }
  706. #if (defined(OS_OBJ_MEM_USAGE) && (OS_OBJ_MEM_USAGE != 0))
  707. osRtxMessageQueueMemUsage.cnt_free++;
  708. #endif
  709. }
  710. EvrRtxMessageQueueDestroyed(mq);
  711. return osOK;
  712. }
  713. // Service Calls definitions
  714. //lint ++flb "Library Begin" [MISRA Note 11]
  715. SVC0_3(MessageQueueNew, osMessageQueueId_t, uint32_t, uint32_t, const osMessageQueueAttr_t *)
  716. SVC0_1(MessageQueueGetName, const char *, osMessageQueueId_t)
  717. SVC0_4(MessageQueuePut, osStatus_t, osMessageQueueId_t, const void *, uint8_t, uint32_t)
  718. SVC0_4(MessageQueueGet, osStatus_t, osMessageQueueId_t, void *, uint8_t *, uint32_t)
  719. SVC0_1(MessageQueueGetCapacity, uint32_t, osMessageQueueId_t)
  720. SVC0_1(MessageQueueGetMsgSize, uint32_t, osMessageQueueId_t)
  721. SVC0_1(MessageQueueGetCount, uint32_t, osMessageQueueId_t)
  722. SVC0_1(MessageQueueGetSpace, uint32_t, osMessageQueueId_t)
  723. SVC0_1(MessageQueueReset, osStatus_t, osMessageQueueId_t)
  724. SVC0_1(MessageQueueDelete, osStatus_t, osMessageQueueId_t)
  725. //lint --flb "Library End"
  726. // ==== ISR Calls ====
  727. /// Put a Message into a Queue or timeout if Queue is full.
  728. /// \note API identical to osMessageQueuePut
  729. __STATIC_INLINE
  730. osStatus_t isrRtxMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
  731. os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
  732. os_message_t *msg;
  733. osStatus_t status;
  734. // Check parameters
  735. if ((mq == NULL) || (mq->id != osRtxIdMessageQueue) || (msg_ptr == NULL) || (timeout != 0U)) {
  736. EvrRtxMessageQueueError(mq, (int32_t)osErrorParameter);
  737. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  738. return osErrorParameter;
  739. }
  740. // Check object state
  741. if (mq->state == osRtxObjectInactive) {
  742. EvrRtxMessageQueueError(mq, (int32_t)osErrorResource);
  743. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  744. return osErrorResource;
  745. }
  746. // Try to allocate memory
  747. //lint -e{9079} "conversion from pointer to void to pointer to other type" [MISRA Note 5]
  748. msg = osRtxMemoryPoolAlloc(&mq->mp_info);
  749. if (msg != NULL) {
  750. // Copy Message
  751. memcpy(&msg[1], msg_ptr, mq->msg_size);
  752. msg->id = osRtxIdMessage;
  753. msg->state = osRtxObjectActive;
  754. msg->flags = 0U;
  755. msg->priority = msg_prio;
  756. // Register post ISR processing
  757. //lint -e{9079} -e{9087} "cast between pointers to different object types"
  758. *((const void **)(void *)&msg->prev) = msg_ptr;
  759. //lint -e{9079} -e{9087} "cast between pointers to different object types"
  760. *( (void **) &msg->next) = mq;
  761. osRtxPostProcess(osRtxObject(msg));
  762. EvrRtxMessageQueueInsertPending(mq, msg_ptr);
  763. status = osOK;
  764. } else {
  765. // No memory available
  766. EvrRtxMessageQueueNotInserted(mq, msg_ptr);
  767. status = osErrorResource;
  768. }
  769. return status;
  770. }
  771. /// Get a Message from a Queue or timeout if Queue is empty.
  772. /// \note API identical to osMessageQueueGet
  773. __STATIC_INLINE
  774. osStatus_t isrRtxMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
  775. os_message_queue_t *mq = osRtxMessageQueueId(mq_id);
  776. os_message_t *msg;
  777. osStatus_t status;
  778. // Check parameters
  779. if ((mq == NULL) || (mq->id != osRtxIdMessageQueue) || (msg_ptr == NULL) || (timeout != 0U)) {
  780. EvrRtxMessageQueueError(mq, (int32_t)osErrorParameter);
  781. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  782. return osErrorParameter;
  783. }
  784. // Check object state
  785. if (mq->state == osRtxObjectInactive) {
  786. EvrRtxMessageQueueError(mq, (int32_t)osErrorResource);
  787. //lint -e{904} "Return statement before end of function" [MISRA Note 1]
  788. return osErrorResource;
  789. }
  790. // Get Message from Queue
  791. msg = MessageQueueGet(mq);
  792. if (msg != NULL) {
  793. // Copy Message
  794. memcpy(msg_ptr, &msg[1], mq->msg_size);
  795. if (msg_prio != NULL) {
  796. *msg_prio = msg->priority;
  797. }
  798. // Register post ISR processing
  799. //lint -e{9079} -e{9087} "cast between pointers to different object types"
  800. *((os_message_queue_t **)(void *)&msg[1]) = mq;
  801. osRtxPostProcess(osRtxObject(msg));
  802. EvrRtxMessageQueueRetrieved(mq, msg_ptr);
  803. status = osOK;
  804. } else {
  805. // No Message available
  806. EvrRtxMessageQueueNotRetrieved(mq, msg_ptr);
  807. status = osErrorResource;
  808. }
  809. return status;
  810. }
  811. // ==== Public API ====
  812. /// Create and Initialize a Message Queue object.
  813. osMessageQueueId_t osMessageQueueNew (uint32_t msg_count, uint32_t msg_size, const osMessageQueueAttr_t *attr) {
  814. osMessageQueueId_t mq_id;
  815. EvrRtxMessageQueueNew(msg_count, msg_size, attr);
  816. if (IsIrqMode() || IsIrqMasked()) {
  817. EvrRtxMessageQueueError(NULL, (int32_t)osErrorISR);
  818. mq_id = NULL;
  819. } else {
  820. mq_id = __svcMessageQueueNew(msg_count, msg_size, attr);
  821. }
  822. return mq_id;
  823. }
  824. /// Get name of a Message Queue object.
  825. const char *osMessageQueueGetName (osMessageQueueId_t mq_id) {
  826. const char *name;
  827. if (IsIrqMode() || IsIrqMasked()) {
  828. EvrRtxMessageQueueGetName(mq_id, NULL);
  829. name = NULL;
  830. } else {
  831. name = __svcMessageQueueGetName(mq_id);
  832. }
  833. return name;
  834. }
  835. /// Put a Message into a Queue or timeout if Queue is full.
  836. osStatus_t osMessageQueuePut (osMessageQueueId_t mq_id, const void *msg_ptr, uint8_t msg_prio, uint32_t timeout) {
  837. osStatus_t status;
  838. EvrRtxMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
  839. if (IsIrqMode() || IsIrqMasked()) {
  840. status = isrRtxMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
  841. } else {
  842. status = __svcMessageQueuePut(mq_id, msg_ptr, msg_prio, timeout);
  843. }
  844. return status;
  845. }
  846. /// Get a Message from a Queue or timeout if Queue is empty.
  847. osStatus_t osMessageQueueGet (osMessageQueueId_t mq_id, void *msg_ptr, uint8_t *msg_prio, uint32_t timeout) {
  848. osStatus_t status;
  849. EvrRtxMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
  850. if (IsIrqMode() || IsIrqMasked()) {
  851. status = isrRtxMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
  852. } else {
  853. status = __svcMessageQueueGet(mq_id, msg_ptr, msg_prio, timeout);
  854. }
  855. return status;
  856. }
  857. /// Get maximum number of messages in a Message Queue.
  858. uint32_t osMessageQueueGetCapacity (osMessageQueueId_t mq_id) {
  859. uint32_t capacity;
  860. if (IsIrqMode() || IsIrqMasked()) {
  861. capacity = svcRtxMessageQueueGetCapacity(mq_id);
  862. } else {
  863. capacity = __svcMessageQueueGetCapacity(mq_id);
  864. }
  865. return capacity;
  866. }
  867. /// Get maximum message size in a Memory Pool.
  868. uint32_t osMessageQueueGetMsgSize (osMessageQueueId_t mq_id) {
  869. uint32_t msg_size;
  870. if (IsIrqMode() || IsIrqMasked()) {
  871. msg_size = svcRtxMessageQueueGetMsgSize(mq_id);
  872. } else {
  873. msg_size = __svcMessageQueueGetMsgSize(mq_id);
  874. }
  875. return msg_size;
  876. }
  877. /// Get number of queued messages in a Message Queue.
  878. uint32_t osMessageQueueGetCount (osMessageQueueId_t mq_id) {
  879. uint32_t count;
  880. if (IsIrqMode() || IsIrqMasked()) {
  881. count = svcRtxMessageQueueGetCount(mq_id);
  882. } else {
  883. count = __svcMessageQueueGetCount(mq_id);
  884. }
  885. return count;
  886. }
  887. /// Get number of available slots for messages in a Message Queue.
  888. uint32_t osMessageQueueGetSpace (osMessageQueueId_t mq_id) {
  889. uint32_t space;
  890. if (IsIrqMode() || IsIrqMasked()) {
  891. space = svcRtxMessageQueueGetSpace(mq_id);
  892. } else {
  893. space = __svcMessageQueueGetSpace(mq_id);
  894. }
  895. return space;
  896. }
  897. /// Reset a Message Queue to initial empty state.
  898. osStatus_t osMessageQueueReset (osMessageQueueId_t mq_id) {
  899. osStatus_t status;
  900. EvrRtxMessageQueueReset(mq_id);
  901. if (IsIrqMode() || IsIrqMasked()) {
  902. EvrRtxMessageQueueError(mq_id, (int32_t)osErrorISR);
  903. status = osErrorISR;
  904. } else {
  905. status = __svcMessageQueueReset(mq_id);
  906. }
  907. return status;
  908. }
  909. /// Delete a Message Queue object.
  910. osStatus_t osMessageQueueDelete (osMessageQueueId_t mq_id) {
  911. osStatus_t status;
  912. EvrRtxMessageQueueDelete(mq_id);
  913. if (IsIrqMode() || IsIrqMasked()) {
  914. EvrRtxMessageQueueError(mq_id, (int32_t)osErrorISR);
  915. status = osErrorISR;
  916. } else {
  917. status = __svcMessageQueueDelete(mq_id);
  918. }
  919. return status;
  920. }