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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  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_Config.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. #ifdef __CORTEX_A9
  42. #include "rt_HAL_CA.h"
  43. #else
  44. #include "rt_HAL_CM.h"
  45. #endif
  46. /*----------------------------------------------------------------------------
  47. * Functions
  48. *---------------------------------------------------------------------------*/
  49. /*--------------------------- rt_mbx_init -----------------------------------*/
  50. void rt_mbx_init (OS_ID mailbox, U16 mbx_size) {
  51. /* Initialize a mailbox */
  52. P_MCB p_MCB = mailbox;
  53. p_MCB->cb_type = MCB;
  54. p_MCB->state = 0;
  55. p_MCB->isr_st = 0;
  56. p_MCB->p_lnk = NULL;
  57. p_MCB->first = 0;
  58. p_MCB->last = 0;
  59. p_MCB->count = 0;
  60. p_MCB->size = (mbx_size + sizeof(void *) - sizeof(struct OS_MCB)) /
  61. (U32)sizeof (void *);
  62. }
  63. /*--------------------------- rt_mbx_send -----------------------------------*/
  64. OS_RESULT rt_mbx_send (OS_ID mailbox, void *p_msg, U16 timeout) {
  65. /* Send message to a mailbox */
  66. P_MCB p_MCB = mailbox;
  67. P_TCB p_TCB;
  68. if ((p_MCB->p_lnk != NULL) && (p_MCB->state == 1)) {
  69. /* A task is waiting for message */
  70. p_TCB = rt_get_first ((P_XCB)p_MCB);
  71. #ifdef __CMSIS_RTOS
  72. rt_ret_val2(p_TCB, 0x10/*osEventMessage*/, (U32)p_msg);
  73. #else
  74. *p_TCB->msg = p_msg;
  75. rt_ret_val (p_TCB, OS_R_MBX);
  76. #endif
  77. rt_rmv_dly (p_TCB);
  78. rt_dispatch (p_TCB);
  79. }
  80. else {
  81. /* Store message in mailbox queue */
  82. if (p_MCB->count == p_MCB->size) {
  83. /* No free message entry, wait for one. If message queue is full, */
  84. /* then no task is waiting for message. The 'p_MCB->p_lnk' list */
  85. /* pointer can now be reused for send message waits task list. */
  86. if (timeout == 0) {
  87. return (OS_R_TMO);
  88. }
  89. if (p_MCB->p_lnk != NULL) {
  90. rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
  91. }
  92. else {
  93. p_MCB->p_lnk = os_tsk.run;
  94. os_tsk.run->p_lnk = NULL;
  95. os_tsk.run->p_rlnk = (P_TCB)p_MCB;
  96. /* Task is waiting to send a message */
  97. p_MCB->state = 2;
  98. }
  99. os_tsk.run->msg = p_msg;
  100. rt_block (timeout, WAIT_MBX);
  101. return (OS_R_TMO);
  102. }
  103. /* Yes, there is a free entry in a mailbox. */
  104. p_MCB->msg[p_MCB->first] = p_msg;
  105. rt_inc (&p_MCB->count);
  106. if (++p_MCB->first == p_MCB->size) {
  107. p_MCB->first = 0;
  108. }
  109. }
  110. return (OS_R_OK);
  111. }
  112. /*--------------------------- rt_mbx_wait -----------------------------------*/
  113. OS_RESULT rt_mbx_wait (OS_ID mailbox, void **message, U16 timeout) {
  114. /* Receive a message; possibly wait for it */
  115. P_MCB p_MCB = mailbox;
  116. P_TCB p_TCB;
  117. /* If a message is available in the fifo buffer */
  118. /* remove it from the fifo buffer and return. */
  119. if (p_MCB->count) {
  120. *message = p_MCB->msg[p_MCB->last];
  121. if (++p_MCB->last == p_MCB->size) {
  122. p_MCB->last = 0;
  123. }
  124. if ((p_MCB->p_lnk != NULL) && (p_MCB->state == 2)) {
  125. /* A task is waiting to send message */
  126. p_TCB = rt_get_first ((P_XCB)p_MCB);
  127. #ifdef __CMSIS_RTOS
  128. rt_ret_val(p_TCB, 0/*osOK*/);
  129. #else
  130. rt_ret_val(p_TCB, OS_R_OK);
  131. #endif
  132. p_MCB->msg[p_MCB->first] = p_TCB->msg;
  133. if (++p_MCB->first == p_MCB->size) {
  134. p_MCB->first = 0;
  135. }
  136. rt_rmv_dly (p_TCB);
  137. rt_dispatch (p_TCB);
  138. }
  139. else {
  140. rt_dec (&p_MCB->count);
  141. }
  142. return (OS_R_OK);
  143. }
  144. /* No message available: wait for one */
  145. if (timeout == 0) {
  146. return (OS_R_TMO);
  147. }
  148. if (p_MCB->p_lnk != NULL) {
  149. rt_put_prio ((P_XCB)p_MCB, os_tsk.run);
  150. }
  151. else {
  152. p_MCB->p_lnk = os_tsk.run;
  153. os_tsk.run->p_lnk = NULL;
  154. os_tsk.run->p_rlnk = (P_TCB)p_MCB;
  155. /* Task is waiting to receive a message */
  156. p_MCB->state = 1;
  157. }
  158. rt_block(timeout, WAIT_MBX);
  159. #ifndef __CMSIS_RTOS
  160. os_tsk.run->msg = message;
  161. #endif
  162. return (OS_R_TMO);
  163. }
  164. /*--------------------------- rt_mbx_check ----------------------------------*/
  165. OS_RESULT rt_mbx_check (OS_ID mailbox) {
  166. /* Check for free space in a mailbox. Returns the number of messages */
  167. /* that can be stored to a mailbox. It returns 0 when mailbox is full. */
  168. P_MCB p_MCB = mailbox;
  169. return (p_MCB->size - p_MCB->count);
  170. }
  171. /*--------------------------- isr_mbx_send ----------------------------------*/
  172. void isr_mbx_send (OS_ID mailbox, void *p_msg) {
  173. /* Same function as "os_mbx_send", but to be called by ISRs. */
  174. P_MCB p_MCB = mailbox;
  175. rt_psq_enq (p_MCB, (U32)p_msg);
  176. rt_psh_req ();
  177. }
  178. /*--------------------------- isr_mbx_receive -------------------------------*/
  179. OS_RESULT isr_mbx_receive (OS_ID mailbox, void **message) {
  180. /* Receive a message in the interrupt function. The interrupt function */
  181. /* should not wait for a message since this would block the rtx os. */
  182. P_MCB p_MCB = mailbox;
  183. if (p_MCB->count) {
  184. /* A message is available in the fifo buffer. */
  185. *message = p_MCB->msg[p_MCB->last];
  186. if (p_MCB->state == 2) {
  187. /* A task is locked waiting to send message */
  188. rt_psq_enq (p_MCB, 0);
  189. rt_psh_req ();
  190. }
  191. rt_dec (&p_MCB->count);
  192. if (++p_MCB->last == p_MCB->size) {
  193. p_MCB->last = 0;
  194. }
  195. return (OS_R_MBX);
  196. }
  197. return (OS_R_OK);
  198. }
  199. /*--------------------------- rt_mbx_psh ------------------------------------*/
  200. void rt_mbx_psh (P_MCB p_CB, void *p_msg) {
  201. /* Store the message to the mailbox queue or pass it to task directly. */
  202. P_TCB p_TCB;
  203. void *mem;
  204. if (p_CB->p_lnk != NULL) switch (p_CB->state) {
  205. #ifdef __CMSIS_RTOS
  206. case 3:
  207. /* Task is waiting to allocate memory, remove it from the waiting list */
  208. mem = rt_alloc_box(p_msg);
  209. if (mem == NULL) break;
  210. p_TCB = rt_get_first ((P_XCB)p_CB);
  211. rt_ret_val(p_TCB, (U32)mem);
  212. p_TCB->state = READY;
  213. rt_rmv_dly (p_TCB);
  214. rt_put_prio (&os_rdy, p_TCB);
  215. break;
  216. #endif
  217. case 2:
  218. /* Task is waiting to send a message, remove it from the waiting list */
  219. p_TCB = rt_get_first ((P_XCB)p_CB);
  220. #ifdef __CMSIS_RTOS
  221. rt_ret_val(p_TCB, 0/*osOK*/);
  222. #else
  223. rt_ret_val(p_TCB, OS_R_OK);
  224. #endif
  225. p_CB->msg[p_CB->first] = p_TCB->msg;
  226. rt_inc (&p_CB->count);
  227. if (++p_CB->first == p_CB->size) {
  228. p_CB->first = 0;
  229. }
  230. p_TCB->state = READY;
  231. rt_rmv_dly (p_TCB);
  232. rt_put_prio (&os_rdy, p_TCB);
  233. break;
  234. case 1:
  235. /* Task is waiting for a message, pass the message to the task directly */
  236. p_TCB = rt_get_first ((P_XCB)p_CB);
  237. #ifdef __CMSIS_RTOS
  238. rt_ret_val2(p_TCB, 0x10/*osEventMessage*/, (U32)p_msg);
  239. #else
  240. *p_TCB->msg = p_msg;
  241. rt_ret_val (p_TCB, OS_R_MBX);
  242. #endif
  243. p_TCB->state = READY;
  244. rt_rmv_dly (p_TCB);
  245. rt_put_prio (&os_rdy, p_TCB);
  246. break;
  247. } else {
  248. /* No task is waiting for a message, store it to the mailbox queue */
  249. if (p_CB->count < p_CB->size) {
  250. p_CB->msg[p_CB->first] = p_msg;
  251. rt_inc (&p_CB->count);
  252. if (++p_CB->first == p_CB->size) {
  253. p_CB->first = 0;
  254. }
  255. }
  256. else {
  257. os_error (OS_ERR_MBX_OVF);
  258. }
  259. }
  260. }
  261. /*----------------------------------------------------------------------------
  262. * end of file
  263. *---------------------------------------------------------------------------*/