ChibiOS/RT
2.5.1
serial.c
Go to the documentation of this file.
00001 /*
00002     ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010,
00003                  2011,2012 Giovanni Di Sirio.
00004 
00005     This file is part of ChibiOS/RT.
00006 
00007     ChibiOS/RT is free software; you can redistribute it and/or modify
00008     it under the terms of the GNU General Public License as published by
00009     the Free Software Foundation; either version 3 of the License, or
00010     (at your option) any later version.
00011 
00012     ChibiOS/RT is distributed in the hope that it will be useful,
00013     but WITHOUT ANY WARRANTY; without even the implied warranty of
00014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015     GNU General Public License for more details.
00016 
00017     You should have received a copy of the GNU General Public License
00018     along with this program.  If not, see <http://www.gnu.org/licenses/>.
00019 */
00020 
00021 /**
00022  * @file    serial.c
00023  * @brief   Serial Driver code.
00024  *
00025  * @addtogroup SERIAL
00026  * @{
00027  */
00028 
00029 #include "ch.h"
00030 #include "hal.h"
00031 
00032 #if HAL_USE_SERIAL || defined(__DOXYGEN__)
00033 
00034 /*===========================================================================*/
00035 /* Driver local definitions.                                                 */
00036 /*===========================================================================*/
00037 
00038 /*===========================================================================*/
00039 /* Driver exported variables.                                                */
00040 /*===========================================================================*/
00041 
00042 /*===========================================================================*/
00043 /* Driver local variables.                                                   */
00044 /*===========================================================================*/
00045 
00046 /*===========================================================================*/
00047 /* Driver local functions.                                                   */
00048 /*===========================================================================*/
00049 
00050 /*
00051  * Interface implementation, the following functions just invoke the equivalent
00052  * queue-level function or macro.
00053  */
00054 
00055 static size_t write(void *ip, const uint8_t *bp, size_t n) {
00056 
00057   return chOQWriteTimeout(&((SerialDriver *)ip)->oqueue, bp,
00058                           n, TIME_INFINITE);
00059 }
00060 
00061 static size_t read(void *ip, uint8_t *bp, size_t n) {
00062 
00063   return chIQReadTimeout(&((SerialDriver *)ip)->iqueue, bp,
00064                          n, TIME_INFINITE);
00065 }
00066 
00067 static msg_t put(void *ip, uint8_t b) {
00068 
00069   return chOQPutTimeout(&((SerialDriver *)ip)->oqueue, b, TIME_INFINITE);
00070 }
00071 
00072 static msg_t get(void *ip) {
00073 
00074   return chIQGetTimeout(&((SerialDriver *)ip)->iqueue, TIME_INFINITE);
00075 }
00076 
00077 static msg_t putt(void *ip, uint8_t b, systime_t timeout) {
00078 
00079   return chOQPutTimeout(&((SerialDriver *)ip)->oqueue, b, timeout);
00080 }
00081 
00082 static msg_t gett(void *ip, systime_t timeout) {
00083 
00084   return chIQGetTimeout(&((SerialDriver *)ip)->iqueue, timeout);
00085 }
00086 
00087 static size_t writet(void *ip, const uint8_t *bp, size_t n, systime_t time) {
00088 
00089   return chOQWriteTimeout(&((SerialDriver *)ip)->oqueue, bp, n, time);
00090 }
00091 
00092 static size_t readt(void *ip, uint8_t *bp, size_t n, systime_t time) {
00093 
00094   return chIQReadTimeout(&((SerialDriver *)ip)->iqueue, bp, n, time);
00095 }
00096 
00097 static const struct SerialDriverVMT vmt = {
00098   write, read, put, get,
00099   putt, gett, writet, readt
00100 };
00101 
00102 /*===========================================================================*/
00103 /* Driver exported functions.                                                */
00104 /*===========================================================================*/
00105 
00106 /**
00107  * @brief   Serial Driver initialization.
00108  * @note    This function is implicitly invoked by @p halInit(), there is
00109  *          no need to explicitly initialize the driver.
00110  *
00111  * @init
00112  */
00113 void sdInit(void) {
00114 
00115   sd_lld_init();
00116 }
00117 
00118 /**
00119  * @brief   Initializes a generic full duplex driver object.
00120  * @details The HW dependent part of the initialization has to be performed
00121  *          outside, usually in the hardware initialization code.
00122  *
00123  * @param[out] sdp      pointer to a @p SerialDriver structure
00124  * @param[in] inotify   pointer to a callback function that is invoked when
00125  *                      some data is read from the Queue. The value can be
00126  *                      @p NULL.
00127  * @param[in] onotify   pointer to a callback function that is invoked when
00128  *                      some data is written in the Queue. The value can be
00129  *                      @p NULL.
00130  *
00131  * @init
00132  */
00133 void sdObjectInit(SerialDriver *sdp, qnotify_t inotify, qnotify_t onotify) {
00134 
00135   sdp->vmt = &vmt;
00136   chEvtInit(&sdp->event);
00137   sdp->state = SD_STOP;
00138   chIQInit(&sdp->iqueue, sdp->ib, SERIAL_BUFFERS_SIZE, inotify, sdp);
00139   chOQInit(&sdp->oqueue, sdp->ob, SERIAL_BUFFERS_SIZE, onotify, sdp);
00140 }
00141 
00142 /**
00143  * @brief   Configures and starts the driver.
00144  *
00145  * @param[in] sdp       pointer to a @p SerialDriver object
00146  * @param[in] config    the architecture-dependent serial driver configuration.
00147  *                      If this parameter is set to @p NULL then a default
00148  *                      configuration is used.
00149  *
00150  * @api
00151  */
00152 void sdStart(SerialDriver *sdp, const SerialConfig *config) {
00153 
00154   chDbgCheck(sdp != NULL, "sdStart");
00155 
00156   chSysLock();
00157   chDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY),
00158               "sdStart(), #1",
00159               "invalid state");
00160   sd_lld_start(sdp, config);
00161   sdp->state = SD_READY;
00162   chSysUnlock();
00163 }
00164 
00165 /**
00166  * @brief   Stops the driver.
00167  * @details Any thread waiting on the driver's queues will be awakened with
00168  *          the message @p Q_RESET.
00169  *
00170  * @param[in] sdp       pointer to a @p SerialDriver object
00171  *
00172  * @api
00173  */
00174 void sdStop(SerialDriver *sdp) {
00175 
00176   chDbgCheck(sdp != NULL, "sdStop");
00177 
00178   chSysLock();
00179   chDbgAssert((sdp->state == SD_STOP) || (sdp->state == SD_READY),
00180               "sdStop(), #1",
00181               "invalid state");
00182   sd_lld_stop(sdp);
00183   sdp->state = SD_STOP;
00184   chOQResetI(&sdp->oqueue);
00185   chIQResetI(&sdp->iqueue);
00186   chSchRescheduleS();
00187   chSysUnlock();
00188 }
00189 
00190 /**
00191  * @brief   Handles incoming data.
00192  * @details This function must be called from the input interrupt service
00193  *          routine in order to enqueue incoming data and generate the
00194  *          related events.
00195  * @note    The incoming data event is only generated when the input queue
00196  *          becomes non-empty.
00197  * @note    In order to gain some performance it is suggested to not use
00198  *          this function directly but copy this code directly into the
00199  *          interrupt service routine.
00200  *
00201  * @param[in] sdp       pointer to a @p SerialDriver structure
00202  * @param[in] b         the byte to be written in the driver's Input Queue
00203  *
00204  * @iclass
00205  */
00206 void sdIncomingDataI(SerialDriver *sdp, uint8_t b) {
00207 
00208   chDbgCheckClassI();
00209   chDbgCheck(sdp != NULL, "sdIncomingDataI");
00210 
00211   if (chIQIsEmptyI(&sdp->iqueue))
00212     chnAddFlagsI(sdp, CHN_INPUT_AVAILABLE);
00213   if (chIQPutI(&sdp->iqueue, b) < Q_OK)
00214     chnAddFlagsI(sdp, SD_OVERRUN_ERROR);
00215 }
00216 
00217 /**
00218  * @brief   Handles outgoing data.
00219  * @details Must be called from the output interrupt service routine in order
00220  *          to get the next byte to be transmitted.
00221  * @note    In order to gain some performance it is suggested to not use
00222  *          this function directly but copy this code directly into the
00223  *          interrupt service routine.
00224  *
00225  * @param[in] sdp       pointer to a @p SerialDriver structure
00226  * @return              The byte value read from the driver's output queue.
00227  * @retval Q_EMPTY      if the queue is empty (the lower driver usually
00228  *                      disables the interrupt source when this happens).
00229  *
00230  * @iclass
00231  */
00232 msg_t sdRequestDataI(SerialDriver *sdp) {
00233   msg_t  b;
00234 
00235   chDbgCheckClassI();
00236   chDbgCheck(sdp != NULL, "sdRequestDataI");
00237 
00238   b = chOQGetI(&sdp->oqueue);
00239   if (b < Q_OK)
00240     chnAddFlagsI(sdp, CHN_OUTPUT_EMPTY);
00241   return b;
00242 }
00243 
00244 #endif /* HAL_USE_SERIAL */
00245 
00246 /** @} */