ChibiOS/RT Architecture - Reference Manual - Guides |
00001 /* 00002 ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010 Giovanni Di Sirio. 00003 00004 This file is part of ChibiOS/RT. 00005 00006 ChibiOS/RT is free software; you can redistribute it and/or modify 00007 it under the terms of the GNU General Public License as published by 00008 the Free Software Foundation; either version 3 of the License, or 00009 (at your option) any later version. 00010 00011 ChibiOS/RT is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00014 GNU General Public License for more details. 00015 00016 You should have received a copy of the GNU General Public License 00017 along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 00019 --- 00020 00021 A special exception to the GPL can be applied should you wish to distribute 00022 a combined work that includes ChibiOS/RT, without being obliged to provide 00023 the source code for any proprietary components. See the file exception.txt 00024 for full details of how and when the exception can be applied. 00025 */ 00026 00027 /** 00028 * @file chmboxes.c 00029 * @brief Mailboxes code. 00030 * 00031 * @addtogroup mailboxes 00032 * @details Asynchronous messages. 00033 * <h2>Operation mode</h2> 00034 * A mailbox is an asynchronous communication mechanism.<br> 00035 * Operations defined for mailboxes: 00036 * - <b>Post</b>: Posts a message on the mailbox in FIFO order. 00037 * - <b>Post Ahead</b>: Posts a message on the mailbox with urgent 00038 * priority. 00039 * - <b>Fetch</b>: A message is fetched from the mailbox and removed 00040 * from the queue. 00041 * - <b>Reset</b>: The mailbox is emptied and all the stored messages 00042 * are lost. 00043 * . 00044 * A message is a variable of type msg_t that is guaranteed to have 00045 * the same size of and be compatible with (data) pointers (anyway an 00046 * explicit cast is needed). 00047 * If larger messages need to be exchanged then a pointer to a 00048 * structure can be posted in the mailbox but the posting side has 00049 * no predefined way to know when the message has been processed. A 00050 * possible approach is to allocate memory (from a memory pool as 00051 * example) from the posting side and free it on the fetching side. 00052 * Another approach is to set a "done" flag into the structure pointed 00053 * by the message.<br> 00054 * In order to use the mailboxes APIs the @p CH_USE_MAILBOXES option 00055 * must be enabled in @p chconf.h. 00056 * @{ 00057 */ 00058 00059 #include "ch.h" 00060 00061 #if CH_USE_MAILBOXES 00062 /** 00063 * @brief Initializes a Mailbox object. 00064 * 00065 * @param[out] mbp the pointer to the Mailbox structure to be initialized 00066 * @param[in] buf the circular messages buffer 00067 * @param[in] n the buffer size as number of @p msg_t 00068 */ 00069 void chMBInit(Mailbox *mbp, msg_t *buf, cnt_t n) { 00070 00071 chDbgCheck((mbp != NULL) && (buf != NULL) && (n > 0), "chMBInit"); 00072 00073 mbp->mb_buffer = mbp->mb_wrptr = mbp->mb_rdptr = buf; 00074 mbp->mb_top = &buf[n]; 00075 chSemInit(&mbp->mb_emptysem, n); 00076 chSemInit(&mbp->mb_fullsem, 0); 00077 } 00078 00079 /** 00080 * @brief Resets a Mailbox object. 00081 * @details All the waiting threads are resumed with status @p RDY_RESET and 00082 * the queued messages are lost. 00083 * 00084 * @param[in] mbp the pointer to an initialized Mailbox object 00085 */ 00086 void chMBReset(Mailbox *mbp) { 00087 00088 chDbgCheck(mbp != NULL, "chMBReset"); 00089 00090 chSysLock(); 00091 mbp->mb_wrptr = mbp->mb_rdptr = mbp->mb_buffer; 00092 chSemResetI(&mbp->mb_emptysem, mbp->mb_top - mbp->mb_buffer); 00093 chSemResetI(&mbp->mb_fullsem, 0); 00094 chSchRescheduleS(); 00095 chSysUnlock(); 00096 } 00097 00098 /** 00099 * @brief Posts a message into a mailbox. 00100 * @details The invoking thread waits until a empty slot in the mailbox becomes 00101 * available or the specified time runs out. 00102 * 00103 * @param[in] mbp the pointer to an initialized Mailbox object 00104 * @param[in] msg the message to be posted on the mailbox 00105 * @param[in] time the number of ticks before the operation timeouts, 00106 * the following special values are allowed: 00107 * - @a TIME_IMMEDIATE immediate timeout. 00108 * - @a TIME_INFINITE no timeout. 00109 * . 00110 * @return The operation status. 00111 * @retval RDY_OK if the message was correctly posted. 00112 * @retval RDY_RESET if the mailbox was reset while waiting. 00113 * @retval RDY_TIMEOUT if the operation timed out. 00114 */ 00115 msg_t chMBPost(Mailbox *mbp, msg_t msg, systime_t time) { 00116 msg_t rdymsg; 00117 00118 chSysLock(); 00119 rdymsg = chMBPostS(mbp, msg, time); 00120 chSysUnlock(); 00121 return rdymsg; 00122 } 00123 00124 /** 00125 * @brief Posts a message into a mailbox. 00126 * @details The invoking thread waits until a empty slot in the mailbox becomes 00127 * available or the specified time runs out. 00128 * 00129 * @param[in] mbp the pointer to an initialized Mailbox object 00130 * @param[in] msg the message to be posted on the mailbox 00131 * @param[in] time the number of ticks before the operation timeouts, 00132 * the following special values are allowed: 00133 * - @a TIME_IMMEDIATE immediate timeout. 00134 * - @a TIME_INFINITE no timeout. 00135 * . 00136 * @return The operation status. 00137 * @retval RDY_OK if the message was correctly posted. 00138 * @retval RDY_RESET if the mailbox was reset while waiting. 00139 * @retval RDY_TIMEOUT if the operation timed out. 00140 */ 00141 msg_t chMBPostS(Mailbox *mbp, msg_t msg, systime_t time) { 00142 msg_t rdymsg; 00143 00144 chDbgCheck(mbp != NULL, "chMBPostS"); 00145 00146 rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time); 00147 if (rdymsg == RDY_OK) { 00148 *mbp->mb_wrptr++ = msg; 00149 if (mbp->mb_wrptr >= mbp->mb_top) 00150 mbp->mb_wrptr = mbp->mb_buffer; 00151 chSemSignalI(&mbp->mb_fullsem); 00152 chSchRescheduleS(); 00153 } 00154 return rdymsg; 00155 } 00156 00157 /** 00158 * @brief Posts an high priority message into a mailbox. 00159 * @details The invoking thread waits until a empty slot in the mailbox becomes 00160 * available or the specified time runs out. 00161 * 00162 * @param[in] mbp the pointer to an initialized Mailbox object 00163 * @param[in] msg the message to be posted on the mailbox 00164 * @param[in] time the number of ticks before the operation timeouts, 00165 * the following special values are allowed: 00166 * - @a TIME_IMMEDIATE immediate timeout. 00167 * - @a TIME_INFINITE no timeout. 00168 * . 00169 * @return The operation status. 00170 * @retval RDY_OK if the message was correctly posted. 00171 * @retval RDY_RESET if the mailbox was reset while waiting. 00172 * @retval RDY_TIMEOUT if the operation timed out. 00173 */ 00174 msg_t chMBPostAhead(Mailbox *mbp, msg_t msg, systime_t time) { 00175 msg_t rdymsg; 00176 00177 chSysLock(); 00178 rdymsg = chMBPostAheadS(mbp, msg, time); 00179 chSysUnlock(); 00180 return rdymsg; 00181 } 00182 00183 /** 00184 * @brief Posts an high priority message into a mailbox. 00185 * @details The invoking thread waits until a empty slot in the mailbox becomes 00186 * available or the specified time runs out. 00187 * 00188 * @param[in] mbp the pointer to an initialized Mailbox object 00189 * @param[in] msg the message to be posted on the mailbox 00190 * @param[in] time the number of ticks before the operation timeouts, 00191 * the following special values are allowed: 00192 * - @a TIME_IMMEDIATE immediate timeout. 00193 * - @a TIME_INFINITE no timeout. 00194 * . 00195 * @return The operation status. 00196 * @retval RDY_OK if the message was correctly posted. 00197 * @retval RDY_RESET if the mailbox was reset while waiting. 00198 * @retval RDY_TIMEOUT if the operation timed out. 00199 */ 00200 msg_t chMBPostAheadS(Mailbox *mbp, msg_t msg, systime_t time) { 00201 msg_t rdymsg; 00202 00203 chDbgCheck(mbp != NULL, "chMBPostAheadS"); 00204 00205 rdymsg = chSemWaitTimeoutS(&mbp->mb_emptysem, time); 00206 if (rdymsg == RDY_OK) { 00207 if (--mbp->mb_rdptr < mbp->mb_buffer) 00208 mbp->mb_rdptr = mbp->mb_top - 1; 00209 *mbp->mb_rdptr = msg; 00210 chSemSignalI(&mbp->mb_fullsem); 00211 chSchRescheduleS(); 00212 } 00213 return rdymsg; 00214 } 00215 00216 /** 00217 * @brief Retrieves a message from a mailbox. 00218 * @details The invoking thread waits until a message is posted in the mailbox 00219 * or the specified time runs out. 00220 * 00221 * @param[in] mbp the pointer to an initialized Mailbox object 00222 * @param[out] msgp pointer to a message variable for the received message 00223 * @param[in] time the number of ticks before the operation timeouts, 00224 * the following special values are allowed: 00225 * - @a TIME_IMMEDIATE immediate timeout. 00226 * - @a TIME_INFINITE no timeout. 00227 * . 00228 * @return The operation status. 00229 * @retval RDY_OK if a message was correctly fetched. 00230 * @retval RDY_RESET if the mailbox was reset while waiting. 00231 * @retval RDY_TIMEOUT if the operation timed out. 00232 */ 00233 msg_t chMBFetch(Mailbox *mbp, msg_t *msgp, systime_t time) { 00234 msg_t rdymsg; 00235 00236 chSysLock(); 00237 rdymsg = chMBFetchS(mbp, msgp, time); 00238 chSysUnlock(); 00239 return rdymsg; 00240 } 00241 00242 /** 00243 * @brief Retrieves a message from a mailbox. 00244 * @details The invoking thread waits until a message is posted in the mailbox 00245 * or the specified time runs out. 00246 * 00247 * @param[in] mbp the pointer to an initialized Mailbox object 00248 * @param[out] msgp pointer to a message variable for the received message 00249 * @param[in] time the number of ticks before the operation timeouts, 00250 * the following special values are allowed: 00251 * - @a TIME_IMMEDIATE immediate timeout. 00252 * - @a TIME_INFINITE no timeout. 00253 * . 00254 * @return The operation status. 00255 * @retval RDY_OK if a message was correctly fetched. 00256 * @retval RDY_RESET if the mailbox was reset while waiting. 00257 * @retval RDY_TIMEOUT if the operation timed out. 00258 */ 00259 msg_t chMBFetchS(Mailbox *mbp, msg_t *msgp, systime_t time) { 00260 msg_t rdymsg; 00261 00262 chDbgCheck((mbp != NULL) && (msgp != NULL), "chMBFetchS"); 00263 00264 rdymsg = chSemWaitTimeoutS(&mbp->mb_fullsem, time); 00265 if (rdymsg == RDY_OK) { 00266 *msgp = *mbp->mb_rdptr++; 00267 if (mbp->mb_rdptr >= mbp->mb_top) 00268 mbp->mb_rdptr = mbp->mb_buffer; 00269 chSemSignalI(&mbp->mb_emptysem); 00270 chSchRescheduleS(); 00271 } 00272 return rdymsg; 00273 } 00274 #endif /* CH_USE_MAILBOXES */ 00275 00276 /** @} */