blob: f1acb2fe0d1251cc9840d2f938953d6b40ed1322 [file] [log] [blame]
Christina Quast8be71e42014-12-02 13:06:01 +01001/* ----------------------------------------------------------------------------
2 * ATMEL Microcontroller Software Support
3 * ----------------------------------------------------------------------------
4 * Copyright (c) 2009, Atmel Corporation
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the disclaimer below.
13 *
14 * Atmel's name may not be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * ----------------------------------------------------------------------------
28 */
29
30/** \addtogroup usart_module Working with USART
31 * The USART driver provides the interface to configure and use the USART peripheral.\n
32 *
33 * The USART supports several kinds of comminication modes such as full-duplex asynchronous/
34 * synchronous serial commnunication,RS485 with driver control signal,ISO7816,SPI and Test modes.
35 *
36 * To start a USART transfer with \ref AT91SAM3S_PDC "PDC" support, the user could follow these steps:
37 * <ul>
38 * <li> Configure USART with expected mode and baudrate(see \ref USART_Configure), which could be done by:
39 * -# Resetting and disabling transmitter and receiver by setting US_CR(Control Register). </li>
40 * -# Conifguring the USART in a specific mode by setting USART_MODE bits in US_MR(Mode Register) </li>
41 * -# Setting baudrate which is different from mode to mode.
42 </li>
43 * <li> Enable transmitter or receiver respectively by set US_CR_TXEN or US_CR_RXEN in US_CR.</li>
44 * <li> Read from or write to the peripheral with \ref USART_ReadBuffer or \ref USART_WriteBuffer.
45 These operations could be done by polling or interruption. </li>
46 * <li> For polling, check the status bit US_CSR_ENDRX/US_CSR_RXBUFF (READ) or US_CSR_ENDTX/
47 US_CSR_TXBUFE (WRITE). </li>
48 * <li> For interruption,"enable" the status bit through US_IER and
49 realize the hanler with USARTx_IrqHandler according to IRQ vector
50 table which is defined in board_cstartup_<toolchain>.c
51 To enable the interruption of USART,it should be configured with priority and enabled first through
52 NVIC .</li>
53 * </ul>
54 *
55 * For more accurate information, please look at the USART section of the
56 * Datasheet.
57 *
58 * Related files :\n
59 * \ref usart.c\n
60 * \ref usart.h\n
61*/
62
63
64
65/**
66 * \file
67 *
68 * Implementation of USART (Universal Synchronous Asynchronous Receiver Transmitter)
69 * controller.
70 *
71 */
72/*------------------------------------------------------------------------------
73 * Headers
74 *------------------------------------------------------------------------------*/
75#include "chip.h"
76#include "trace.h"
77
78#include <assert.h>
79#include <string.h>
80
81/*----------------------------------------------------------------------------
82 * Local definitions
83 *----------------------------------------------------------------------------*/
84
85
86/*------------------------------------------------------------------------------
87 * Exported functions
88 *------------------------------------------------------------------------------*/
89
90/**
91 * \brief Configures an USART peripheral with the specified parameters.
92 *
93 *
94 * \param usart Pointer to the USART peripheral to configure.
95 * \param mode Desired value for the USART mode register (see the datasheet).
96 * \param baudrate Baudrate at which the USART should operate (in Hz).
97 * \param masterClock Frequency of the system master clock (in Hz).
98 */
99void USART_Configure(Usart *usart,
100 uint32_t mode,
101 uint32_t baudrate,
102 uint32_t masterClock)
103{
104 /* Reset and disable receiver & transmitter*/
105 usart->US_CR = US_CR_RSTRX | US_CR_RSTTX
106 | US_CR_RXDIS | US_CR_TXDIS;
107
108 /* Configure mode*/
109 usart->US_MR = mode;
110
111 /* Configure baudrate*/
112 /* Asynchronous, no oversampling*/
113 if ( ((mode & US_MR_SYNC) == 0) && ((mode & US_MR_OVER) == 0) )
114 {
115 usart->US_BRGR = (masterClock / baudrate) / 16;
116 }
117
118 if( ((mode & US_MR_USART_MODE_SPI_MASTER) == US_MR_USART_MODE_SPI_MASTER)
119 || ((mode & US_MR_SYNC) == US_MR_SYNC))
120 {
121 if( (mode & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK)
122 {
123 usart->US_BRGR = masterClock / baudrate;
124 }
125 else
126 {
127 if ( (mode & US_MR_USCLKS_DIV) == US_MR_USCLKS_DIV)
128 {
129 usart->US_BRGR = masterClock / baudrate / 8;
130 }
131 }
132 }
133 /* TODO other modes*/
134}
135/**
136 * \brief Enables or disables the transmitter of an USART peripheral.
137 *
138 *
139 * \param usart Pointer to an USART peripheral
140 * \param enabled If true, the transmitter is enabled; otherwise it is
141 * disabled.
142 */
143void USART_SetTransmitterEnabled(Usart *usart, uint8_t enabled)
144{
145 if (enabled) {
146
147 usart->US_CR = US_CR_TXEN;
148 }
149 else {
150
151 usart->US_CR = US_CR_TXDIS;
152 }
153}
154
155/**
156 * \brief Enables or disables the receiver of an USART peripheral
157 *
158 *
159 * \param usart Pointer to an USART peripheral
160 * \param enabled If true, the receiver is enabled; otherwise it is disabled.
161 */
162void USART_SetReceiverEnabled(Usart *usart,
163 uint8_t enabled)
164{
165 if (enabled) {
166
167 usart->US_CR = US_CR_RXEN;
168 }
169 else {
170
171 usart->US_CR = US_CR_RXDIS;
172 }
173}
174
175/**
176 * \brief Sends one packet of data through the specified USART peripheral. This
177 * function operates synchronously, so it only returns when the data has been
178 * actually sent.
179 *
180 *
181 * \param usart Pointer to an USART peripheral.
182 * \param data Data to send including 9nth bit and sync field if necessary (in
183 * the same format as the US_THR register in the datasheet).
184 * \param timeOut Time out value (0 = no timeout).
185 */
186void USART_Write(
187 Usart *usart,
188 uint16_t data,
189 volatile uint32_t timeOut)
190{
191 if (timeOut == 0) {
192
193 while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
194 }
195 else {
196
197 while ((usart->US_CSR & US_CSR_TXEMPTY) == 0) {
198
199 if (timeOut == 0) {
200
201 TRACE_ERROR("USART_Write: Timed out.\n\r");
202 return;
203 }
204 timeOut--;
205 }
206 }
207
208 usart->US_THR = data;
209}
210
211/**
212 * \brief Sends the contents of a data buffer through the specified USART peripheral.
213 * This function returns immediately (1 if the buffer has been queued, 0
214 * otherwise); poll the ENDTX and TXBUFE bits of the USART status register
215 * to check for the transfer completion.
216 *
217 * \param usart Pointer to an USART peripheral.
218 * \param buffer Pointer to the data buffer to send.
219 * \param size Size of the data buffer (in bytes).
220 */
221uint8_t USART_WriteBuffer(
222 Usart *usart,
223 void *buffer,
224 uint32_t size)
225{
226 /* Check if the first PDC bank is free*/
227 if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) {
228
229 usart->US_TPR = (uint32_t) buffer;
230 usart->US_TCR = size;
231 usart->US_PTCR = US_PTCR_TXTEN;
232
233 return 1;
234 }
235 /* Check if the second PDC bank is free*/
236 else if (usart->US_TNCR == 0) {
237
238 usart->US_TNPR = (uint32_t) buffer;
239 usart->US_TNCR = size;
240
241 return 1;
242 }
243 else {
244
245 return 0;
246 }
247}
248
249
250/**
251 * \brief Reads and return a packet of data on the specified USART peripheral. This
252 * function operates asynchronously, so it waits until some data has been
253 * received.
254 *
255 * \param usart Pointer to an USART peripheral.
256 * \param timeOut Time out value (0 -> no timeout).
257 */
258uint16_t USART_Read(
259 Usart *usart,
260 volatile uint32_t timeOut)
261{
262 if (timeOut == 0) {
263
264 while ((usart->US_CSR & US_CSR_RXRDY) == 0);
265 }
266 else {
267
268 while ((usart->US_CSR & US_CSR_RXRDY) == 0) {
269
270 if (timeOut == 0) {
271
272 TRACE_ERROR( "USART_Read: Timed out.\n\r" ) ;
273 return 0;
274 }
275 timeOut--;
276 }
277 }
278
279 return usart->US_RHR;
280}
281
282/**
283 * \brief Reads data from an USART peripheral, filling the provided buffer until it
284 * becomes full. This function returns immediately with 1 if the buffer has
285 * been queued for transmission; otherwise 0.
286 *
287 * \param usart Pointer to an USART peripheral.
288 * \param buffer Pointer to the buffer where the received data will be stored.
289 * \param size Size of the data buffer (in bytes).
290 */
291uint8_t USART_ReadBuffer(Usart *usart,
292 void *buffer,
293 uint32_t size)
294{
295 /* Check if the first PDC bank is free*/
296 if ((usart->US_RCR == 0) && (usart->US_RNCR == 0)) {
297
298 usart->US_RPR = (uint32_t) buffer;
299 usart->US_RCR = size;
300 usart->US_PTCR = US_PTCR_RXTEN;
301
302 return 1;
303 }
304 /* Check if the second PDC bank is free*/
305 else if (usart->US_RNCR == 0) {
306
307 usart->US_RNPR = (uint32_t) buffer;
308 usart->US_RNCR = size;
309
310 return 1;
311 }
312 else {
313
314 return 0;
315 }
316}
317
318/**
319 * \brief Returns 1 if some data has been received and can be read from an USART;
320 * otherwise returns 0.
321 *
322 * \param usart Pointer to an Usart instance.
323 */
324uint8_t USART_IsDataAvailable(Usart *usart)
325{
326 if ((usart->US_CSR & US_CSR_RXRDY) != 0) {
327
328 return 1;
329 }
330 else {
331
332 return 0;
333 }
334}
335
336/**
337 * \brief Sets the filter value for the IRDA demodulator.
338 *
339 * \param pUsart Pointer to an Usart instance.
340 * \param filter Filter value.
341 */
342void USART_SetIrdaFilter(Usart *pUsart, uint8_t filter)
343{
344 assert( pUsart != NULL ) ;
345
346 pUsart->US_IF = filter;
347}
348
349/**
350 * \brief Sends one packet of data through the specified USART peripheral. This
351 * function operates synchronously, so it only returns when the data has been
352 * actually sent.
353 *
354 * \param usart Pointer to an USART peripheral.
355 * \param c Character to send
356 */
357void USART_PutChar(
358 Usart *usart,
359 uint8_t c)
360{
361 /* Wait for the transmitter to be ready*/
362 while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
363
364 /* Send character*/
365 usart->US_THR = c;
366
367 /* Wait for the transfer to complete*/
368 while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
369}
370
371/**
372 * \brief Return 1 if a character can be read in USART
373 */
374uint32_t USART_IsRxReady(Usart *usart)
375{
376 return (usart->US_CSR & US_CSR_RXRDY);
377}
378/**
379 * \brief Get present status
380 */
381uint32_t USART_GetStatus(Usart *usart)
382{
383 return usart->US_CSR;
384}
385/**
386 * \brief Enable interrupt
387 */
388void USART_EnableIt(Usart *usart,uint32_t mode)
389{
390 usart->US_IER = mode;
391}
392/**
393 * \brief Disable interrupt
394 */
395void USART_DisableIt(Usart *usart,uint32_t mode)
396{
397 usart->US_IDR = mode;
398}
399/**
400 * \brief Reads and returns a character from the USART.
401 *
402 * \note This function is synchronous (i.e. uses polling).
403 * \param usart Pointer to an USART peripheral.
404 * \return Character received.
405 */
406uint8_t USART_GetChar(Usart *usart)
407{
408 while ((usart->US_CSR & US_CSR_RXRDY) == 0);
409 return usart->US_RHR;
410}