usart.c

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

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