Keyboard firmwares for Atmel AVR and Cortex-M
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.

rt_Mailbox.c 9.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /*----------------------------------------------------------------------------
  2. * RL-ARM - RTX
  3. *----------------------------------------------------------------------------
  4. * Name: RT_MAILBOX.C
  5. * Purpose: Implements waits and wake-ups for mailbox messages
  6. * Rev.: V4.60
  7. *----------------------------------------------------------------------------
  8. *
  9. * Copyright (c) 1999-2009 KEIL, 2009-2012 ARM Germany GmbH
  10. * All rights reserved.
  11. * Redistribution and use in source and binary forms, with or without
  12. * modification, are permitted provided that the following conditions are met:
  13. * - Redistributions of source code must retain the above copyright
  14. * notice, this list of conditions and the following disclaimer.
  15. * - Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in the
  17. * documentation and/or other materials provided with the distribution.
  18. * - Neither the name of ARM nor the names of its contributors may be used
  19. * to endorse or promote products derived from this software without
  20. * specific prior written permission.
  21. *
  22. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  23. * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25. * ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
  26. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  27. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  28. * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  29. * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  30. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  31. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  32. * POSSIBILITY OF SUCH DAMAGE.
  33. *---------------------------------------------------------------------------*/
  34. #include "rt_TypeDef.h"
  35. #include "RTX_Conf.h"
  36. #include "rt_System.h"
  37. #include "rt_List.h"
  38. #include "rt_Mailbox.h"
  39. #include "rt_MemBox.h"
  40. #include "rt_Task.h"
  41. #include "rt_HAL_CM.h"
  42. /*----------------------------------------------------------------------------
  43. * Functions
  44. *---------------------------------------------------------------------------*/
  45. /*--------------------------- rt_mbx_init -----------------------------------*/
  46. void rt_mbx_init (OS_ID mailbox, U16 mbx_size) {
  47. /* Initialize a mailbox */
  48. P_MCB p_MCB = mailbox;
  49. p_MCB->cb_type = MCB;
  50. p_MCB->state = 0;
  51. p_MCB->isr_st = 0;
  52. p_MCB->p_lnk = NULL;
  53. p_MCB->first = 0;
  54. p_MCB->last = 0;
  55. p_MCB->count = 0;
  56. p_MCB->size = (mbx_size + sizeof(void *) - sizeof(struct OS_MCB)) /
  57. (U32)sizeof (void *);
  58. }
  59. /*--------------------------- rt_mbx_send -----------------------------------*/
  60. OS_RESULT rt_mbx_send (OS_ID mailbox, void *p_msg, U16 timeout) {
  61. /* Send message to a mailbox */
  62. P_MCB p_MCB = mailbox;
  63. P_TCB p_TCB;
  64. if ((p_MCB->p_lnk != NULL) && (p_MCB->state == 1)) {
  65. /* A task is waiting for message */
  66. p_TCB = rt_get_first ((P_XCB)p_MCB);
  67. #ifdef __CMSIS_RTOS
  68. rt_ret_val2(p_TCB, 0x10/*osEventMessage*/, (U32)p_msg);
  69. #else
  70. *p_TCB->msg = p_msg;
  71. rt_ret_val (p_TCB, OS_R_MBX);
  72. #endif
  73. rt_rmv_dly (p_TCB);
  74. rt_dispatch (p_TCB);
  75. }
  76. else {
  77. /* Store message in mailbox queue */
  78. if (p_MCB->count == p_MCB->size) {
  79. /* No free message entry, wait for one. If message queue is full, */
  80. /* then no task is waiting for message. The 'p_MCB->p_lnk' list */
  81. /* pointer can now be reused for send message waits task list. */
  82. if (timeout == 0) {
  83. return (OS_R_TMO);
  84. }
  85. if (p_MCB->p_lnk != NULL) {
  86. rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
  87. }
  88. else {
  89. p_MCB->p_lnk = os_tsk.run;
  90. os_tsk.run->p_lnk = NULL;
  91. os_tsk.run->p_rlnk = (P_TCB)p_MCB;
  92. /* Task is waiting to send a message */
  93. p_MCB->state = 2;
  94. }
  95. os_tsk.run->msg = p_msg;
  96. rt_block (timeout, WAIT_MBX);
  97. return (OS_R_TMO);
  98. }
  99. /* Yes, there is a free entry in a mailbox. */
  100. p_MCB->msg[p_MCB->first] = p_msg;
  101. rt_inc (&p_MCB->count);
  102. if (++p_MCB->first == p_MCB->size) {
  103. p_MCB->first = 0;
  104. }
  105. }
  106. return (OS_R_OK);
  107. }
  108. /*--------------------------- rt_mbx_wait -----------------------------------*/
  109. OS_RESULT rt_mbx_wait (OS_ID mailbox, void **message, U16 timeout) {
  110. /* Receive a message; possibly wait for it */
  111. P_MCB p_MCB = mailbox;
  112. P_TCB p_TCB;
  113. /* If a message is available in the fifo buffer */
  114. /* remove it from the fifo buffer and return. */
  115. if (p_MCB->count) {
  116. *message = p_MCB->msg[p_MCB->last];
  117. if (++p_MCB->last == p_MCB->size) {
  118. p_MCB->last = 0;
  119. }
  120. if ((p_MCB->p_lnk != NULL) && (p_MCB->state == 2)) {
  121. /* A task is waiting to send message */
  122. p_TCB = rt_get_first ((P_XCB)p_MCB);
  123. #ifdef __CMSIS_RTOS
  124. rt_ret_val(p_TCB, 0/*osOK*/);
  125. #else
  126. rt_ret_val(p_TCB, OS_R_OK);
  127. #endif
  128. p_MCB->msg[p_MCB->first] = p_TCB->msg;
  129. if (++p_MCB->first == p_MCB->size) {
  130. p_MCB->first = 0;
  131. }
  132. rt_rmv_dly (p_TCB);
  133. rt_dispatch (p_TCB);
  134. }
  135. else {
  136. rt_dec (&p_MCB->count);
  137. }
  138. return (OS_R_OK);
  139. }
  140. /* No message available: wait for one */
  141. if (timeout == 0) {
  142. return (OS_R_TMO);
  143. }
  144. if (p_MCB->p_lnk != NULL) {
  145. rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
  146. }
  147. else {
  148. p_MCB->p_lnk = os_tsk.run;
  149. os_tsk.run->p_lnk = NULL;
  150. os_tsk.run->p_rlnk = (P_TCB)p_MCB;
  151. /* Task is waiting to receive a message */
  152. p_MCB->state = 1;
  153. }
  154. rt_block(timeout, WAIT_MBX);
  155. #ifndef __CMSIS_RTOS
  156. os_tsk.run->msg = message;
  157. #endif
  158. return (OS_R_TMO);
  159. }
  160. /*--------------------------- rt_mbx_check ----------------------------------*/
  161. OS_RESULT rt_mbx_check (OS_ID mailbox) {
  162. /* Check for free space in a mailbox. Returns the number of messages */
  163. /* that can be stored to a mailbox. It returns 0 when mailbox is full. */
  164. P_MCB p_MCB = mailbox;
  165. return (p_MCB->size - p_MCB->count);
  166. }
  167. /*--------------------------- isr_mbx_send ----------------------------------*/
  168. void isr_mbx_send (OS_ID mailbox, void *p_msg) {
  169. /* Same function as "os_mbx_send", but to be called by ISRs. */
  170. P_MCB p_MCB = mailbox;
  171. rt_psq_enq (p_MCB, (U32)p_msg);
  172. rt_psh_req ();
  173. }
  174. /*--------------------------- isr_mbx_receive -------------------------------*/
  175. OS_RESULT isr_mbx_receive (OS_ID mailbox, void **message) {
  176. /* Receive a message in the interrupt function. The interrupt function */
  177. /* should not wait for a message since this would block the rtx os. */
  178. P_MCB p_MCB = mailbox;
  179. if (p_MCB->count) {
  180. /* A message is available in the fifo buffer. */
  181. *message = p_MCB->msg[p_MCB->last];
  182. if (p_MCB->state == 2) {
  183. /* A task is locked waiting to send message */
  184. rt_psq_enq (p_MCB, 0);
  185. rt_psh_req ();
  186. }
  187. rt_dec (&p_MCB->count);
  188. if (++p_MCB->last == p_MCB->size) {
  189. p_MCB->last = 0;
  190. }
  191. return (OS_R_MBX);
  192. }
  193. return (OS_R_OK);
  194. }
  195. /*--------------------------- rt_mbx_psh ------------------------------------*/
  196. void rt_mbx_psh (P_MCB p_CB, void *p_msg) {
  197. /* Store the message to the mailbox queue or pass it to task directly. */
  198. P_TCB p_TCB;
  199. void *mem;
  200. if (p_CB->p_lnk != NULL) switch (p_CB->state) {
  201. #ifdef __CMSIS_RTOS
  202. case 3:
  203. /* Task is waiting to allocate memory, remove it from the waiting list */
  204. mem = rt_alloc_box(p_msg);
  205. if (mem == NULL) break;
  206. p_TCB = rt_get_first ((P_XCB)p_CB);
  207. rt_ret_val(p_TCB, (U32)mem);
  208. p_TCB->state = READY;
  209. rt_rmv_dly (p_TCB);
  210. rt_put_prio (&os_rdy, p_TCB);
  211. break;
  212. #endif
  213. case 2:
  214. /* Task is waiting to send a message, remove it from the waiting list */
  215. p_TCB = rt_get_first ((P_XCB)p_CB);
  216. #ifdef __CMSIS_RTOS
  217. rt_ret_val(p_TCB, 0/*osOK*/);
  218. #else
  219. rt_ret_val(p_TCB, OS_R_OK);
  220. #endif
  221. p_CB->msg[p_CB->first] = p_TCB->msg;
  222. rt_inc (&p_CB->count);
  223. if (++p_CB->first == p_CB->size) {
  224. p_CB->first = 0;
  225. }
  226. p_TCB->state = READY;
  227. rt_rmv_dly (p_TCB);
  228. rt_put_prio (&os_rdy, p_TCB);
  229. break;
  230. case 1:
  231. /* Task is waiting for a message, pass the message to the task directly */
  232. p_TCB = rt_get_first ((P_XCB)p_CB);
  233. #ifdef __CMSIS_RTOS
  234. rt_ret_val2(p_TCB, 0x10/*osEventMessage*/, (U32)p_msg);
  235. #else
  236. *p_TCB->msg = p_msg;
  237. rt_ret_val (p_TCB, OS_R_MBX);
  238. #endif
  239. p_TCB->state = READY;
  240. rt_rmv_dly (p_TCB);
  241. rt_put_prio (&os_rdy, p_TCB);
  242. break;
  243. } else {
  244. /* No task is waiting for a message, store it to the mailbox queue */
  245. if (p_CB->count < p_CB->size) {
  246. p_CB->msg[p_CB->first] = p_msg;
  247. rt_inc (&p_CB->count);
  248. if (++p_CB->first == p_CB->size) {
  249. p_CB->first = 0;
  250. }
  251. }
  252. else {
  253. os_error (OS_ERR_MBX_OVF);
  254. }
  255. }
  256. }
  257. /*----------------------------------------------------------------------------
  258. * end of file
  259. *---------------------------------------------------------------------------*/