msgq.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. /*
  2. * Copyright (c) 2018 Intel Corporation
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <kernel.h>
  7. #include <string.h>
  8. #include "wrapper.h"
  9. K_MEM_SLAB_DEFINE(cv2_msgq_slab, sizeof(struct cv2_msgq),
  10. CONFIG_CMSIS_V2_MSGQ_MAX_COUNT, 4);
  11. static const osMessageQueueAttr_t init_msgq_attrs = {
  12. .name = "ZephyrMsgQ",
  13. .attr_bits = 0,
  14. .cb_mem = NULL,
  15. .cb_size = 0,
  16. .mq_mem = NULL,
  17. .mq_size = 0,
  18. };
  19. /**
  20. * @brief Create and Initialize Message queue.
  21. */
  22. osMessageQueueId_t osMessageQueueNew(uint32_t msg_count, uint32_t msg_size,
  23. const osMessageQueueAttr_t *attr)
  24. {
  25. struct cv2_msgq *msgq;
  26. BUILD_ASSERT(CONFIG_HEAP_MEM_POOL_SIZE >=
  27. CONFIG_CMSIS_V2_MSGQ_MAX_DYNAMIC_SIZE,
  28. "heap must be configured to be at least the max dynamic size");
  29. if (k_is_in_isr()) {
  30. return NULL;
  31. }
  32. if ((attr != NULL) && (attr->mq_size < msg_count * msg_size)) {
  33. return NULL;
  34. }
  35. if (attr == NULL) {
  36. attr = &init_msgq_attrs;
  37. }
  38. if (k_mem_slab_alloc(&cv2_msgq_slab, (void **)&msgq, K_MSEC(100)) == 0) {
  39. (void)memset(msgq, 0, sizeof(struct cv2_msgq));
  40. } else {
  41. return NULL;
  42. }
  43. if (attr->mq_mem == NULL) {
  44. __ASSERT((msg_count * msg_size) <=
  45. CONFIG_CMSIS_V2_MSGQ_MAX_DYNAMIC_SIZE,
  46. "message queue size exceeds dynamic maximum");
  47. msgq->pool = k_calloc(msg_count, msg_size);
  48. if (msgq->pool == NULL) {
  49. k_mem_slab_free(&cv2_msgq_slab, (void *) &msgq);
  50. return NULL;
  51. }
  52. msgq->is_dynamic_allocation = TRUE;
  53. } else {
  54. msgq->pool = attr->mq_mem;
  55. msgq->is_dynamic_allocation = FALSE;
  56. }
  57. k_msgq_init(&msgq->z_msgq, msgq->pool, msg_size, msg_count);
  58. if (attr->name == NULL) {
  59. strncpy(msgq->name, init_msgq_attrs.name,
  60. sizeof(msgq->name) - 1);
  61. } else {
  62. strncpy(msgq->name, attr->name, sizeof(msgq->name) - 1);
  63. }
  64. return (osMessageQueueId_t)(msgq);
  65. }
  66. /**
  67. * @brief Put a message to a Queue.
  68. */
  69. osStatus_t osMessageQueuePut(osMessageQueueId_t msgq_id, const void *msg_ptr,
  70. uint8_t msg_prio, uint32_t timeout)
  71. {
  72. struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;
  73. int retval;
  74. ARG_UNUSED(msg_prio);
  75. if (msgq == NULL) {
  76. return osErrorParameter;
  77. }
  78. /* Can be called from ISRs only if timeout is set to 0 */
  79. if (timeout > 0 && k_is_in_isr()) {
  80. return osErrorParameter;
  81. }
  82. if (timeout == 0U) {
  83. retval = k_msgq_put(&msgq->z_msgq, (void *)msg_ptr, K_NO_WAIT);
  84. } else if (timeout == osWaitForever) {
  85. retval = k_msgq_put(&msgq->z_msgq, (void *)msg_ptr, K_FOREVER);
  86. } else {
  87. retval = k_msgq_put(&msgq->z_msgq, (void *)msg_ptr,
  88. K_TICKS(timeout));
  89. }
  90. if (retval == 0) {
  91. return osOK;
  92. } else if (retval == -EAGAIN) {
  93. return osErrorTimeout;
  94. } else {
  95. return osErrorResource;
  96. }
  97. }
  98. /**
  99. * @brief Get a message or Wait for a Message from a Queue.
  100. */
  101. osStatus_t osMessageQueueGet(osMessageQueueId_t msgq_id, void *msg_ptr,
  102. uint8_t *msg_prio, uint32_t timeout)
  103. {
  104. struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;
  105. int retval;
  106. ARG_UNUSED(msg_prio);
  107. if (msgq == NULL) {
  108. return osErrorParameter;
  109. }
  110. /* Can be called from ISRs only if timeout is set to 0 */
  111. if (timeout > 0 && k_is_in_isr()) {
  112. return osErrorParameter;
  113. }
  114. if (timeout == 0U) {
  115. retval = k_msgq_get(&msgq->z_msgq, msg_ptr, K_NO_WAIT);
  116. } else if (timeout == osWaitForever) {
  117. retval = k_msgq_get(&msgq->z_msgq, msg_ptr, K_FOREVER);
  118. } else {
  119. retval = k_msgq_get(&msgq->z_msgq, msg_ptr,
  120. K_TICKS(timeout));
  121. }
  122. if (retval == 0) {
  123. return osOK;
  124. } else if (retval == -EAGAIN) {
  125. return osErrorTimeout;
  126. } else if (retval == -ENOMSG) {
  127. return osErrorResource;
  128. }
  129. return osOK;
  130. }
  131. /**
  132. * @brief Get maximum number of messages in a Message Queue.
  133. */
  134. uint32_t osMessageQueueGetCapacity(osMessageQueueId_t msgq_id)
  135. {
  136. struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;
  137. if (msgq == NULL) {
  138. return 0;
  139. } else {
  140. return msgq->z_msgq.max_msgs;
  141. }
  142. }
  143. /**
  144. * @brief Get maximum message size in a Message Queue.
  145. */
  146. uint32_t osMessageQueueGetMsgSize(osMessageQueueId_t msgq_id)
  147. {
  148. struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;
  149. if (msgq == NULL) {
  150. return 0;
  151. } else {
  152. return msgq->z_msgq.msg_size;
  153. }
  154. }
  155. /**
  156. * @brief Get number of queued messages in a Message Queue.
  157. */
  158. uint32_t osMessageQueueGetCount(osMessageQueueId_t msgq_id)
  159. {
  160. struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;
  161. if (msgq == NULL) {
  162. return 0;
  163. } else {
  164. return k_msgq_num_used_get(&msgq->z_msgq);
  165. }
  166. }
  167. /**
  168. * @brief Get number of available slots for messages in a Message Queue.
  169. */
  170. uint32_t osMessageQueueGetSpace(osMessageQueueId_t msgq_id)
  171. {
  172. struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;
  173. if (msgq == NULL) {
  174. return 0;
  175. } else {
  176. return k_msgq_num_free_get(&msgq->z_msgq);
  177. }
  178. }
  179. /**
  180. * @brief Get name of a Message Queue object.
  181. */
  182. const char *osMessageQueueGetName(osMessageQueueId_t msgq_id)
  183. {
  184. struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;
  185. if (!k_is_in_isr() && (msgq_id != NULL)) {
  186. return msgq->name;
  187. } else {
  188. return NULL;
  189. }
  190. }
  191. /**
  192. * @brief Reset a Message Queue to initial empty state.
  193. */
  194. osStatus_t osMessageQueueReset(osMessageQueueId_t msgq_id)
  195. {
  196. struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;
  197. if (msgq == NULL) {
  198. return osErrorParameter;
  199. }
  200. if (k_is_in_isr()) {
  201. return osErrorISR;
  202. }
  203. /* The status code "osErrorResource" (the message queue specified by
  204. * parameter msgq_id is in an invalid message queue state) is not
  205. * supported in Zephyr.
  206. */
  207. k_msgq_purge(&msgq->z_msgq);
  208. return osOK;
  209. }
  210. /**
  211. * @brief Delete a Message Queue object.
  212. */
  213. osStatus_t osMessageQueueDelete(osMessageQueueId_t msgq_id)
  214. {
  215. struct cv2_msgq *msgq = (struct cv2_msgq *)msgq_id;
  216. if (msgq == NULL) {
  217. return osErrorParameter;
  218. }
  219. if (k_is_in_isr()) {
  220. return osErrorISR;
  221. }
  222. /* The status code "osErrorResource" (the message queue specified by
  223. * parameter msgq_id is in an invalid message queue state) is not
  224. * supported in Zephyr.
  225. */
  226. if (msgq->is_dynamic_allocation) {
  227. k_free(msgq->pool);
  228. }
  229. k_mem_slab_free(&cv2_msgq_slab, (void *)&msgq);
  230. return osOK;
  231. }