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