usart.c

Go to the documentation of this file.
00001 /*This file has been prepared for Doxygen automatic documentation generation.*/
00022 /* ************************************************************************
00023 
00024 Copyright (c) 2006, Atmel Corporation All rights reserved.
00025 
00026 Redistribution and use in source and binary forms, with or without
00027 modification, are permitted provided that the following conditions are met:
00028 
00029 1. Redistributions of source code must retain the above copyright notice,
00030 this list of conditions and the
00031 following disclaimer.
00032 
00033 2. Redistributions in binary form must reproduce the above copyright notice,
00034 this list of conditions and the following disclaimer in the documentation
00035 and/or other materials provided with the distribution.
00036 
00037 3. The name of ATMEL may not be used to endorse or promote products
00038 derived from this software without specific prior written permission.
00039 
00040 THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS
00041 OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00042 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
00043 PARTICULAR PURPOSE ARE EXPRESSLY AND SPECIFICALLY
00044 DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
00045 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00046 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00047 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
00048 OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
00049 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00050 OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
00051 WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00052 
00053 POSSIBILITY OF SUCH DAMAGE.
00054 
00055 \* ************************************************************************ */
00056 
00057 #include "usart.h"
00058 #include "errno.h"
00059 
00060 /*
00061  * Description: Check if the usart is in multidrop
00062  * Arguments:   *usart: Base address of the usart
00063  * Returns:     1 if the usart is in multidrop mode, otherwise 0
00064  */
00065 
00066 static int usart_mode_is_multidrop(volatile struct avr32_usart_t * usart)
00067 {
00068   return ( (usart->mr & 0x00000600) >> AVR32_USART_MR_PAR_OFFSET );
00069 }
00070 
00071 void usart_reset( volatile struct avr32_usart_t * usart)
00072 {
00073         /* Disable all usart interrupts, interrupts needed should be set
00074            explicitly on every reset */
00075         usart->idr = 0xFFFFffff;
00076 
00077         /* Reset mode and other registers that could cause unpredictable
00078            behaviour after reset */
00079         usart->mr = 0;
00080         usart->rtor = 0;
00081         usart->ttgr = 0;
00082 
00083         /* Shutdown RX and TX (will be reenabled when setup
00084            is completed successfully), reset status bits and turn
00085            off DTR and RTS */
00086         usart->cr = (1 << AVR32_USART_CR_RSTRX_OFFSET) |
00087                     (1 << AVR32_USART_CR_RSTTX_OFFSET) |
00088                     (1 << AVR32_USART_CR_RSTSTA_OFFSET) |
00089                     (1 << AVR32_USART_CR_RSTIT_OFFSET) |
00090                     (1 << AVR32_USART_CR_RSTNACK_OFFSET) |
00091                     (1 << AVR32_USART_CR_DTRDIS_OFFSET) |
00092                     (1 << AVR32_USART_CR_RTSDIS_OFFSET);
00093 }
00094 
00095 
00106 static int usart_set_baudrate( volatile struct avr32_usart_t * usart, unsigned int baudrate, long cpu_hz)
00107 {
00108         int cd; /* Clock divider */
00109 
00110         /*
00111          *             ** BAUDRATE CALCULATION **
00112          *
00113          *                 Selected Clock                       Selected Clock
00114          *     baudrate = ----------------   or     baudrate = ----------------
00115          *                             16 x CD                                        8 x CD
00116          *
00117          *       (with 16x oversampling)              (with 8x oversampling)
00118          */
00119 
00120         if ( baudrate < (cpu_hz/16)  ){
00121                 /* Use 8x oversampling */
00122                 usart->mr |= (1<<AVR32_USART_MR_OVER_OFFSET);
00123                 cd = cpu_hz / (8*baudrate);
00124 
00125                 if (cd < 2) {
00126                         return INVALID_ARGUMENT;
00127                 }
00128                 usart->brgr = (cd << AVR32_USART_BRGR_CD_OFFSET);
00129         } else {
00130                 /* Use 16x oversampling */
00131                 usart->mr &= ~(1<<AVR32_USART_MR_OVER_OFFSET);
00132                 cd =  cpu_hz / (16*baudrate);
00133 
00134                 if (cd > 65535) {
00135                   /* Baudrate is too low */
00136                   return INVALID_ARGUMENT;
00137                 }
00138         }
00139         usart->brgr = (cd << AVR32_USART_BRGR_CD_OFFSET);
00140         return SUCCESS;
00141 }
00142 
00143 
00144 
00145 
00146  /*---------------------------------------------------------------------------+
00147  |                                                                            |
00148  |                           INITIALIZATION FUNCTIONS                         |
00149  |                                                                            |
00150  +---------------------------------------------------------------------------*/
00151 
00152 
00153 int usart_init_rs232(volatile struct avr32_usart_t * usart, struct usart_options_t * opt, long cpu_hz)
00154 {
00155         int retval;
00156 
00157         /* Reset the usart and shutdown RX and TX */
00158         usart_reset(usart);
00159 
00160         /* Control input values */
00161         if (opt == 0) /* Null pointer */
00162                 return INVALID_ARGUMENT;
00163         if (opt->charlength < 5 || opt->charlength > 9)
00164                 return INVALID_ARGUMENT;
00165         if (opt->paritytype > 7)
00166                 return INVALID_ARGUMENT;
00167         if (opt->stopbits > 2+255)
00168                 return INVALID_ARGUMENT;
00169         if (opt->channelmode > 3)
00170                 return INVALID_ARGUMENT;
00171 
00172         if ((retval = usart_set_baudrate(usart, opt->baudrate, cpu_hz)) != \
00173              SUCCESS)
00174                 return retval;
00175 
00176         if (opt->charlength == 9) {
00177                 /* Charlength set to 9 bits; MODE9 dominates CHRL */
00178                 usart->mr |= (1<<AVR32_USART_MR_MODE9_OFFSET);
00179         } else {
00180                 /* CHRL gives the charlength( - 5) when USART_MODE9=0 */
00181                 usart->mr |=
00182                         ((opt->charlength-5) << AVR32_USART_MR_CHRL_OFFSET);
00183         }
00184 
00185         usart->mr |= (opt->channelmode << AVR32_USART_MR_CHMODE_OFFSET) |
00186                      (opt->paritytype << AVR32_USART_MR_PAR_OFFSET);
00187 
00188         if (opt->stopbits > 2)
00189         {
00190                 /* Set two stop bits */
00191                 usart->mr |= (2 << AVR32_USART_MR_NBSTOP_OFFSET);
00192                 /* And a timeguard period gives the rest */
00193                 usart->ttgr = (opt->stopbits-2);
00194         }
00195         else
00196                 /* Insert 1, 1.5 or 2 stop bits */
00197                 usart->mr |= (opt->stopbits << AVR32_USART_MR_NBSTOP_OFFSET);
00198 
00199         /* Setup complete; enable communication */
00200         /* Enable input and output */
00201         usart->cr |= (1<<AVR32_USART_CR_TXEN_OFFSET) |
00202                      (1<<AVR32_USART_CR_RXEN_OFFSET);
00203 
00204         return SUCCESS;
00205 }
00206 
00207 /*
00208  * Description: This function is meant to be run after rs232_init().
00209  *              It sets up the usart to use handshaking in its communication.
00210  * Arguments:   *usart:    Base address of the usart
00211  *              *opt:      Options needed to set up RS232 communcation (see usart_options_t)
00212  *                              cpu_hz:    The clock frequency of the usart module
00213  *              software_handshaking:
00214  *                         1= Use software handshaking
00215  *                         0= Use hardware handshaking (requires extra wiring)
00216  *              xon_char:  Character sent from receiver to transmitter when more
00217  *                         data can be sent. (Software handshaking only)
00218  *              xoff_char: Sent from recv. to trans. when recv. buffers are full (sw)
00219  * Returns:     SUCCESS or INVALID_ARGUMENT
00220  */
00221 int usart_init_handshaking(volatile struct avr32_usart_t * usart, struct usart_options_t * opt,
00222                            long cpu_hz, int software_handshaking,
00223                            char xon_char, char xoff_char)
00224 {
00225         int retval;
00226 
00227         /* First: Setup standard RS323 */
00228         if ((retval = usart_init_rs232(usart, opt, cpu_hz)) != SUCCESS)
00229                 return retval;
00230 
00231         if (software_handshaking == 0)
00232         {
00233                 /* Clear previous mode */
00234                 usart-> mr &= ~(0xf << AVR32_USART_MR_MODE_OFFSET);
00235                 /* Hardware handshaking */
00236                 usart-> mr |= (USART_MODE_HW_HSH << AVR32_USART_MR_MODE_OFFSET);
00237         }
00238         else
00239                 return INVALID_ARGUMENT;
00240 
00241         return SUCCESS;
00242 }
00243 
00244 /*
00245  * Description: Setup the usart to use the IrDA protocol
00246  * Arguments:   *usart:      Base address of the usart
00247  *              *opt:        Options needed to set up RS232 communcation (see usart_options_t)
00248  *                              cpu_hz:          The module's clock frequency
00249  *              irda_filter: Counter used to seperate received ones from zeros
00250  * Returns:     SUCCESS or INVALID_ARGUMENT
00251  */
00252 int usart_init_IrDA(volatile struct avr32_usart_t * usart, struct usart_options_t * opt,
00253                     long cpu_hz, unsigned char irda_filter)
00254 {
00255         int retval;
00256 
00257         /* First: Setup standard RS323 */
00258         if ((retval = usart_init_rs232(usart, opt, cpu_hz)) != SUCCESS)
00259                 return retval;
00260 
00261         /* Set IrDA counter */
00262         usart->ifr = irda_filter;
00263 
00264         /* Activate "low-pass filtering" of input */
00265         usart->mr |= (1 << AVR32_USART_MR_FILTER_OFFSET);
00266         return SUCCESS;
00267 }
00268 
00269 /*
00270  * Description: Setup the usart to use the Modem protocol, activating special inputs/outputs
00271  * Arguments:   *usart: Base address of the usart
00272  *              *opt:   Options needed to set up RS232 communcation (see usart_options_t)
00273 *                               cpu_hz:          The module's clock frequency
00274  * Returns:     SUCCESS or INVALID_ARGUMENT
00275  */
00276 int usart_init_modem(volatile struct avr32_usart_t * usart, struct usart_options_t * opt, long cpu_hz)
00277 {
00278         int retval;
00279 
00280         /* First: Setup standard RS323 */
00281         if ((retval = usart_init_rs232(usart, opt, cpu_hz)) != SUCCESS)
00282                 return retval;
00283 
00284         /* Clear previous mode */
00285         usart-> mr &= ~(0xf << AVR32_USART_MR_MODE_OFFSET);
00286         /* Set Modem mode */
00287         usart-> mr |= (USART_MODE_MODEM << AVR32_USART_MR_MODE_OFFSET);
00288         return SUCCESS;
00289 }
00290 
00291 
00292 /*
00293  * Description: Setup the usart to use the RS485 protocol
00294  * Arguments:   *usart: Base address of the usart
00295  *              *opt:   Options needed to set up RS232 communcation (see usart_options_t)
00296  *                              cpu_hz: The module's clock frequency
00297  * Returns:     SUCCESS: mode successfully initialized
00298  *              INVALID_ARGUMENT: one of the arguments are out of valid range
00299  *              USART_MODE_FAULT: mode not initialized with multidrop parity
00300  */
00301 int usart_init_rs485(volatile struct avr32_usart_t * usart, struct usart_options_t * opt, long cpu_hz)
00302 {
00303         int retval;
00304 
00305         /* First: Setup standard RS323 */
00306         if ((retval = usart_init_rs232(usart, opt, cpu_hz)) != SUCCESS)
00307                 return retval;
00308 
00309         /* Clear previous mode */
00310         usart->mr &= ~(0xf << AVR32_USART_MR_MODE_OFFSET);
00311         /* Set Modem mode */
00312         usart->mr |= (USART_MODE_RS485 << AVR32_USART_MR_MODE_OFFSET);
00313         return SUCCESS;
00314 }
00315 
00316 
00317 /*
00318  * Description: Setup the usart to use ISO7816 T=0 or T=1 smartcard protocol
00319  * Arguments:   *usart: Base address of the usart
00320  *              *opt:   Options needed to set up ISO7816 (see iso7816_options_t)
00321  *              t:      Which ISO7816 mode to use (T=0 or T=1)
00322  * Returns:     SUCCESS or INVALID_ARGUMENT
00323  */
00324 int usart_init_iso7816(volatile struct avr32_usart_t * usart, const struct iso7816_options_t * opt, int t, const long cpu_hz)
00325 {
00326         int retval;
00327 
00328         /* Reset the usart and shutdown RX and TX */
00329         usart_reset(usart);
00330 
00331         if (opt == 0)
00332                 /* Null pointer */
00333                 return INVALID_ARGUMENT;
00334 
00335         /* Don't care about charlength, parity or channelmode; All these fields
00336            are ignored in iso7816 mode. 8bit characters and even parity is always
00337            used */
00338 
00339         if (t == 0)
00340         {
00341                 /* Set USART mode to ISO7816, T=0 */
00342                 /* The T=0 protocol always use 2 stop bits */
00343                 usart->mr = (USART_MODE_ISO7816_T0 << AVR32_USART_MR_MODE_OFFSET) |
00344                             (2 << AVR32_USART_MR_NBSTOP_OFFSET) |
00345                             (opt->bit_order << AVR32_USART_MR_MSBF_OFFSET); /* Allow MSBF in T=0 */
00346         }
00347         else if (t == 1)
00348         {
00349                 /* Only LSB first in the T=1 protocol */
00350                 if (opt->bit_order != 0)
00351                         return INVALID_ARGUMENT;
00352                 /* max_iterations field is only used in T=0 mode */
00353                 if (opt->max_iterations != 0)
00354                         return INVALID_ARGUMENT;
00355                 /* Set USART mode to ISO7816, T=1 */
00356                 usart->mr = (USART_MODE_ISO7816_T1 << AVR32_USART_MR_MODE_OFFSET);
00357                 /* The T=1 protocol always use 1 stop bit (no change needed) */
00358         }
00359         else
00360                 return INVALID_ARGUMENT;
00361 
00362         if ((retval = usart_set_baudrate(usart, opt->iso7816_hz, cpu_hz)) != SUCCESS)
00363                 return retval;
00364 
00365         /* Set FIDI register: bit rate = selected clock/FI_DI_ratio/16 */
00366         usart->fidi = opt->fidi_ratio;
00367         /* Set ISO7816 spesific options in the MODE register */
00368         usart->mr |= (opt->inhibit_nack << AVR32_USART_MR_INACK_OFFSET) |
00369                      (opt->dis_suc_nack << AVR32_USART_MR_DSNACK_OFFSET) |
00370                      (opt->max_iterations << AVR32_USART_MR_MAX_ITERATION_OFFSET) |
00371                      (1 << AVR32_USART_MR_CLKO_OFFSET); /* Enable clock output */
00372 
00373         /* Setup complete; enable input */
00374         /* Leave TX disabled for now */
00375         usart->cr |= (1<<AVR32_USART_CR_RXEN_OFFSET);
00376 
00377         return SUCCESS;
00378 }
00379 
00380 
00381 
00382 
00383  /*---------------------------------------------------------------------------+
00384  |                                                                            |
00385  |                     READ AND RESET ERROR STATUS BITS                       |
00386  |                                                                            |
00387  +---------------------------------------------------------------------------*/
00388 
00389 /*
00390  * Description: This function resets the status bits indicating that a parity error,
00391  *              framing error or overrun has occured. The rxbreak bit, indicating
00392  *              a start/end of break condition on the rx-line, is also reset.
00393  * Arguments:   *usart:  Base address of the usart
00394  * Returns:     nothing
00395  */
00396 void usart_reset_status(volatile struct avr32_usart_t * usart)
00397 {
00398         usart->cr |= (1<<AVR32_USART_CR_RSTSTA_OFFSET);
00399 }
00400 
00401 /*
00402  * Description: Checks if a parity error has occured since last status reset
00403  * Arguments:   *usart:  Base address of the usart
00404  * Returns:     1 if a parity error has been detected, otherwise 0
00405  */
00406 int usart_parity_error(volatile struct avr32_usart_t * usart)
00407 {
00408         return ((usart->csr & (1<<AVR32_USART_CSR_PARE_OFFSET)) != 0);
00409 }
00410 
00411 
00412 /*
00413  * Description: Checks if a framing error has occured since last status reset
00414  * Arguments:   *usart:  Base address of the usart
00415  * Returns:     1 if a framing error has been detected, otherwise 0
00416  */
00417 int usart_framing_error(volatile struct avr32_usart_t * usart)
00418 {
00419         return ((usart->csr & (1<<AVR32_USART_CSR_FRAME_OFFSET)) != 0);
00420 }
00421 
00422 
00423 /*
00424  * Description: Checks if a overrun error has occured since last status reset
00425  * Arguments:   *usart:  Base address of the usart
00426  * Returns:     1 if a overrun error has been detected, otherwise 0
00427  */
00428 int usart_overrun_error(volatile struct avr32_usart_t * usart)
00429 {
00430         return ((usart->csr & AVR32_USART_CSR_OVRE_OFFSET)) != 0;
00431 }
00432 
00433 
00434 
00435  /*---------------------------------------------------------------------------+
00436  |                                                                            |
00437  |                         TRANSMIT/RECEIVE FUNCTIONS                         |
00438  |                                                                            |
00439  +---------------------------------------------------------------------------*/
00440 
00441 /*
00442  * Description: While in RS485-mode, receviers only accept data addressed to them.
00443  *              A packet/char with the address tag set has to preceed any data.
00444  *              usart_send_address() is used to address a receiver. This receiver should read
00445  *              all the following data, until an address packet addresses someone else.
00446  * Arguments:   *usart:  Base address of the usart
00447  *              addr: the address of the target device
00448  * Returns:     SUCCESS if the current mode is RS485
00449  *              USART_MODE_FAULT if called while in wrong mode
00450  */
00451 
00452 int usart_send_address(volatile struct avr32_usart_t * usart, int address)
00453 {
00454         /* Check if usart is in multidrop / RS485 mode */
00455         if ( usart_mode_is_multidrop(usart) )
00456         {
00457                 /* Prepare to send an address */
00458                 usart->cr |= (1<<AVR32_USART_CR_SENDA_OFFSET);
00459 
00460                 /* Write the address to TX */
00461                 usart_bw_write_char(usart, address);
00462                 return SUCCESS;
00463         } else {
00464                 return USART_MODE_FAULT;
00465         }
00466 }
00467 
00468 /*
00469  * Description: Wait until the transmitter it ready (potentially forever),
00470  *              then transmit the given character
00471  * Arguments:   *usart:  Base address of the usart
00472  *              c:       The character (up to 9 bits) to transmit
00473  * Returns:     nothing
00474  */
00475 inline void usart_bw_write_char(volatile struct avr32_usart_t * usart, int c)
00476 {
00477         while (usart_write_char(usart, c) != SUCCESS) {
00478         }
00479 
00480         return;
00481 }
00482 
00483 int usart_write_char(volatile struct avr32_usart_t * usart, int c)
00484 {
00485 
00486         if ((usart->csr & (1<<AVR32_USART_CSR_TXRDY_OFFSET)) != 0) {
00487                 usart->thr = c;
00488                 return SUCCESS;
00489         }
00490         else
00491                 return USART_TX_BUSY;
00492 }
00493 
00494 
00495 int usart_read_char(volatile struct avr32_usart_t * usart, int * c)
00496 {
00497         /* Check for errors; Frame, parity and overrun In RS485 mode a parity
00498                 error would mean that we received an address char */
00499         if (usart->csr &
00500                         ((1 << AVR32_USART_CSR_OVRE_OFFSET) |
00501                         (1 << AVR32_USART_CSR_FRAME_OFFSET) |
00502                         (1 << AVR32_USART_CSR_PARE_OFFSET))) {
00503                 return USART_RX_ERROR;
00504         }
00505         /* No error; if we really did receive a char, read it and return SUCCESS */
00506         else if ((usart->csr & (1<<AVR32_USART_CSR_RXRDY_OFFSET)) != 0) {
00507                 *c = (unsigned short)usart->rhr;
00508                 return SUCCESS;
00509         } else {
00510                 return USART_RX_EMPTY;
00511         }
00512 } /* usart_read */
00513 
00514 
00515 int usart_getchar(volatile struct avr32_usart_t * usart)
00516 {
00517         int c, ret;
00518 
00519         while (((ret = usart_read_char(usart, &c)) == USART_RX_EMPTY)) {
00520         }
00521 
00522         if (ret == USART_RX_ERROR)
00523                 return -1;
00524         else
00525                 return c;
00526 }
00527 
00528 
00529 int usart_putchar(volatile struct avr32_usart_t * usart, int c)
00530 {
00531         int timeout = USART_DEFAULT_TIMEOUT;
00532 
00533         if (c == '\n'){
00534           while ((usart_write_char(usart, '\r') != SUCCESS) && (timeout>0) ){
00535             timeout--;
00536           }
00537         
00538           if (timeout == 0)
00539             return -1;
00540           timeout = USART_DEFAULT_TIMEOUT;
00541         }
00542 
00543         while ((usart_write_char(usart, c) != SUCCESS) && ( timeout>0 )){
00544           timeout--;
00545         }
00546         if (timeout == 0)
00547                 return -1;
00548         else
00549                 return 0;
00550 }
00551 

Generated on Wed May 7 16:03:17 2008 for AVR32114 Using the AVR32 LCD Controller by  doxygen 1.5.3-20071008