usart.c

Go to the documentation of this file.
00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
00023 /* Copyright (c) 2006, Atmel Corporation All rights reserved.
00024  *
00025  * Redistribution and use in source and binary forms, with or without
00026  * modification, are permitted provided that the following conditions are met:
00027  *
00028  * 1. Redistributions of source code must retain the above copyright notice,
00029  * this list of conditions and the following disclaimer.
00030  *
00031  * 2. Redistributions in binary form must reproduce the above copyright notice,
00032  * this list of conditions and the following disclaimer in the documentation
00033  * and/or other materials provided with the distribution.
00034  *
00035  * 3. The name of ATMEL may not be used to endorse or promote products derived
00036  * from this software without specific prior written permission.
00037  *
00038  * THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
00039  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
00040  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
00041  * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00042  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00043  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00044  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
00045  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00046  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
00047  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00048  */
00049 
00050 #include "usart.h"
00051 
00056 void usart_reset(volatile avr32_usart_t * usart)
00057 {
00058     /* Disable all usart interrupts, interrupts needed should be set
00059        explicitly on every reset */
00060     usart->idr = 0xFFFFffff;
00061 
00062     /* Reset mode and other registers that could cause unpredictable
00063        behaviour after reset */
00064     usart->mr = 0;
00065     usart->rtor = 0;
00066     usart->ttgr = 0;
00067 
00068     /* Shutdown RX and TX (will be reenabled when setup
00069        is completed successfully), reset status bits and turn
00070        off DTR and RTS */
00071     usart->cr = AVR32_USART_CR_RSTRX_MASK|
00072                 AVR32_USART_CR_RSTTX_MASK|
00073                 AVR32_USART_CR_RSTSTA_MASK|
00074                 AVR32_USART_CR_RSTIT_MASK|
00075                 AVR32_USART_CR_RSTNACK_MASK|
00076                 AVR32_USART_CR_DTRDIS_MASK|
00077                 AVR32_USART_CR_RTSDIS_MASK;
00078 }
00079 
00080 
00094 static int usart_set_baudrate(volatile avr32_usart_t * usart,
00095         unsigned int baudrate,
00096         const long cpuHz)
00097 {
00098     int cd, fp; /* clock divider and fractional part */
00099 
00100     /*
00101      *             ** BAUDRATE CALCULATION **
00102      *
00103      *                 selected clock                       selected clock
00104      *     baudrate = ----------------   or     baudrate = ----------------
00105      *                16 x (CD + FP/8)                      8 x (CD + FP/8)
00106      *
00107      *       (with 16x oversampling)              (with 8x oversampling)
00108      */
00109     if (baudrate > (cpuHz/16)) {
00110         /* use 8x oversampling */
00111         usart->mr |= (AVR32_USART_MR_OVER_MASK);
00112         cd = cpuHz / (8 * baudrate);
00113 
00114         if (cd < 2) {
00115             /* wanted baudrate is too high */
00116             return USART_ERROR_ARGUMENT;
00117         }
00118 
00119         fp = cpuHz / baudrate - 8 * cd;
00120         usart->brgr = (fp << AVR32_USART_BRGR_FP_OFFSET)
00121             | (cd << AVR32_USART_BRGR_CD_OFFSET);
00122     } else {
00123         /* use 16x oversampling */
00124         usart->mr &= ~(AVR32_USART_MR_OVER_MASK);
00125         cd = cpuHz / (16 * baudrate);
00126 
00127         if (cd > 65535) {
00128             /* wanted baudrate is too low */
00129             return USART_ERROR_ARGUMENT;
00130         }
00131 
00132         fp = cpuHz / (2 * baudrate) - 16 * cd;
00133         usart->brgr = (fp << AVR32_USART_BRGR_FP_OFFSET)
00134             | (cd << AVR32_USART_BRGR_CD_OFFSET);
00135     }
00136 
00137     return USART_OK;
00138 }
00139 
00140 
00152 int usart_linit(volatile avr32_usart_t * usart,
00153         const struct usart_options_t * opt,
00154         const long cpuHz)
00155 {
00156     int retval;
00157 
00158     /* reset the usart and shutdown RX and TX */
00159     usart_reset(usart);
00160 
00161     /* control input values */
00162     if (opt == 0) {
00163         return USART_ERROR_ARGUMENT;
00164     }
00165     if (opt->charlength < 5 || opt->charlength > 9) {
00166         return USART_ERROR_ARGUMENT;
00167     }
00168     if (opt->paritytype > 7) {
00169         return USART_ERROR_ARGUMENT;
00170     }
00171     if (opt->stopbits > 2+255) {
00172         return USART_ERROR_ARGUMENT;
00173     }
00174     if (opt->channelmode > 3) {
00175         return USART_ERROR_ARGUMENT;
00176     }
00177 
00178     retval = usart_set_baudrate(usart, opt->baudrate, cpuHz);
00179 
00180     if (retval != USART_OK) {
00181         return retval;
00182     }
00183 
00184     if (opt->charlength == 9) {
00185         /* charlength set to 9 bits; MODE9 dominates CHRL */
00186         usart->mr |= AVR32_USART_MR_MODE9_MASK;
00187     } else {
00188         /* CHRL gives the charlength(- 5) when USART_MODE9=0 */
00189         usart->mr |=
00190             ((opt->charlength-5)<<AVR32_USART_MR_CHRL_OFFSET);
00191     }
00192 
00193     usart->mr |= (opt->channelmode<<AVR32_USART_MR_CHMODE_OFFSET)|
00194                  (opt->paritytype<<AVR32_USART_MR_PAR_OFFSET);
00195 
00196     if (opt->stopbits > 2) {
00197         /* set two stop bits */
00198         usart->mr |= (2<<AVR32_USART_MR_NBSTOP_OFFSET);
00199         /* and a timeguard period gives the rest */
00200         usart->ttgr = (opt->stopbits-2);
00201     } else {
00202         /* insert 1, 1.5 or 2 stop bits */
00203         usart->mr |= (opt->stopbits<<AVR32_USART_MR_NBSTOP_OFFSET);
00204     }
00205 
00206     /* enable TX and RX */
00207     usart->cr |= AVR32_USART_CR_TXEN_MASK|AVR32_USART_CR_RXEN_MASK;
00208 
00209     return USART_OK;
00210 }
00211 
00212 
00222 int usart_putchar(volatile avr32_usart_t * usart, const short character)
00223 {
00224     int timeout = USART_DEFAULT_TIMEOUT;
00225 
00226     do {
00227         --timeout;
00228     } while ((usart->csr & AVR32_USART_CSR_TXRDY_MASK) == 0 && timeout > 0);
00229 
00230     if (timeout == 0) {
00231         return USART_TX_BUSY;
00232     }
00233 
00234     usart->thr = character;
00235 
00236     return USART_OK;
00237 }
00238 
00239 
00240 /* printf rewrite functions */
00241 
00252 int _write_r(struct _reent *ptr, int fd, const void *buf, size_t cnt)
00253 {
00254     volatile char *msg = (char *) buf;
00255     volatile int i;
00256 
00257     for (i=0; i < cnt; i++) {
00258         usart_putchar(&USART_MODULE, *msg++);
00259     }
00260 
00261     return cnt;
00262 }
00263 

Generated on Thu Oct 18 09:30:01 2007 for AVR32113 Configuration and Use of the Memory Management Unit by  doxygen 1.5.3