1 /* ----------------------------------------------------------------------------
\r
2 * SAM Software Package License
\r
3 * ----------------------------------------------------------------------------
\r
4 * Copyright (c) 2013, Atmel Corporation
\r
6 * All rights reserved.
\r
8 * Redistribution and use in source and binary forms, with or without
\r
9 * modification, are permitted provided that the following conditions are met:
\r
11 * - Redistributions of source code must retain the above copyright notice,
\r
12 * this list of conditions and the disclaimer below.
\r
14 * Atmel's name may not be used to endorse or promote products derived from
\r
15 * this software without specific prior written permission.
\r
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
\r
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
\r
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
\r
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
\r
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
\r
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
\r
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
\r
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
\r
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
\r
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\r
27 * ----------------------------------------------------------------------------
\r
33 * Implementation of USART (Universal Synchronous Asynchronous Receiver
\r
34 * Transmitter) controller.
\r
37 /*------------------------------------------------------------------------------
\r
39 *-----------------------------------------------------------------------------*/
\r
45 /*----------------------------------------------------------------------------
\r
47 *----------------------------------------------------------------------------*/
\r
50 /*------------------------------------------------------------------------------
\r
51 * Exported functions
\r
52 *-----------------------------------------------------------------------------*/
\r
55 * \brief Configures an USART baudrate.
\r
58 * \param pUsart Pointer to the USART peripheral to configure.
\r
59 * \param baudrate Baudrate at which the USART should operate (in Hz).
\r
60 * \param masterClock Frequency of the system master clock (in Hz).
\r
62 void USART_SetBaudrate(Usart *pUsart,
\r
65 uint32_t masterClock)
\r
67 unsigned int CD, FP, BaudError, ActualBaudRate;
\r
68 /* Configure baudrate*/
\r
73 if ((pUsart->US_MR & US_MR_SYNC) == 0)
\r
76 if( ((pUsart->US_MR & US_MR_USART_MODE_IS07816_T_0)
\r
77 == US_MR_USART_MODE_IS07816_T_0 )
\r
78 || ((pUsart->US_MR & US_MR_USART_MODE_IS07816_T_1)
\r
79 == US_MR_USART_MODE_IS07816_T_1 ))
\r
81 /* Define the baud rate divisor register */
\r
82 /* CD = MCK / SCK */
\r
83 /* SCK = FIDI x BAUD = 372 x 9600 */
\r
85 /* CD = MCK/(FIDI x BAUD) = 150000000 / (372x9600) = 42 */
\r
86 CD = masterClock / (pUsart->US_FIDI * baudrate);
\r
90 while (BaudError > 5) {
\r
91 CD = (masterClock / (baudrate * 8 *( 2 - OverSamp)));
\r
92 FP = ((masterClock / (baudrate * ( 2 - OverSamp)) ) - CD * 8);
\r
93 ActualBaudRate = (masterClock/(CD * 8 + FP)) / ( 2 - OverSamp);
\r
94 BaudError = (100 - ((baudrate * 100 / ActualBaudRate)));
\r
101 TRACE_ERROR("Canont set this baudrate \n\r");
\r
108 /*Synchronous SPI */
\r
109 if((pUsart->US_MR & US_MR_USART_MODE_SPI_MASTER)
\r
110 == US_MR_USART_MODE_SPI_MASTER
\r
111 || ((pUsart->US_MR & US_MR_SYNC) == US_MR_SYNC) )
\r
113 if( (pUsart->US_MR & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK)
\r
115 CD = masterClock / baudrate;
\r
116 FP = ((masterClock / baudrate) - CD);
\r
120 pUsart->US_BRGR = ( US_BRGR_CD(CD) | US_BRGR_FP(FP));
\r
122 /* Configure OverSamp*/
\r
123 pUsart->US_MR |= (OverSamp << 19);
\r
127 * \brief Configures an USART peripheral with the specified parameters.
\r
130 * \param pUsart Pointer to the USART peripheral to configure.
\r
131 * \param mode Desired value for the USART mode register (see the datasheet).
\r
132 * \param baudrate Baudrate at which the USART should operate (in Hz).
\r
133 * \param masterClock Frequency of the system master clock (in Hz).
\r
135 void USART_Configure(Usart *pUsart,
\r
138 uint32_t masterClock)
\r
141 /* Reset and disable receiver & transmitter*/
\r
142 pUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX
\r
143 | US_CR_RXDIS | US_CR_TXDIS | US_CR_RSTSTA;
\r
144 pUsart->US_IDR = 0xFFFFFFFF;
\r
146 pUsart->US_MR = mode;
\r
147 /* Configure baudrate*/
\r
148 USART_SetBaudrate(pUsart, 0, baudrate, masterClock);
\r
150 /* Enable receiver and transmitter */
\r
151 pUsart->US_CR = US_CR_RXEN | US_CR_TXEN;
\r
153 /* Disable buffering for printf(). */
\r
154 #if ( defined (__GNUC__) && !defined (__SAMBA__) )
\r
155 setvbuf(stdout, (char *)NULL, _IONBF, 0);
\r
160 * \brief Enables or disables the transmitter of an USART peripheral.
\r
163 * \param pUsart Pointer to an USART peripheral
\r
164 * \param enabled If true, the transmitter is enabled; otherwise it is
\r
167 void USART_SetTransmitterEnabled(Usart *pUsart, uint8_t enabled)
\r
170 pUsart->US_CR = US_CR_TXEN;
\r
172 pUsart->US_CR = US_CR_TXDIS;
\r
177 * \brief Disables the Receiver of an USART peripheral.
\r
179 * \param pUsart Pointer to an USART peripheral
\r
181 void USART_DisableRx(Usart *pUsart)
\r
184 pUsart->US_CR = US_CR_RXDIS;
\r
188 * \brief Disables the transmitter of an USART peripheral.
\r
190 * \param pUsart Pointer to an USART peripheral
\r
192 void USART_DisableTx(Usart *pUsart)
\r
194 pUsart->US_CR = US_CR_TXDIS;
\r
198 * \brief Enables the Receiver of an USART peripheral.
\r
200 * \param pUsart Pointer to an USART peripheral
\r
202 void USART_EnableRx(Usart *pUsart)
\r
205 pUsart->US_CR = US_CR_RXEN;
\r
209 * \brief Enables the transmitter of an USART peripheral
\r
211 * \param pUsart Pointer to an USART peripheral
\r
213 void USART_EnableTx(Usart *pUsart)
\r
215 pUsart->US_CR = US_CR_TXEN;
\r
218 * \brief Resets or disables the Receiver of an USART peripheral.
\r
221 * \param pUsart Pointer to an USART peripheral
\r
223 void USART_ResetRx(Usart *pUsart)
\r
226 pUsart->US_CR = US_CR_RSTRX | US_CR_RXDIS;
\r
230 * \brief resets and disables the transmitter of an USART peripheral.
\r
233 * \param pUsart Pointer to an USART peripheral
\r
235 void USART_ResetTx(Usart *pUsart)
\r
237 pUsart->US_CR = US_CR_RSTTX | US_CR_TXDIS;
\r
240 * \brief Enables or disables the receiver of an USART peripheral
\r
243 * \param pUsart Pointer to an USART peripheral
\r
244 * \param enabled If true, the receiver is enabled; otherwise it is disabled.
\r
246 void USART_SetReceiverEnabled(Usart *pUsart, uint8_t enabled)
\r
249 pUsart->US_CR = US_CR_RXEN;
\r
251 pUsart->US_CR = US_CR_RXDIS;
\r
256 * \brief Enables or disables the Request To Send (RTS) of an USART peripheral
\r
259 * \param pUsart Pointer to an USART peripheral
\r
260 * \param enabled If true, the RTS is enabled (0); otherwise it is disabled.
\r
262 void USART_SetRTSEnabled( Usart *pUsart, uint8_t enabled)
\r
265 pUsart->US_CR = US_CR_RTSEN;
\r
267 pUsart->US_CR = US_CR_RTSDIS;
\r
272 * \brief Sends one packet of data through the specified USART peripheral. This
\r
273 * function operates synchronously, so it only returns when the data has been
\r
277 * \param pUsart Pointer to an USART peripheral.
\r
278 * \param data Data to send including 9nth bit and sync field if necessary (in
\r
279 * the same format as the US_THR register in the datasheet).
\r
280 * \param timeOut Time out value (0 = no timeout).
\r
282 void USART_Write( Usart *pUsart, uint16_t data, volatile uint32_t timeOut)
\r
284 if (timeOut == 0) {
\r
285 while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);
\r
287 while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0) {
\r
288 if (timeOut == 0) {
\r
289 TRACE_ERROR("USART_Write: Timed out.\n\r");
\r
295 pUsart->US_THR = data;
\r
299 * \brief Reads and return a packet of data on the specified USART peripheral.
\r
300 * This function operates asynchronously, so it waits until some data has been
\r
303 * \param pUsart Pointer to an USART peripheral.
\r
304 * \param timeOut Time out value (0 -> no timeout).
\r
306 uint16_t USART_Read( Usart *pUsart, volatile uint32_t timeOut)
\r
308 if (timeOut == 0) {
\r
309 while ((pUsart->US_CSR & US_CSR_RXRDY) == 0);
\r
311 while ((pUsart->US_CSR & US_CSR_RXRDY) == 0) {
\r
312 if (timeOut == 0) {
\r
313 TRACE_ERROR( "USART_Read: Timed out.\n\r" ) ;
\r
319 return pUsart->US_RHR;
\r
323 * \brief Returns 1 if some data has been received and can be read from an
\r
324 * USART; otherwise returns 0.
\r
326 * \param pUsart Pointer to an USART instance.
\r
328 uint8_t USART_IsDataAvailable(Usart *pUsart)
\r
330 if ((pUsart->US_CSR & US_CSR_RXRDY) != 0) {
\r
338 * \brief Sends one packet of data through the specified USART peripheral. This
\r
339 * function operates synchronously, so it only returns when the data has been
\r
342 * \param pUsart Pointer to an USART peripheral.
\r
343 * \param c Character to send
\r
345 void USART_PutChar( Usart *pUsart, uint8_t c)
\r
347 /* Wait for the transmitter to be ready*/
\r
348 while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);
\r
350 /* Send character*/
\r
351 pUsart->US_THR = c;
\r
353 /* Wait for the transfer to complete*/
\r
354 while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);
\r
358 * \brief Return 1 if a character can be read in USART
\r
359 * \param pUsart Pointer to an USART peripheral.
\r
361 uint32_t USART_IsRxReady(Usart *pUsart)
\r
363 return (pUsart->US_CSR & US_CSR_RXRDY);
\r
367 * \brief Get present status
\r
368 * \param pUsart Pointer to an USART peripheral.
\r
370 uint32_t USART_GetStatus(Usart *pUsart)
\r
372 return pUsart->US_CSR;
\r
376 * \brief Enable interrupt
\r
377 * \param pUsart Pointer to an USART peripheral.
\r
378 * \param mode Interrupt mode.
\r
380 void USART_EnableIt(Usart *pUsart,uint32_t mode)
\r
382 pUsart->US_IER = mode;
\r
386 * \brief Disable interrupt
\r
387 * \param pUsart Pointer to an USART peripheral.
\r
388 * \param mode Interrupt mode.
\r
390 void USART_DisableIt(Usart *pUsart,uint32_t mode)
\r
392 pUsart->US_IDR = mode;
\r
396 * \brief Return interrupt mask
\r
397 * \param pUsart Pointer to an USART peripheral.
\r
399 uint32_t USART_GetItMask(Usart *pUsart)
\r
401 return pUsart->US_IMR;
\r
405 * \brief Reads and returns a character from the USART.
\r
407 * \note This function is synchronous (i.e. uses polling).
\r
408 * \param pUsart Pointer to an USART peripheral.
\r
409 * \return Character received.
\r
411 uint8_t USART_GetChar(Usart *pUsart)
\r
413 while ((pUsart->US_CSR & US_CSR_RXRDY) == 0);
\r
414 return pUsart->US_RHR;
\r
418 * \brief Enable Rx Timeout for USART.
\r
420 * \param pUsart Pointer to an USART peripheral.
\r
421 * \param Timeout Timeout value
\r
424 void USART_EnableRecvTimeOut(Usart *pUsart, uint32_t Timeout)
\r
426 if( Timeout <= MAX_RX_TIMEOUT ) {
\r
427 pUsart->US_RTOR = Timeout;
\r
428 } else if( Timeout == 0) {
\r
429 TRACE_DEBUG("Timeout is disabled\n\r");
\r
431 TRACE_INFO_WP("\n\r");
\r
432 TRACE_FATAL("Timeout value is out of range\n\r");
\r
437 * \brief Enable Tx Timeout for USART.
\r
439 * \param pUsart Pointer to an USART peripheral.
\r
440 * \param TimeGaurd TimeGaurd value
\r
443 void USART_EnableTxTimeGaurd(Usart *pUsart, uint32_t TimeGaurd)
\r
445 if( ( (pUsart->US_MR & US_MR_USART_MODE_LON ) && TimeGaurd <= 16777215) ||
\r
446 ((pUsart->US_MR & US_MR_USART_MODE_LON ) && TimeGaurd <= 255) ) {
\r
447 pUsart->US_TTGR = TimeGaurd;
\r
449 TRACE_ERROR(" TimeGaurd Value is too big for mode");
\r
453 * \brief Acknowledge Rx timeout and sets to Idle or periodic repetitive state.
\r
455 * \param pUsart Pointer to an USART peripheral.
\r
456 * \param Periodic If timeout is periodic or should wait for new char
\r
459 void USART_AcknowledgeRxTimeOut(Usart *pUsart, uint8_t Periodic)
\r
462 pUsart->US_CR = US_CR_RETTO; // Restart timeout timer
\r
464 // Puts USARt in Idle mode and waits for a char after timeout
\r
465 pUsart->US_CR = US_CR_STTTO;
\r