ChibiOS/RT
2.5.1
uart.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    uart.c
00023  * @brief   UART Driver code.
00024  *
00025  * @addtogroup UART
00026  * @{
00027  */
00028 
00029 #include "ch.h"
00030 #include "hal.h"
00031 
00032 #if HAL_USE_UART || 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 /* Driver exported functions.                                                */
00052 /*===========================================================================*/
00053 
00054 /**
00055  * @brief   UART Driver initialization.
00056  * @note    This function is implicitly invoked by @p halInit(), there is
00057  *          no need to explicitly initialize the driver.
00058  *
00059  * @init
00060  */
00061 void uartInit(void) {
00062 
00063   uart_lld_init();
00064 }
00065 
00066 /**
00067  * @brief   Initializes the standard part of a @p UARTDriver structure.
00068  *
00069  * @param[out] uartp    pointer to the @p UARTDriver object
00070  *
00071  * @init
00072  */
00073 void uartObjectInit(UARTDriver *uartp) {
00074 
00075   uartp->state   = UART_STOP;
00076   uartp->txstate = UART_TX_IDLE;
00077   uartp->rxstate = UART_RX_IDLE;
00078   uartp->config  = NULL;
00079   /* Optional, user-defined initializer.*/
00080 #if defined(UART_DRIVER_EXT_INIT_HOOK)
00081   UART_DRIVER_EXT_INIT_HOOK(uartp);
00082 #endif
00083 }
00084 
00085 /**
00086  * @brief   Configures and activates the UART peripheral.
00087  *
00088  * @param[in] uartp     pointer to the @p UARTDriver object
00089  * @param[in] config    pointer to the @p UARTConfig object
00090  *
00091  * @api
00092  */
00093 void uartStart(UARTDriver *uartp, const UARTConfig *config) {
00094 
00095   chDbgCheck((uartp != NULL) && (config != NULL), "uartStart");
00096 
00097   chSysLock();
00098   chDbgAssert((uartp->state == UART_STOP) || (uartp->state == UART_READY),
00099               "uartStart(), #1", "invalid state");
00100 
00101   uartp->config = config;
00102   uart_lld_start(uartp);
00103   uartp->state = UART_READY;
00104   chSysUnlock();
00105 }
00106 
00107 /**
00108  * @brief   Deactivates the UART peripheral.
00109  *
00110  * @param[in] uartp     pointer to the @p UARTDriver object
00111  *
00112  * @api
00113  */
00114 void uartStop(UARTDriver *uartp) {
00115 
00116   chDbgCheck(uartp != NULL, "uartStop");
00117 
00118   chSysLock();
00119   chDbgAssert((uartp->state == UART_STOP) || (uartp->state == UART_READY),
00120               "uartStop(), #1", "invalid state");
00121 
00122   uart_lld_stop(uartp);
00123   uartp->state = UART_STOP;
00124   uartp->txstate = UART_TX_IDLE;
00125   uartp->rxstate = UART_RX_IDLE;
00126   chSysUnlock();
00127 }
00128 
00129 /**
00130  * @brief   Starts a transmission on the UART peripheral.
00131  * @note    The buffers are organized as uint8_t arrays for data sizes below
00132  *          or equal to 8 bits else it is organized as uint16_t arrays.
00133  *
00134  * @param[in] uartp     pointer to the @p UARTDriver object
00135  * @param[in] n         number of data frames to send
00136  * @param[in] txbuf     the pointer to the transmit buffer
00137  *
00138  * @api
00139  */
00140 void uartStartSend(UARTDriver *uartp, size_t n, const void *txbuf) {
00141 
00142   chDbgCheck((uartp != NULL) && (n > 0) && (txbuf != NULL),
00143              "uartStartSend");
00144              
00145   chSysLock();
00146   chDbgAssert((uartp->state == UART_READY) && (uartp->txstate == UART_TX_IDLE),
00147               "uartStartSend(), #1", "not active");
00148 
00149   uart_lld_start_send(uartp, n, txbuf);
00150   uartp->txstate = UART_TX_ACTIVE;
00151   chSysUnlock();
00152 }
00153 
00154 /**
00155  * @brief   Starts a transmission on the UART peripheral.
00156  * @note    The buffers are organized as uint8_t arrays for data sizes below
00157  *          or equal to 8 bits else it is organized as uint16_t arrays.
00158  * @note    This function has to be invoked from a lock zone.
00159  *
00160  * @param[in] uartp     pointer to the @p UARTDriver object
00161  * @param[in] n         number of data frames to send
00162  * @param[in] txbuf     the pointer to the transmit buffer
00163  *
00164  * @iclass
00165  */
00166 void uartStartSendI(UARTDriver *uartp, size_t n, const void *txbuf) {
00167 
00168   chDbgCheckClassI();
00169   chDbgCheck((uartp != NULL) && (n > 0) && (txbuf != NULL),
00170              "uartStartSendI");
00171   chDbgAssert((uartp->state == UART_READY) &&
00172               (uartp->txstate != UART_TX_ACTIVE),
00173               "uartStartSendI(), #1", "not active");
00174 
00175   uart_lld_start_send(uartp, n, txbuf);
00176   uartp->txstate = UART_TX_ACTIVE;
00177 }
00178 
00179 /**
00180  * @brief   Stops any ongoing transmission.
00181  * @note    Stopping a transmission also suppresses the transmission callbacks.
00182  *
00183  * @param[in] uartp     pointer to the @p UARTDriver object
00184  *
00185  * @return              The number of data frames not transmitted by the
00186  *                      stopped transmit operation.
00187  * @retval 0            There was no transmit operation in progress.
00188  *
00189  * @api
00190  */
00191 size_t uartStopSend(UARTDriver *uartp) {
00192   size_t n;
00193 
00194   chDbgCheck(uartp != NULL, "uartStopSend");
00195 
00196   chSysLock();
00197   chDbgAssert(uartp->state == UART_READY, "uartStopSend(), #1", "not active");
00198 
00199   if (uartp->txstate == UART_TX_ACTIVE) {
00200     n = uart_lld_stop_send(uartp);
00201     uartp->txstate = UART_TX_IDLE;
00202   }
00203   else
00204     n = 0;
00205   chSysUnlock();
00206   return n;
00207 }
00208 
00209 /**
00210  * @brief   Stops any ongoing transmission.
00211  * @note    Stopping a transmission also suppresses the transmission callbacks.
00212  * @note    This function has to be invoked from a lock zone.
00213  *
00214  * @param[in] uartp     pointer to the @p UARTDriver object
00215  *
00216  * @return              The number of data frames not transmitted by the
00217  *                      stopped transmit operation.
00218  * @retval 0            There was no transmit operation in progress.
00219  *
00220  * @iclass
00221  */
00222 size_t uartStopSendI(UARTDriver *uartp) {
00223 
00224   chDbgCheckClassI();
00225   chDbgCheck(uartp != NULL, "uartStopSendI");
00226   chDbgAssert(uartp->state == UART_READY, "uartStopSendI(), #1", "not active");
00227 
00228   if (uartp->txstate == UART_TX_ACTIVE) {
00229     size_t n = uart_lld_stop_send(uartp);
00230     uartp->txstate = UART_TX_IDLE;
00231     return n;
00232   }
00233   return 0;
00234 }
00235 
00236 /**
00237  * @brief   Starts a receive operation on the UART peripheral.
00238  * @note    The buffers are organized as uint8_t arrays for data sizes below
00239  *          or equal to 8 bits else it is organized as uint16_t arrays.
00240  *
00241  * @param[in] uartp     pointer to the @p UARTDriver object
00242  * @param[in] n         number of data frames to send
00243  * @param[in] rxbuf     the pointer to the receive buffer
00244  *
00245  * @api
00246  */
00247 void uartStartReceive(UARTDriver *uartp, size_t n, void *rxbuf) {
00248 
00249   chDbgCheck((uartp != NULL) && (n > 0) && (rxbuf != NULL),
00250              "uartStartReceive");
00251 
00252   chSysLock();
00253   chDbgAssert((uartp->state == UART_READY) && (uartp->rxstate == UART_RX_IDLE),
00254               "uartStartReceive(), #1", "not active");
00255 
00256   uart_lld_start_receive(uartp, n, rxbuf);
00257   uartp->rxstate = UART_RX_ACTIVE;
00258   chSysUnlock();
00259 }
00260 
00261 /**
00262  * @brief   Starts a receive operation on the UART peripheral.
00263  * @note    The buffers are organized as uint8_t arrays for data sizes below
00264  *          or equal to 8 bits else it is organized as uint16_t arrays.
00265  * @note    This function has to be invoked from a lock zone.
00266  *
00267  * @param[in] uartp     pointer to the @p UARTDriver object
00268  * @param[in] n         number of data frames to send
00269  * @param[out] rxbuf    the pointer to the receive buffer
00270  *
00271  * @iclass
00272  */
00273 void uartStartReceiveI(UARTDriver *uartp, size_t n, void *rxbuf) {
00274 
00275   chDbgCheckClassI();
00276   chDbgCheck((uartp != NULL) && (n > 0) && (rxbuf != NULL),
00277              "uartStartReceiveI");
00278   chDbgAssert((uartp->state == UART_READY) && (uartp->rxstate == UART_RX_IDLE),
00279               "uartStartReceiveI(), #1", "not active");
00280 
00281   uart_lld_start_receive(uartp, n, rxbuf);
00282   uartp->rxstate = UART_RX_ACTIVE;
00283 }
00284 
00285 /**
00286  * @brief   Stops any ongoing receive operation.
00287  * @note    Stopping a receive operation also suppresses the receive callbacks.
00288  *
00289  * @param[in] uartp     pointer to the @p UARTDriver object
00290  *
00291  * @return              The number of data frames not received by the
00292  *                      stopped receive operation.
00293  * @retval 0            There was no receive operation in progress.
00294  *
00295  * @api
00296  */
00297 size_t uartStopReceive(UARTDriver *uartp) {
00298   size_t n;
00299 
00300   chDbgCheck(uartp != NULL, "uartStopReceive");
00301 
00302   chSysLock();
00303   chDbgAssert(uartp->state == UART_READY,
00304               "uartStopReceive(), #1", "not active");
00305 
00306   if (uartp->rxstate == UART_RX_ACTIVE) {
00307     n = uart_lld_stop_receive(uartp);
00308     uartp->rxstate = UART_RX_IDLE;
00309   }
00310   else
00311     n = 0;
00312   chSysUnlock();
00313   return n;
00314 }
00315 
00316 /**
00317  * @brief   Stops any ongoing receive operation.
00318  * @note    Stopping a receive operation also suppresses the receive callbacks.
00319  * @note    This function has to be invoked from a lock zone.
00320  *
00321  * @param[in] uartp      pointer to the @p UARTDriver object
00322  *
00323  * @return              The number of data frames not received by the
00324  *                      stopped receive operation.
00325  * @retval 0            There was no receive operation in progress.
00326  *
00327  * @iclass
00328  */
00329 size_t uartStopReceiveI(UARTDriver *uartp) {
00330 
00331   chDbgCheckClassI();
00332   chDbgCheck(uartp != NULL, "uartStopReceiveI");
00333   chDbgAssert(uartp->state == UART_READY,
00334               "uartStopReceiveI(), #1", "not active");
00335 
00336   if (uartp->rxstate == UART_RX_ACTIVE) {
00337     size_t n = uart_lld_stop_receive(uartp);
00338     uartp->rxstate = UART_RX_IDLE;
00339     return n;
00340   }
00341   return 0;
00342 }
00343 
00344 #endif /* HAL_USE_UART */
00345 
00346 /** @} */