SAMV71 Xplained Ultra Software Package 1.3

usart.c

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