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

Generated on Thu May 10 14:17:56 2007 for AVR321000 Communication with the AVR32 USART by  doxygen 1.5.1