]> git.sur5r.net Git - freertos/blob - Demo/AVR32_UC3A_GCC/Atmel_SW_Framework/DRIVERS/USART/usart.c
bfdc977792bb4a5874e550354bf4fec079e1f91c
[freertos] / Demo / AVR32_UC3A_GCC / Atmel_SW_Framework / DRIVERS / USART / usart.c
1 /* This source file is part of the ATMEL AVR-UC3-SoftwareFramework-1.7.0 Release */\r
2
3 /*This file is prepared for Doxygen automatic documentation generation.*/\r
4 /*! \file *********************************************************************\r
5  *\r
6  * \brief USART driver for AVR32 UC3.\r
7  *\r
8  * This file contains basic functions for the AVR32 USART, with support for all\r
9  * modes, settings and clock speeds.\r
10  *\r
11  * - Compiler:           IAR EWAVR32 and GNU GCC for AVR32\r
12  * - Supported devices:  All AVR32 devices with a USART module can be used.\r
13  * - AppNote:\r
14  *\r
15  * \author               Atmel Corporation: http://www.atmel.com \n\r
16  *                       Support and FAQ: http://support.atmel.no/\r
17  *\r
18  ******************************************************************************/\r
19 \r
20 /* Copyright (c) 2009 Atmel Corporation. All rights reserved.\r
21  *\r
22  * Redistribution and use in source and binary forms, with or without\r
23  * modification, are permitted provided that the following conditions are met:\r
24  *\r
25  * 1. Redistributions of source code must retain the above copyright notice, this\r
26  * list of conditions and the following disclaimer.\r
27  *\r
28  * 2. Redistributions in binary form must reproduce the above copyright notice,\r
29  * this list of conditions and the following disclaimer in the documentation\r
30  * and/or other materials provided with the distribution.\r
31  *\r
32  * 3. The name of Atmel may not be used to endorse or promote products derived\r
33  * from this software without specific prior written permission.\r
34  *\r
35  * 4. This software may only be redistributed and used in connection with an Atmel\r
36  * AVR product.\r
37  *\r
38  * THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED\r
39  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
40  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
41  * EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR\r
42  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\r
43  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\r
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\r
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\r
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\r
47  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE\r
48  *\r
49  */\r
50 \r
51 #include "compiler.h"\r
52 #include "usart.h"\r
53 \r
54 \r
55 //------------------------------------------------------------------------------\r
56 /*! \name Private Functions\r
57  */\r
58 //! @{\r
59 \r
60 \r
61 /*! \brief Checks if the USART is in multidrop mode.\r
62  *\r
63  * \param usart Base address of the USART instance.\r
64  *\r
65  * \return \c 1 if the USART is in multidrop mode, otherwise \c 0.\r
66  */\r
67 #if (defined __GNUC__)\r
68 __attribute__((__always_inline__))\r
69 #endif\r
70 static __inline__ int usart_mode_is_multidrop(volatile avr32_usart_t *usart)\r
71 {\r
72   return ((usart->mr >> AVR32_USART_MR_PAR_OFFSET) & AVR32_USART_MR_PAR_MULTI) == AVR32_USART_MR_PAR_MULTI;\r
73 }\r
74 \r
75 \r
76 /*! \brief Calculates a clock divider (\e CD) and a fractional part (\e FP) for\r
77  *         the USART asynchronous modes to generate a baud rate as close as\r
78  *         possible to the baud rate set point.\r
79  *\r
80  * Baud rate calculation:\r
81  * \f$ Baudrate = \frac{SelectedClock}{Over \times (CD + \frac{FP}{8})} \f$, \e Over being 16 or 8.\r
82  * The maximal oversampling is selected if it allows to generate a baud rate close to the set point.\r
83  *\r
84  * \param usart     Base address of the USART instance.\r
85  * \param baudrate  Baud rate set point.\r
86  * \param pba_hz    USART module input clock frequency (PBA clock, Hz).\r
87  *\r
88  * \retval USART_SUCCESS        Baud rate successfully initialized.\r
89  * \retval USART_INVALID_INPUT  Baud rate set point is out of range for the given input clock frequency.\r
90  */\r
91 static int usart_set_async_baudrate(volatile avr32_usart_t *usart, unsigned int baudrate, unsigned long pba_hz)\r
92 {\r
93   unsigned int over = (pba_hz >= 16 * baudrate) ? 16 : 8;\r
94   unsigned int cd_fp = ((1 << AVR32_USART_BRGR_FP_SIZE) * pba_hz + (over * baudrate) / 2) / (over * baudrate);\r
95   unsigned int cd = cd_fp >> AVR32_USART_BRGR_FP_SIZE;\r
96   unsigned int fp = cd_fp & ((1 << AVR32_USART_BRGR_FP_SIZE) - 1);\r
97 \r
98   if (cd < 1 || cd > (1 << AVR32_USART_BRGR_CD_SIZE) - 1)\r
99     return USART_INVALID_INPUT;\r
100 \r
101   usart->mr = (usart->mr & ~(AVR32_USART_MR_USCLKS_MASK |\r
102                              AVR32_USART_MR_SYNC_MASK |\r
103                              AVR32_USART_MR_OVER_MASK)) |\r
104               AVR32_USART_MR_USCLKS_MCK << AVR32_USART_MR_USCLKS_OFFSET |\r
105               ((over == 16) ? AVR32_USART_MR_OVER_X16 : AVR32_USART_MR_OVER_X8) << AVR32_USART_MR_OVER_OFFSET;\r
106 \r
107   usart->brgr = cd << AVR32_USART_BRGR_CD_OFFSET |\r
108                 fp << AVR32_USART_BRGR_FP_OFFSET;\r
109 \r
110   return USART_SUCCESS;\r
111 }\r
112 \r
113 \r
114 /*! \brief Calculates a clock divider (\e CD) for the USART synchronous master\r
115  *         modes to generate a baud rate as close as possible to the baud rate\r
116  *         set point.\r
117  *\r
118  * Baud rate calculation:\r
119  * \f$ Baudrate = \frac{SelectedClock}{CD} \f$.\r
120  *\r
121  * \param usart     Base address of the USART instance.\r
122  * \param baudrate  Baud rate set point.\r
123  * \param pba_hz    USART module input clock frequency (PBA clock, Hz).\r
124  *\r
125  * \retval USART_SUCCESS        Baud rate successfully initialized.\r
126  * \retval USART_INVALID_INPUT  Baud rate set point is out of range for the given input clock frequency.\r
127  */\r
128 static int usart_set_sync_master_baudrate(volatile avr32_usart_t *usart, unsigned int baudrate, unsigned long pba_hz)\r
129 {\r
130   unsigned int cd = (pba_hz + baudrate / 2) / baudrate;\r
131 \r
132   if (cd < 1 || cd > (1 << AVR32_USART_BRGR_CD_SIZE) - 1)\r
133     return USART_INVALID_INPUT;\r
134 \r
135   usart->mr = (usart->mr & ~AVR32_USART_MR_USCLKS_MASK) |\r
136               AVR32_USART_MR_USCLKS_MCK << AVR32_USART_MR_USCLKS_OFFSET |\r
137               AVR32_USART_MR_SYNC_MASK;\r
138 \r
139   usart->brgr = cd << AVR32_USART_BRGR_CD_OFFSET;\r
140 \r
141   return USART_SUCCESS;\r
142 }\r
143 \r
144 \r
145 /*! \brief Selects the SCK pin as the source of baud rate for the USART\r
146  *         synchronous slave modes.\r
147  *\r
148  * \param usart Base address of the USART instance.\r
149  *\r
150  * \retval USART_SUCCESS  Baud rate successfully initialized.\r
151  */\r
152 static int usart_set_sync_slave_baudrate(volatile avr32_usart_t *usart)\r
153 {\r
154   usart->mr = (usart->mr & ~AVR32_USART_MR_USCLKS_MASK) |\r
155               AVR32_USART_MR_USCLKS_SCK << AVR32_USART_MR_USCLKS_OFFSET |\r
156               AVR32_USART_MR_SYNC_MASK;\r
157 \r
158   return USART_SUCCESS;\r
159 }\r
160 \r
161 \r
162 /*! \brief Calculates a clock divider (\e CD) for the USART ISO7816 mode to\r
163  *         generate an ISO7816 clock as close as possible to the clock set point.\r
164  *\r
165  * ISO7816 clock calculation:\r
166  * \f$ Clock = \frac{SelectedClock}{CD} \f$.\r
167  *\r
168  * \param usart   Base address of the USART instance.\r
169  * \param clock   ISO7816 clock set point.\r
170  * \param pba_hz  USART module input clock frequency (PBA clock, Hz).\r
171  *\r
172  * \retval USART_SUCCESS        ISO7816 clock successfully initialized.\r
173  * \retval USART_INVALID_INPUT  ISO7816 clock set point is out of range for the given input clock frequency.\r
174  */\r
175 static int usart_set_iso7816_clock(volatile avr32_usart_t *usart, unsigned int clock, unsigned long pba_hz)\r
176 {\r
177   unsigned int cd = (pba_hz + clock / 2) / clock;\r
178 \r
179   if (cd < 1 || cd > (1 << AVR32_USART_BRGR_CD_SIZE) - 1)\r
180     return USART_INVALID_INPUT;\r
181 \r
182   usart->mr = (usart->mr & ~(AVR32_USART_MR_USCLKS_MASK |\r
183                              AVR32_USART_MR_SYNC_MASK |\r
184                              AVR32_USART_MR_OVER_MASK)) |\r
185               AVR32_USART_MR_USCLKS_MCK << AVR32_USART_MR_USCLKS_OFFSET |\r
186               AVR32_USART_MR_OVER_X16 << AVR32_USART_MR_OVER_OFFSET;\r
187 \r
188   usart->brgr = cd << AVR32_USART_BRGR_CD_OFFSET;\r
189 \r
190   return USART_SUCCESS;\r
191 }\r
192 \r
193 \r
194 #if defined(AVR32_USART_400_H_INCLUDED) || \\r
195     defined(AVR32_USART_410_H_INCLUDED) || \\r
196     defined(AVR32_USART_420_H_INCLUDED) || \\r
197     defined(AVR32_USART_440_H_INCLUDED) || \\r
198     defined(AVR32_USART_602_H_INCLUDED)\r
199 \r
200 \r
201 /*! \brief Calculates a clock divider (\e CD) for the USART SPI master mode to\r
202  *         generate a baud rate as close as possible to the baud rate set point.\r
203  *\r
204  * Baud rate calculation:\r
205  * \f$ Baudrate = \frac{SelectedClock}{CD} \f$.\r
206  *\r
207  * \param usart     Base address of the USART instance.\r
208  * \param baudrate  Baud rate set point.\r
209  * \param pba_hz    USART module input clock frequency (PBA clock, Hz).\r
210  *\r
211  * \retval USART_SUCCESS        Baud rate successfully initialized.\r
212  * \retval USART_INVALID_INPUT  Baud rate set point is out of range for the given input clock frequency.\r
213  */\r
214 static int usart_set_spi_master_baudrate(volatile avr32_usart_t *usart, unsigned int baudrate, unsigned long pba_hz)\r
215 {\r
216   unsigned int cd = (pba_hz + baudrate / 2) / baudrate;\r
217 \r
218   if (cd < 4 || cd > (1 << AVR32_USART_BRGR_CD_SIZE) - 1)\r
219     return USART_INVALID_INPUT;\r
220 \r
221   usart->mr = (usart->mr & ~AVR32_USART_MR_USCLKS_MASK) |\r
222               AVR32_USART_MR_USCLKS_MCK << AVR32_USART_MR_USCLKS_OFFSET;\r
223 \r
224   usart->brgr = cd << AVR32_USART_BRGR_CD_OFFSET;\r
225 \r
226   return USART_SUCCESS;\r
227 }\r
228 \r
229 \r
230 /*! \brief Selects the SCK pin as the source of baud rate for the USART SPI\r
231  *         slave mode.\r
232  *\r
233  * \param usart Base address of the USART instance.\r
234  *\r
235  * \retval USART_SUCCESS  Baud rate successfully initialized.\r
236  */\r
237 static int usart_set_spi_slave_baudrate(volatile avr32_usart_t *usart)\r
238 {\r
239   usart->mr = (usart->mr & ~AVR32_USART_MR_USCLKS_MASK) |\r
240               AVR32_USART_MR_USCLKS_SCK << AVR32_USART_MR_USCLKS_OFFSET;\r
241 \r
242   return USART_SUCCESS;\r
243 }\r
244 \r
245 \r
246 #endif  // USART rev. >= 4.0.0\r
247 \r
248 \r
249 //! @}\r
250 \r
251 \r
252 //------------------------------------------------------------------------------\r
253 /*! \name Initialization Functions\r
254  */\r
255 //! @{\r
256 \r
257 \r
258 void usart_reset(volatile avr32_usart_t *usart)\r
259 {\r
260   Bool global_interrupt_enabled = Is_global_interrupt_enabled();\r
261 \r
262   // Disable all USART interrupts.\r
263   // Interrupts needed should be set explicitly on every reset.\r
264   if (global_interrupt_enabled) Disable_global_interrupt();\r
265   usart->idr = 0xFFFFFFFF;\r
266   usart->csr;\r
267   if (global_interrupt_enabled) Enable_global_interrupt();\r
268 \r
269   // Reset mode and other registers that could cause unpredictable behavior after reset.\r
270   usart->mr = 0;\r
271   usart->rtor = 0;\r
272   usart->ttgr = 0;\r
273 \r
274   // Shutdown TX and RX (will be re-enabled when setup has successfully completed),\r
275   // reset status bits and turn off DTR and RTS.\r
276   usart->cr = AVR32_USART_CR_RSTRX_MASK   |\r
277               AVR32_USART_CR_RSTTX_MASK   |\r
278               AVR32_USART_CR_RSTSTA_MASK  |\r
279               AVR32_USART_CR_RSTIT_MASK   |\r
280               AVR32_USART_CR_RSTNACK_MASK |\r
281 #ifndef AVR32_USART_440_H_INCLUDED\r
282 // Note: Modem Signal Management DTR-DSR-DCD-RI are not included in USART rev.440.\r
283               AVR32_USART_CR_DTRDIS_MASK  |\r
284 #endif\r
285               AVR32_USART_CR_RTSDIS_MASK;\r
286 }\r
287 \r
288 \r
289 int usart_init_rs232(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz)\r
290 {\r
291   // Reset the USART and shutdown TX and RX.\r
292   usart_reset(usart);\r
293 \r
294   // Check input values.\r
295   if (!opt || // Null pointer.\r
296       opt->charlength < 5 || opt->charlength > 9 ||\r
297       opt->paritytype > 7 ||\r
298       opt->stopbits > 2 + 255 ||\r
299       opt->channelmode > 3 ||\r
300       usart_set_async_baudrate(usart, opt->baudrate, pba_hz) == USART_INVALID_INPUT)\r
301     return USART_INVALID_INPUT;\r
302 \r
303   if (opt->charlength == 9)\r
304   {\r
305     // Character length set to 9 bits. MODE9 dominates CHRL.\r
306     usart->mr |= AVR32_USART_MR_MODE9_MASK;\r
307   }\r
308   else\r
309   {\r
310     // CHRL gives the character length (- 5) when MODE9 = 0.\r
311     usart->mr |= (opt->charlength - 5) << AVR32_USART_MR_CHRL_OFFSET;\r
312   }\r
313 \r
314   usart->mr |= opt->paritytype << AVR32_USART_MR_PAR_OFFSET |\r
315                opt->channelmode << AVR32_USART_MR_CHMODE_OFFSET;\r
316 \r
317   if (opt->stopbits > USART_2_STOPBITS)\r
318   {\r
319     // Set two stop bits\r
320     usart->mr |= AVR32_USART_MR_NBSTOP_2 << AVR32_USART_MR_NBSTOP_OFFSET;\r
321     // and a timeguard period gives the rest.\r
322     usart->ttgr = opt->stopbits - USART_2_STOPBITS;\r
323   }\r
324   else\r
325     // Insert 1, 1.5 or 2 stop bits.\r
326     usart->mr |= opt->stopbits << AVR32_USART_MR_NBSTOP_OFFSET;\r
327 \r
328   // Set normal mode.\r
329   usart->mr = (usart->mr & ~AVR32_USART_MR_MODE_MASK) |\r
330               AVR32_USART_MR_MODE_NORMAL << AVR32_USART_MR_MODE_OFFSET;\r
331 \r
332   // Setup complete; enable communication.\r
333   // Enable input and output.\r
334   usart->cr = AVR32_USART_CR_RXEN_MASK |\r
335               AVR32_USART_CR_TXEN_MASK;\r
336 \r
337   return USART_SUCCESS;\r
338 }\r
339 \r
340 \r
341 int usart_init_rs232_tx_only(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz)\r
342 {\r
343   // Reset the USART and shutdown TX and RX.\r
344   usart_reset(usart);\r
345 \r
346   // Check input values.\r
347   if (!opt || // Null pointer.\r
348       opt->charlength < 5 || opt->charlength > 9 ||\r
349       opt->paritytype > 7 ||\r
350       opt->stopbits == 1 || opt->stopbits > 2 + 255 ||\r
351       opt->channelmode > 3 ||\r
352       usart_set_sync_master_baudrate(usart, opt->baudrate, pba_hz) == USART_INVALID_INPUT)\r
353     return USART_INVALID_INPUT;\r
354 \r
355   if (opt->charlength == 9)\r
356   {\r
357     // Character length set to 9 bits. MODE9 dominates CHRL.\r
358     usart->mr |= AVR32_USART_MR_MODE9_MASK;\r
359   }\r
360   else\r
361   {\r
362     // CHRL gives the character length (- 5) when MODE9 = 0.\r
363     usart->mr |= (opt->charlength - 5) << AVR32_USART_MR_CHRL_OFFSET;\r
364   }\r
365 \r
366   usart->mr |= opt->paritytype << AVR32_USART_MR_PAR_OFFSET |\r
367                opt->channelmode << AVR32_USART_MR_CHMODE_OFFSET;\r
368 \r
369   if (opt->stopbits > USART_2_STOPBITS)\r
370   {\r
371     // Set two stop bits\r
372     usart->mr |= AVR32_USART_MR_NBSTOP_2 << AVR32_USART_MR_NBSTOP_OFFSET;\r
373     // and a timeguard period gives the rest.\r
374     usart->ttgr = opt->stopbits - USART_2_STOPBITS;\r
375   }\r
376   else\r
377     // Insert 1 or 2 stop bits.\r
378     usart->mr |= opt->stopbits << AVR32_USART_MR_NBSTOP_OFFSET;\r
379 \r
380   // Set normal mode.\r
381   usart->mr = (usart->mr & ~AVR32_USART_MR_MODE_MASK) |\r
382               AVR32_USART_MR_MODE_NORMAL << AVR32_USART_MR_MODE_OFFSET;\r
383 \r
384   // Setup complete; enable communication.\r
385   // Enable only output as input is not possible in synchronous mode without\r
386   // transferring clock.\r
387   usart->cr = AVR32_USART_CR_TXEN_MASK;\r
388 \r
389   return USART_SUCCESS;\r
390 }\r
391 \r
392 \r
393 int usart_init_hw_handshaking(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz)\r
394 {\r
395   // First: Setup standard RS232.\r
396   if (usart_init_rs232(usart, opt, pba_hz) == USART_INVALID_INPUT)\r
397     return USART_INVALID_INPUT;\r
398 \r
399   // Set hardware handshaking mode.\r
400   usart->mr = (usart->mr & ~AVR32_USART_MR_MODE_MASK) |\r
401               AVR32_USART_MR_MODE_HARDWARE << AVR32_USART_MR_MODE_OFFSET;\r
402 \r
403   return USART_SUCCESS;\r
404 }\r
405 \r
406 \r
407 int usart_init_modem(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz)\r
408 {\r
409   // First: Setup standard RS232.\r
410   if (usart_init_rs232(usart, opt, pba_hz) == USART_INVALID_INPUT)\r
411     return USART_INVALID_INPUT;\r
412 \r
413   // Set modem mode.\r
414   usart->mr = (usart->mr & ~AVR32_USART_MR_MODE_MASK) |\r
415               AVR32_USART_MR_MODE_MODEM << AVR32_USART_MR_MODE_OFFSET;\r
416 \r
417   return USART_SUCCESS;\r
418 }\r
419 \r
420 \r
421 int usart_init_sync_master(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz)\r
422 {\r
423   // Reset the USART and shutdown TX and RX.\r
424   usart_reset(usart);\r
425 \r
426   // Check input values.\r
427   if (!opt || // Null pointer.\r
428       opt->charlength < 5 || opt->charlength > 9 ||\r
429       opt->paritytype > 7 ||\r
430       opt->stopbits == 1 || opt->stopbits > 2 + 255 ||\r
431       opt->channelmode > 3 ||\r
432       usart_set_sync_master_baudrate(usart, opt->baudrate, pba_hz) == USART_INVALID_INPUT)\r
433     return USART_INVALID_INPUT;\r
434 \r
435   if (opt->charlength == 9)\r
436   {\r
437     // Character length set to 9 bits. MODE9 dominates CHRL.\r
438     usart->mr |= AVR32_USART_MR_MODE9_MASK;\r
439   }\r
440   else\r
441   {\r
442     // CHRL gives the character length (- 5) when MODE9 = 0.\r
443     usart->mr |= (opt->charlength - 5) << AVR32_USART_MR_CHRL_OFFSET;\r
444   }\r
445 \r
446   usart->mr |= opt->paritytype << AVR32_USART_MR_PAR_OFFSET |\r
447                opt->channelmode << AVR32_USART_MR_CHMODE_OFFSET;\r
448 \r
449   if (opt->stopbits > USART_2_STOPBITS)\r
450   {\r
451     // Set two stop bits\r
452     usart->mr |= AVR32_USART_MR_NBSTOP_2 << AVR32_USART_MR_NBSTOP_OFFSET;\r
453     // and a timeguard period gives the rest.\r
454     usart->ttgr = opt->stopbits - USART_2_STOPBITS;\r
455   }\r
456   else\r
457     // Insert 1 or 2 stop bits.\r
458     usart->mr |= opt->stopbits << AVR32_USART_MR_NBSTOP_OFFSET;\r
459 \r
460   // Set normal mode.\r
461   usart->mr = (usart->mr & ~AVR32_USART_MR_MODE_MASK) |\r
462               AVR32_USART_MR_MODE_NORMAL << AVR32_USART_MR_MODE_OFFSET |\r
463               AVR32_USART_MR_CLKO_MASK;\r
464 \r
465   // Setup complete; enable communication.\r
466   // Enable input and output.\r
467   usart->cr = AVR32_USART_CR_RXEN_MASK |\r
468               AVR32_USART_CR_TXEN_MASK;\r
469 \r
470   return USART_SUCCESS;\r
471 }\r
472 \r
473 \r
474 int usart_init_sync_slave(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz)\r
475 {\r
476   // Reset the USART and shutdown TX and RX.\r
477   usart_reset(usart);\r
478 \r
479   // Check input values.\r
480   if (!opt || // Null pointer.\r
481       opt->charlength < 5 || opt->charlength > 9 ||\r
482       opt->paritytype > 7 ||\r
483       opt->stopbits == 1 || opt->stopbits > 2 + 255 ||\r
484       opt->channelmode > 3 ||\r
485       usart_set_sync_slave_baudrate(usart) == USART_INVALID_INPUT)\r
486     return USART_INVALID_INPUT;\r
487 \r
488   if (opt->charlength == 9)\r
489   {\r
490     // Character length set to 9 bits. MODE9 dominates CHRL.\r
491     usart->mr |= AVR32_USART_MR_MODE9_MASK;\r
492   }\r
493   else\r
494   {\r
495     // CHRL gives the character length (- 5) when MODE9 = 0.\r
496     usart->mr |= (opt->charlength - 5) << AVR32_USART_MR_CHRL_OFFSET;\r
497   }\r
498 \r
499   usart->mr |= opt->paritytype << AVR32_USART_MR_PAR_OFFSET |\r
500                opt->channelmode << AVR32_USART_MR_CHMODE_OFFSET;\r
501 \r
502   if (opt->stopbits > USART_2_STOPBITS)\r
503   {\r
504     // Set two stop bits\r
505     usart->mr |= AVR32_USART_MR_NBSTOP_2 << AVR32_USART_MR_NBSTOP_OFFSET;\r
506     // and a timeguard period gives the rest.\r
507     usart->ttgr = opt->stopbits - USART_2_STOPBITS;\r
508   }\r
509   else\r
510     // Insert 1 or 2 stop bits.\r
511     usart->mr |= opt->stopbits << AVR32_USART_MR_NBSTOP_OFFSET;\r
512 \r
513   // Set normal mode.\r
514   usart->mr = (usart->mr & ~AVR32_USART_MR_MODE_MASK) |\r
515               AVR32_USART_MR_MODE_NORMAL << AVR32_USART_MR_MODE_OFFSET;\r
516 \r
517   // Setup complete; enable communication.\r
518   // Enable input and output.\r
519   usart->cr = AVR32_USART_CR_RXEN_MASK |\r
520               AVR32_USART_CR_TXEN_MASK;\r
521 \r
522   return USART_SUCCESS;\r
523 }\r
524 \r
525 \r
526 int usart_init_rs485(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz)\r
527 {\r
528   // First: Setup standard RS232.\r
529   if (usart_init_rs232(usart, opt, pba_hz) == USART_INVALID_INPUT)\r
530     return USART_INVALID_INPUT;\r
531 \r
532   // Set RS485 mode.\r
533   usart->mr = (usart->mr & ~AVR32_USART_MR_MODE_MASK) |\r
534               AVR32_USART_MR_MODE_RS485 << AVR32_USART_MR_MODE_OFFSET;\r
535 \r
536   return USART_SUCCESS;\r
537 }\r
538 \r
539 \r
540 int usart_init_IrDA(volatile avr32_usart_t *usart, const usart_options_t *opt,\r
541                     long pba_hz, unsigned char irda_filter)\r
542 {\r
543   // First: Setup standard RS232.\r
544   if (usart_init_rs232(usart, opt, pba_hz) == USART_INVALID_INPUT)\r
545     return USART_INVALID_INPUT;\r
546 \r
547   // Set IrDA filter.\r
548   usart->ifr = irda_filter;\r
549 \r
550   // Set IrDA mode and activate filtering of input.\r
551   usart->mr = (usart->mr & ~AVR32_USART_MR_MODE_MASK) |\r
552               AVR32_USART_MODE_IRDA << AVR32_USART_MR_MODE_OFFSET |\r
553               AVR32_USART_MR_FILTER_MASK;\r
554 \r
555   return USART_SUCCESS;\r
556 }\r
557 \r
558 \r
559 int usart_init_iso7816(volatile avr32_usart_t *usart, const usart_iso7816_options_t *opt, int t, long pba_hz)\r
560 {\r
561   // Reset the USART and shutdown TX and RX.\r
562   usart_reset(usart);\r
563 \r
564   // Check input values.\r
565   if (!opt || // Null pointer.\r
566       opt->paritytype > 1)\r
567     return USART_INVALID_INPUT;\r
568 \r
569   if (t == 0)\r
570   {\r
571     // Set USART mode to ISO7816, T=0.\r
572     // The T=0 protocol always uses 2 stop bits.\r
573     usart->mr = AVR32_USART_MR_MODE_ISO7816_T0 << AVR32_USART_MR_MODE_OFFSET |\r
574                 AVR32_USART_MR_NBSTOP_2 << AVR32_USART_MR_NBSTOP_OFFSET |\r
575                 opt->bit_order << AVR32_USART_MR_MSBF_OFFSET; // Allow MSBF in T=0.\r
576   }\r
577   else if (t == 1)\r
578   {\r
579     // Only LSB first in the T=1 protocol.\r
580     // max_iterations field is only used in T=0 mode.\r
581     if (opt->bit_order != 0 ||\r
582         opt->max_iterations != 0)\r
583       return USART_INVALID_INPUT;\r
584 \r
585     // Set USART mode to ISO7816, T=1.\r
586     // The T=1 protocol always uses 1 stop bit.\r
587     usart->mr = AVR32_USART_MR_MODE_ISO7816_T1 << AVR32_USART_MR_MODE_OFFSET |\r
588                 AVR32_USART_MR_NBSTOP_1 << AVR32_USART_MR_NBSTOP_OFFSET;\r
589   }\r
590   else\r
591     return USART_INVALID_INPUT;\r
592 \r
593   if (usart_set_iso7816_clock(usart, opt->iso7816_hz, pba_hz) == USART_INVALID_INPUT)\r
594     return USART_INVALID_INPUT;\r
595 \r
596   // Set FIDI register: bit rate = selected clock/FI_DI_ratio/16.\r
597   usart->fidi = opt->fidi_ratio;\r
598 \r
599   // Set ISO7816 spesific options in the MODE register.\r
600   usart->mr |= opt->paritytype << AVR32_USART_MR_PAR_OFFSET |\r
601                AVR32_USART_MR_CLKO_MASK | // Enable clock output.\r
602                opt->inhibit_nack << AVR32_USART_MR_INACK_OFFSET |\r
603                opt->dis_suc_nack << AVR32_USART_MR_DSNACK_OFFSET |\r
604                opt->max_iterations << AVR32_USART_MR_MAX_ITERATION_OFFSET;\r
605 \r
606   // Setup complete; enable the receiver by default.\r
607   usart_iso7816_enable_receiver(usart);\r
608 \r
609   return USART_SUCCESS;\r
610 }\r
611 \r
612 \r
613 #if defined(AVR32_USART_400_H_INCLUDED) || \\r
614     defined(AVR32_USART_410_H_INCLUDED) || \\r
615     defined(AVR32_USART_420_H_INCLUDED) || \\r
616     defined(AVR32_USART_440_H_INCLUDED) || \\r
617     defined(AVR32_USART_602_H_INCLUDED)\r
618 \r
619 \r
620 int usart_init_lin_master(volatile avr32_usart_t *usart, unsigned long baudrate, long pba_hz)\r
621 {\r
622   // Reset the USART and shutdown TX and RX.\r
623   usart_reset(usart);\r
624 \r
625   // Check input values.\r
626   if (usart_set_async_baudrate(usart, baudrate, pba_hz) == USART_INVALID_INPUT)\r
627     return USART_INVALID_INPUT;\r
628 \r
629   usart->mr |= AVR32_USART_MR_MODE_LIN_MASTER << AVR32_USART_MR_MODE_OFFSET;  // LIN master mode.\r
630 \r
631   // Setup complete; enable communication.\r
632   // Enable input and output.\r
633   usart->cr = AVR32_USART_CR_RXEN_MASK |\r
634               AVR32_USART_CR_TXEN_MASK;\r
635 \r
636   return USART_SUCCESS;\r
637 }\r
638 \r
639 \r
640 int usart_init_lin_slave(volatile avr32_usart_t *usart, unsigned long baudrate, long pba_hz)\r
641 {\r
642   // Reset the USART and shutdown TX and RX.\r
643   usart_reset(usart);\r
644 \r
645   // Check input values.\r
646   if (usart_set_async_baudrate(usart, baudrate, pba_hz) == USART_INVALID_INPUT)\r
647     return USART_INVALID_INPUT;\r
648 \r
649   usart->mr |= AVR32_USART_MR_MODE_LIN_SLAVE << AVR32_USART_MR_MODE_OFFSET; // LIN slave mode.\r
650 \r
651   // Setup complete; enable communication.\r
652   // Enable input and output.\r
653   usart->cr = AVR32_USART_CR_RXEN_MASK |\r
654               AVR32_USART_CR_TXEN_MASK;\r
655 \r
656   return USART_SUCCESS;\r
657 }\r
658 \r
659 \r
660 int usart_init_spi_master(volatile avr32_usart_t *usart, const usart_spi_options_t *opt, long pba_hz)\r
661 {\r
662   // Reset the USART and shutdown TX and RX.\r
663   usart_reset(usart);\r
664 \r
665   // Check input values.\r
666   if (!opt || // Null pointer.\r
667       opt->charlength < 5 || opt->charlength > 9 ||\r
668       opt->spimode > 3 ||\r
669       opt->channelmode > 3 ||\r
670       usart_set_spi_master_baudrate(usart, opt->baudrate, pba_hz) == USART_INVALID_INPUT)\r
671     return USART_INVALID_INPUT;\r
672 \r
673   if (opt->charlength == 9)\r
674   {\r
675     // Character length set to 9 bits. MODE9 dominates CHRL.\r
676     usart->mr |= AVR32_USART_MR_MODE9_MASK;\r
677   }\r
678   else\r
679   {\r
680     // CHRL gives the character length (- 5) when MODE9 = 0.\r
681     usart->mr |= (opt->charlength - 5) << AVR32_USART_MR_CHRL_OFFSET;\r
682   }\r
683 \r
684   usart->mr |= AVR32_USART_MR_MODE_SPI_MASTER << AVR32_USART_MR_MODE_OFFSET | // SPI master mode.\r
685                ((opt->spimode & 0x1) ^ 0x1) << AVR32_USART_MR_SYNC_OFFSET |   // SPI clock phase.\r
686                opt->channelmode << AVR32_USART_MR_CHMODE_OFFSET |             // Channel mode.\r
687                (opt->spimode >> 1) << AVR32_USART_MR_MSBF_OFFSET |            // SPI clock polarity.\r
688                AVR32_USART_MR_CLKO_MASK;                                      // Drive SCK pin.\r
689 \r
690   // Setup complete; enable communication.\r
691   // Enable input and output.\r
692   usart->cr = AVR32_USART_CR_RXEN_MASK |\r
693               AVR32_USART_CR_TXEN_MASK;\r
694 \r
695   return USART_SUCCESS;\r
696 }\r
697 \r
698 \r
699 int usart_init_spi_slave(volatile avr32_usart_t *usart, const usart_spi_options_t *opt, long pba_hz)\r
700 {\r
701   // Reset the USART and shutdown TX and RX.\r
702   usart_reset(usart);\r
703 \r
704   // Check input values.\r
705   if (!opt || // Null pointer.\r
706       opt->charlength < 5 || opt->charlength > 9 ||\r
707       opt->spimode > 3 ||\r
708       opt->channelmode > 3 ||\r
709       usart_set_spi_slave_baudrate(usart) == USART_INVALID_INPUT)\r
710     return USART_INVALID_INPUT;\r
711 \r
712   if (opt->charlength == 9)\r
713   {\r
714     // Character length set to 9 bits. MODE9 dominates CHRL.\r
715     usart->mr |= AVR32_USART_MR_MODE9_MASK;\r
716   }\r
717   else\r
718   {\r
719     // CHRL gives the character length (- 5) when MODE9 = 0.\r
720     usart->mr |= (opt->charlength - 5) << AVR32_USART_MR_CHRL_OFFSET;\r
721   }\r
722 \r
723   usart->mr |= AVR32_USART_MR_MODE_SPI_SLAVE << AVR32_USART_MR_MODE_OFFSET |  // SPI slave mode.\r
724                ((opt->spimode & 0x1) ^ 0x1) << AVR32_USART_MR_SYNC_OFFSET |   // SPI clock phase.\r
725                opt->channelmode << AVR32_USART_MR_CHMODE_OFFSET |             // Channel mode.\r
726                (opt->spimode >> 1) << AVR32_USART_MR_MSBF_OFFSET;             // SPI clock polarity.\r
727 \r
728   // Setup complete; enable communication.\r
729   // Enable input and output.\r
730   usart->cr = AVR32_USART_CR_RXEN_MASK |\r
731               AVR32_USART_CR_TXEN_MASK;\r
732 \r
733   return USART_SUCCESS;\r
734 }\r
735 \r
736 \r
737 #endif  // USART rev. >= 4.0.0\r
738 \r
739 \r
740 //! @}\r
741 \r
742 \r
743 //------------------------------------------------------------------------------\r
744 #if defined(AVR32_USART_400_H_INCLUDED) || \\r
745     defined(AVR32_USART_410_H_INCLUDED) || \\r
746     defined(AVR32_USART_420_H_INCLUDED) || \\r
747     defined(AVR32_USART_440_H_INCLUDED) || \\r
748     defined(AVR32_USART_602_H_INCLUDED)\r
749 \r
750 \r
751 /*! \name SPI Control Functions\r
752  */\r
753 //! @{\r
754 \r
755 \r
756 int usart_spi_selectChip(volatile avr32_usart_t *usart)\r
757 {\r
758   // Force the SPI chip select.\r
759   usart->cr = AVR32_USART_CR_RTSEN_MASK;\r
760 \r
761   return USART_SUCCESS;\r
762 }\r
763 \r
764 \r
765 int usart_spi_unselectChip(volatile avr32_usart_t *usart)\r
766 {\r
767   int timeout = USART_DEFAULT_TIMEOUT;\r
768 \r
769   do\r
770   {\r
771     if (!timeout--) return USART_FAILURE;\r
772   } while (!usart_tx_empty(usart));\r
773 \r
774   // Release the SPI chip select.\r
775   usart->cr = AVR32_USART_CR_RTSDIS_MASK;\r
776 \r
777   return USART_SUCCESS;\r
778 }\r
779 \r
780 \r
781 //! @}\r
782 \r
783 \r
784 #endif  // USART rev. >= 4.0.0\r
785 \r
786 \r
787 //------------------------------------------------------------------------------\r
788 /*! \name Transmit/Receive Functions\r
789  */\r
790 //! @{\r
791 \r
792 \r
793 int usart_send_address(volatile avr32_usart_t *usart, int address)\r
794 {\r
795   // Check if USART is in multidrop / RS485 mode.\r
796   if (!usart_mode_is_multidrop(usart)) return USART_MODE_FAULT;\r
797 \r
798   // Prepare to send an address.\r
799   usart->cr = AVR32_USART_CR_SENDA_MASK;\r
800 \r
801   // Write the address to TX.\r
802   usart_bw_write_char(usart, address);\r
803 \r
804   return USART_SUCCESS;\r
805 }\r
806 \r
807 \r
808 int usart_write_char(volatile avr32_usart_t *usart, int c)\r
809 {\r
810   if (usart_tx_ready(usart))\r
811   {\r
812     usart->thr = (c << AVR32_USART_THR_TXCHR_OFFSET) & AVR32_USART_THR_TXCHR_MASK;\r
813     return USART_SUCCESS;\r
814   }\r
815   else\r
816     return USART_TX_BUSY;\r
817 }\r
818 \r
819 \r
820 int usart_putchar(volatile avr32_usart_t *usart, int c)\r
821 {\r
822   int timeout = USART_DEFAULT_TIMEOUT;\r
823 \r
824   if (c == '\n')\r
825   {\r
826     do\r
827     {\r
828       if (!timeout--) return USART_FAILURE;\r
829     } while (usart_write_char(usart, '\r') != USART_SUCCESS);\r
830 \r
831     timeout = USART_DEFAULT_TIMEOUT;\r
832   }\r
833 \r
834   do\r
835   {\r
836     if (!timeout--) return USART_FAILURE;\r
837   } while (usart_write_char(usart, c) != USART_SUCCESS);\r
838 \r
839   return USART_SUCCESS;\r
840 }\r
841 \r
842 \r
843 int usart_read_char(volatile avr32_usart_t *usart, int *c)\r
844 {\r
845   // Check for errors: frame, parity and overrun. In RS485 mode, a parity error\r
846   // would mean that an address char has been received.\r
847   if (usart->csr & (AVR32_USART_CSR_OVRE_MASK |\r
848                     AVR32_USART_CSR_FRAME_MASK |\r
849                     AVR32_USART_CSR_PARE_MASK))\r
850     return USART_RX_ERROR;\r
851 \r
852   // No error; if we really did receive a char, read it and return SUCCESS.\r
853   if (usart_test_hit(usart))\r
854   {\r
855     *c = (usart->rhr & AVR32_USART_RHR_RXCHR_MASK) >> AVR32_USART_RHR_RXCHR_OFFSET;\r
856     return USART_SUCCESS;\r
857   }\r
858   else\r
859     return USART_RX_EMPTY;\r
860 }\r
861 \r
862 \r
863 int usart_getchar(volatile avr32_usart_t *usart)\r
864 {\r
865   int c, ret;\r
866 \r
867   while ((ret = usart_read_char(usart, &c)) == USART_RX_EMPTY);\r
868 \r
869   if (ret == USART_RX_ERROR)\r
870     return USART_FAILURE;\r
871 \r
872   return c;\r
873 }\r
874 \r
875 \r
876 void usart_write_line(volatile avr32_usart_t *usart, const char *string)\r
877 {\r
878   while (*string != '\0')\r
879     usart_putchar(usart, *string++);\r
880 }\r
881 \r
882 \r
883 int usart_get_echo_line(volatile avr32_usart_t *usart)\r
884 {\r
885   int rx_char;\r
886   int retval = USART_SUCCESS;\r
887 \r
888   while (1)\r
889   {\r
890     rx_char = usart_getchar(usart);\r
891     if (rx_char == USART_FAILURE)\r
892     {\r
893       usart_write_line(usart, "Error!!!\n");\r
894       retval = USART_FAILURE;\r
895       break;\r
896     }\r
897     if (rx_char == '\x03')\r
898     {\r
899       retval = USART_FAILURE;\r
900       break;\r
901     }\r
902     usart_putchar(usart, rx_char);\r
903     if (rx_char == '\r')\r
904     {\r
905       usart_putchar(usart, '\n');\r
906       break;\r
907     }\r
908   }\r
909 \r
910   return retval;\r
911 }\r
912 \r
913 \r
914 //! @}\r