SAMV71 Xplained Ultra Software Package 1.5

usart.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /**
00031  * \file
00032  *
00033  * Implementation of USART (Universal Synchronous Asynchronous Receiver
00034  * Transmitter) controller.
00035  *
00036  */
00037 /*------------------------------------------------------------------------------
00038  *         Headers
00039  *-----------------------------------------------------------------------------*/
00040 #include "chip.h"
00041 
00042 #include <assert.h>
00043 #include <string.h>
00044 
00045 /*----------------------------------------------------------------------------
00046  *        Local definitions
00047  *----------------------------------------------------------------------------*/
00048 
00049 
00050 /*------------------------------------------------------------------------------
00051  *         Exported functions
00052  *-----------------------------------------------------------------------------*/
00053 
00054 /**
00055  * \brief Configures an USART baudrate.
00056  *
00057  *
00058  *  \param pUsart  Pointer to the USART peripheral to configure.
00059  *  \param baudrate  Baudrate at which the USART should operate (in Hz).
00060  *  \param masterClock  Frequency of the system master clock (in Hz).
00061  */
00062 void USART_SetBaudrate(Usart *pUsart,
00063                        uint8_t OverSamp,
00064                        uint32_t baudrate,
00065                        uint32_t masterClock)
00066 {
00067     unsigned int CD, FP, BaudError, ActualBaudRate;
00068     /* Configure baudrate*/
00069     BaudError = 10;
00070     OverSamp = 0;
00071 
00072     /*Asynchronous*/
00073     if ((pUsart->US_MR & US_MR_SYNC) == 0) {
00074         /* 7816 mode */
00075         if (((pUsart->US_MR & US_MR_USART_MODE_IS07816_T_0)
00076               == US_MR_USART_MODE_IS07816_T_0)
00077              || ((pUsart->US_MR & US_MR_USART_MODE_IS07816_T_1)
00078                  == US_MR_USART_MODE_IS07816_T_1)) {
00079             /* Define the baud rate divisor register */
00080             /* CD  = MCK / SCK */
00081             /* SCK = FIDI x BAUD = 372 x 9600 */
00082             /* BOARD_MCK */
00083             /* CD = MCK/(FIDI x BAUD) = 150000000 / (372x9600) = 42 */
00084             CD = masterClock / (pUsart->US_FIDI * baudrate);
00085             FP = 0;
00086         } else {
00087             while (BaudError > 5) {
00088                 CD = (masterClock / (baudrate * 8 * (2 - OverSamp)));
00089                 FP = ((masterClock / (baudrate * (2 - OverSamp))) - CD * 8);
00090                 ActualBaudRate = (masterClock / (CD * 8 + FP)) / (2 - OverSamp);
00091                 BaudError = (100 - ((baudrate * 100 / ActualBaudRate)));
00092 
00093                 if (BaudError > 5) {
00094                     OverSamp++;
00095 
00096                     if (OverSamp >= 2) {
00097                         TRACE_ERROR("Canont set this baudrate \n\r");
00098                         break;
00099                     }
00100                 }
00101             }
00102         }
00103     }
00104 
00105     /*Synchronous SPI  */
00106     if ((pUsart->US_MR & US_MR_USART_MODE_SPI_MASTER)
00107         == US_MR_USART_MODE_SPI_MASTER
00108         || ((pUsart->US_MR & US_MR_SYNC) == US_MR_SYNC)) {
00109         if ((pUsart->US_MR & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK) {
00110             CD = masterClock / baudrate;
00111             FP = ((masterClock / baudrate) - CD);
00112         }
00113     }
00114 
00115     pUsart->US_BRGR = (US_BRGR_CD(CD) | US_BRGR_FP(FP));
00116 
00117     /* Configure OverSamp*/
00118     pUsart->US_MR |= (OverSamp << 19);
00119 }
00120 
00121 /**
00122  * \brief Configures an USART peripheral with the specified parameters.
00123  *
00124  *
00125  *  \param pUsart  Pointer to the USART peripheral to configure.
00126  *  \param mode  Desired value for the USART mode register (see the datasheet).
00127  *  \param baudrate  Baudrate at which the USART should operate (in Hz).
00128  *  \param masterClock  Frequency of the system master clock (in Hz).
00129  */
00130 void USART_Configure(Usart *pUsart,
00131                      uint32_t mode,
00132                      uint32_t baudrate,
00133                      uint32_t masterClock)
00134 {
00135 
00136     /* Reset and disable receiver & transmitter*/
00137     pUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX
00138                     | US_CR_RXDIS | US_CR_TXDIS | US_CR_RSTSTA;
00139     pUsart->US_IDR = 0xFFFFFFFF;
00140 
00141     pUsart->US_MR = mode;
00142     /* Configure baudrate*/
00143     USART_SetBaudrate(pUsart, 0, baudrate, masterClock);
00144 
00145     /* Enable receiver and transmitter */
00146     pUsart->US_CR = US_CR_RXEN | US_CR_TXEN;
00147 
00148     /* Disable buffering for printf(). */
00149 #if (defined (__GNUC__) && !defined (__SAMBA__))
00150     setvbuf(stdout, (char *)NULL, _IONBF, 0);
00151 #endif
00152 
00153 }
00154 /**
00155  * \brief Enables or disables the transmitter of an USART peripheral.
00156  *
00157  *
00158  * \param pUsart  Pointer to an USART peripheral
00159  * \param enabled  If true, the transmitter is enabled; otherwise it is
00160  * disabled.
00161  */
00162 void USART_SetTransmitterEnabled(Usart *pUsart, uint8_t enabled)
00163 {
00164     if (enabled)
00165         pUsart->US_CR = US_CR_TXEN;
00166     else
00167         pUsart->US_CR = US_CR_TXDIS;
00168 }
00169 
00170 /**
00171  * \brief Disables the Receiver of an USART peripheral.
00172  *
00173  * \param pUsart  Pointer to an USART peripheral
00174  */
00175 void USART_DisableRx(Usart *pUsart)
00176 {
00177 
00178     pUsart->US_CR = US_CR_RXDIS;
00179 }
00180 
00181 /**
00182  * \brief Disables the transmitter of an USART peripheral.
00183  *
00184  * \param pUsart  Pointer to an USART peripheral
00185  */
00186 void USART_DisableTx(Usart *pUsart)
00187 {
00188     pUsart->US_CR =  US_CR_TXDIS;
00189 }
00190 
00191 /**
00192  * \brief Enables the Receiver of an USART peripheral.
00193  *
00194  * \param pUsart  Pointer to an USART peripheral
00195  */
00196 void USART_EnableRx(Usart *pUsart)
00197 {
00198 
00199     pUsart->US_CR = US_CR_RXEN;
00200 }
00201 
00202 /**
00203  * \brief Enables the transmitter of an USART peripheral
00204  *
00205  * \param pUsart  Pointer to an USART peripheral
00206  */
00207 void USART_EnableTx(Usart *pUsart)
00208 {
00209     pUsart->US_CR =  US_CR_TXEN;
00210 }
00211 /**
00212  * \brief Resets or disables the Receiver of an USART peripheral.
00213  *
00214  *
00215  * \param pUsart  Pointer to an USART peripheral
00216  */
00217 void USART_ResetRx(Usart *pUsart)
00218 {
00219 
00220     pUsart->US_CR = US_CR_RSTRX | US_CR_RXDIS;
00221 }
00222 
00223 /**
00224  * \brief resets and disables the transmitter of an USART peripheral.
00225  *
00226  *
00227  * \param pUsart  Pointer to an USART peripheral
00228  */
00229 void USART_ResetTx(Usart *pUsart)
00230 {
00231     pUsart->US_CR =  US_CR_RSTTX | US_CR_TXDIS;
00232 }
00233 /**
00234  * \brief Enables or disables the receiver of an USART peripheral
00235  *
00236  *
00237  * \param pUsart  Pointer to an USART peripheral
00238  * \param enabled  If true, the receiver is enabled; otherwise it is disabled.
00239  */
00240 void USART_SetReceiverEnabled(Usart *pUsart, uint8_t enabled)
00241 {
00242     if (enabled)
00243         pUsart->US_CR = US_CR_RXEN;
00244     else
00245         pUsart->US_CR = US_CR_RXDIS;
00246 }
00247 
00248 /**
00249  * \brief Enables or disables the Request To Send (RTS) of an USART peripheral
00250  *
00251  *
00252  * \param pUsart  Pointer to an USART peripheral
00253  * \param enabled  If true, the RTS is enabled (0); otherwise it is disabled.
00254  */
00255 void USART_SetRTSEnabled(Usart *pUsart, uint8_t enabled)
00256 {
00257     if (enabled)
00258         pUsart->US_CR = US_CR_RTSEN;
00259     else
00260         pUsart->US_CR = US_CR_RTSDIS;
00261 }
00262 
00263 /**
00264  * \brief Sends one packet of data through the specified USART peripheral. This
00265  * function operates synchronously, so it only returns when the data has been
00266  * actually sent.
00267  *
00268  *
00269  * \param pUsart  Pointer to an USART peripheral.
00270  * \param data  Data to send including 9nth bit and sync field if necessary (in
00271  *        the same format as the US_THR register in the datasheet).
00272  * \param timeOut  Time out value (0 = no timeout).
00273  */
00274 void USART_Write(Usart *pUsart, uint16_t data, volatile uint32_t timeOut)
00275 {
00276     if (timeOut == 0) {
00277         while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);
00278     } else {
00279         while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0) {
00280             if (timeOut == 0) {
00281                 TRACE_ERROR("USART_Write: Timed out.\n\r");
00282                 return;
00283             }
00284 
00285             timeOut--;
00286         }
00287     }
00288 
00289     pUsart->US_THR = data;
00290 }
00291 
00292 /**
00293  * \brief  Reads and return a packet of data on the specified USART peripheral.
00294  * This function operates asynchronously, so it waits until some data has been
00295  * received.
00296  *
00297  * \param pUsart  Pointer to an USART peripheral.
00298  * \param timeOut  Time out value (0 -> no timeout).
00299  */
00300 uint16_t USART_Read(Usart *pUsart, volatile uint32_t timeOut)
00301 {
00302     if (timeOut == 0) {
00303         while ((pUsart->US_CSR & US_CSR_RXRDY) == 0);
00304     } else {
00305         while ((pUsart->US_CSR & US_CSR_RXRDY) == 0) {
00306             if (timeOut == 0) {
00307                 TRACE_ERROR("USART_Read: Timed out.\n\r");
00308                 return 0;
00309             }
00310 
00311             timeOut--;
00312         }
00313     }
00314 
00315     return pUsart->US_RHR;
00316 }
00317 
00318 /**
00319  * \brief  Returns 1 if some data has been received and can be read from an
00320  * USART; otherwise returns 0.
00321  *
00322  * \param pUsart  Pointer to an USART instance.
00323  */
00324 uint8_t USART_IsDataAvailable(Usart *pUsart)
00325 {
00326     if ((pUsart->US_CSR & US_CSR_RXRDY) != 0)
00327         return 1;
00328     else
00329         return 0;
00330 }
00331 
00332 /**
00333  * \brief  Sends one packet of data through the specified USART peripheral. This
00334  * function operates synchronously, so it only returns when the data has been
00335  * actually sent.
00336  *
00337  * \param pUsart  Pointer to an USART peripheral.
00338  * \param c  Character to send
00339  */
00340 void USART_PutChar(Usart *pUsart, uint8_t c)
00341 {
00342     /* Wait for the transmitter to be ready*/
00343     while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);
00344 
00345     /* Send character*/
00346     pUsart->US_THR = c;
00347 
00348     /* Wait for the transfer to complete*/
00349     while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);
00350 }
00351 
00352 /**
00353  * \brief   Return 1 if a character can be read in USART
00354  * \param pUsart  Pointer to an USART peripheral.
00355  */
00356 uint32_t USART_IsRxReady(Usart *pUsart)
00357 {
00358     return (pUsart->US_CSR & US_CSR_RXRDY);
00359 }
00360 
00361 /**
00362  * \brief   Get present status
00363  * \param pUsart  Pointer to an USART peripheral.
00364  */
00365 uint32_t USART_GetStatus(Usart *pUsart)
00366 {
00367     return pUsart->US_CSR;
00368 }
00369 
00370 /**
00371  * \brief   Enable interrupt
00372  * \param pUsart  Pointer to an USART peripheral.
00373  * \param mode  Interrupt mode.
00374  */
00375 void USART_EnableIt(Usart *pUsart, uint32_t mode)
00376 {
00377     pUsart->US_IER = mode;
00378 }
00379 
00380 /**
00381  * \brief   Disable interrupt
00382  * \param pUsart  Pointer to an USART peripheral.
00383  * \param mode  Interrupt mode.
00384  */
00385 void USART_DisableIt(Usart *pUsart, uint32_t mode)
00386 {
00387     pUsart->US_IDR = mode;
00388 }
00389 
00390 /**
00391  * \brief   Return interrupt mask
00392  * \param pUsart  Pointer to an USART peripheral.
00393  */
00394 uint32_t USART_GetItMask(Usart *pUsart)
00395 {
00396     return pUsart->US_IMR;
00397 }
00398 
00399 /**
00400  * \brief  Reads and returns a character from the USART.
00401  *
00402  * \note This function is synchronous (i.e. uses polling).
00403  * \param pUsart  Pointer to an USART peripheral.
00404  * \return Character received.
00405  */
00406 uint8_t USART_GetChar(Usart *pUsart)
00407 {
00408     while ((pUsart->US_CSR & US_CSR_RXRDY) == 0);
00409 
00410     return pUsart->US_RHR;
00411 }
00412 
00413 /**
00414  * \brief  Enable Rx Timeout for USART.
00415  *
00416  * \param pUsart  Pointer to an USART peripheral.
00417  * \param Timeout  Timeout value
00418  * \return None
00419  */
00420 void USART_EnableRecvTimeOut(Usart *pUsart, uint32_t Timeout)
00421 {
00422     if (Timeout <= MAX_RX_TIMEOUT)
00423         pUsart->US_RTOR = Timeout;
00424     else if (Timeout == 0) {
00425         TRACE_DEBUG("Timeout is disabled\n\r");
00426     } else {
00427         TRACE_INFO_WP("\n\r");
00428         TRACE_FATAL("Timeout value is out of range\n\r");
00429     }
00430 }
00431 
00432 /**
00433  * \brief  Enable Tx Timeout for USART.
00434  *
00435  * \param pUsart  Pointer to an USART peripheral.
00436  * \param TimeGaurd  TimeGaurd value
00437  * \return None
00438  */
00439 void USART_EnableTxTimeGaurd(Usart *pUsart, uint32_t TimeGaurd)
00440 {
00441     if (((pUsart->US_MR & US_MR_USART_MODE_LON) && TimeGaurd <= 16777215) ||
00442          ((pUsart->US_MR & US_MR_USART_MODE_LON) && TimeGaurd <= 255))
00443         pUsart->US_TTGR = TimeGaurd;
00444     else
00445         TRACE_ERROR(" TimeGaurd Value is too big for mode");
00446 }
00447 /**
00448  * \brief  Acknowledge Rx timeout and sets to Idle or periodic repetitive state.
00449  *
00450  * \param pUsart  Pointer to an USART peripheral.
00451  * \param Periodic  If timeout is periodic or should wait for new char
00452  * \return None
00453  */
00454 void USART_AcknowledgeRxTimeOut(Usart *pUsart, uint8_t Periodic)
00455 {
00456     if (Periodic) {
00457         pUsart->US_CR = US_CR_RETTO;     // Restart timeout timer
00458     } else {
00459         // Puts USARt in Idle mode and waits for a char after timeout
00460         pUsart->US_CR = US_CR_STTTO;
00461     }
00462 }
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines