Nut/OS  4.10.3
API Reference
usartavr.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  * The 9-bit communication had been contributed by Brett Abbott,
00033  * Digital Telemetry Limited.
00034  *
00035  * Dave Smart contributed the synchronous mode support.
00036  */
00037 
00038 /*
00039  * $Log$
00040  * Revision 1.7  2008/08/11 06:59:17  haraldkipp
00041  * BSD types replaced by stdint types (feature request #1282721).
00042  *
00043  * Revision 1.6  2008/04/29 02:28:34  thiagocorrea
00044  * Add configurable DTR pin to AVR USART driver.
00045  *
00046  * Revision 1.5  2007/11/13 20:16:33  thiagocorrea
00047  * Fix a small documentation typo
00048  *
00049  * Revision 1.4  2007/03/08 16:59:01  freckle
00050  * moved Exit Tracer event to end of IRQ
00051  *
00052  * Revision 1.3  2006/08/05 11:53:02  haraldkipp
00053  * Half duplex flow control used the wrong buffer. Many thanks to
00054  * Andrej Taran for fixing this bug.
00055  *
00056  * Revision 1.2  2005/10/07 22:05:00  hwmaier
00057  * Using __AVR_ENHANCED__ macro instead of __AVR_ATmega128__ to support also AT90CAN128 MCU
00058  *
00059  * Revision 1.1  2005/07/26 18:02:40  haraldkipp
00060  * Moved from dev.
00061  *
00062  * Revision 1.10  2005/07/22 08:07:07  freckle
00063  * added experimental improvements to usart driver. see ChangeLog for details
00064  *
00065  * Revision 1.9  2005/02/21 12:38:00  phblum
00066  * Removed tabs and added semicolons after NUTTRACER macros
00067  *
00068  * Revision 1.8  2005/01/24 22:34:46  freckle
00069  * Added new tracer by Phlipp Blum <blum@tik.ee.ethz.ch>
00070  *
00071  * Revision 1.6  2005/01/21 16:49:46  freckle
00072  * Seperated calls to NutEventPostAsync between Threads and IRQs
00073  *
00074  * Revision 1.5  2004/11/12 08:25:51  drsung
00075  * Bugfix in AvrUsartTxEmpty. Thanks to Grzegorz Plonski and Matthias Ringwald.
00076  *
00077  * Revision 1.4  2004/05/26 09:04:17  drsung
00078  * Bugfix in AvrUsartTxStart. Now the correct port and pin are used for half duplex mode...again...
00079  * Thanks to Przemyslaw Rudy.
00080  *
00081  * Revision 1.3  2004/05/16 14:09:06  drsung
00082  * Applied bugfixes for half duplex mode an XON/XOFF handling. Thanks to Damian Slee.
00083  *
00084  * Revision 1.2  2004/04/07 12:58:52  haraldkipp
00085  * Bugfix for half duplex mode
00086  *
00087  * Revision 1.1  2003/12/15 19:25:33  haraldkipp
00088  * New USART driver added
00089  *
00090  */
00091 
00092 #include <sys/atom.h>
00093 #include <sys/event.h>
00094 #include <sys/timer.h>
00095 
00096 #include <dev/irqreg.h>
00097 
00098 #include <dev/usartavr.h>
00099 
00100 #ifdef NUTTRACER
00101 #include <sys/tracer.h>
00102 #endif
00103 
00108 
00109 /* \brief ASCII code for software flow control, starts transmitter. */
00110 #define ASCII_XON   0x11
00111 /* \brief ASCII code for software flow control, stops transmitter. */
00112 #define ASCII_XOFF  0x13
00113 
00114 /* \brief XON transmit pending flag. */
00115 #define XON_PENDING     0x10
00116 /* \brief XOFF transmit pending flag. */
00117 #define XOFF_PENDING    0x20
00118 /* \brief XOFF sent flag. */
00119 #define XOFF_SENT       0x40
00120 /* \brief XOFF received flag. */
00121 #define XOFF_RCVD       0x80
00122 
00123 
00127 static ureg_t rx_errors;
00128 
00132 static ureg_t flow_control;
00133 
00137 static ureg_t tx_aframe;
00138 
00139 #ifdef UART_HDX_BIT
00140         /* define in cfg/modem.h */
00141         #ifdef UART_HDX_FLIP_BIT        /* same as RTS toggle by Windows NT driver */
00142                 #define UART_HDX_TX             cbi
00143                 #define UART_HDX_RX             sbi
00144         #else                                           /* previous usage by Ethernut */
00145                 #define UART_HDX_TX             sbi
00146                 #define UART_HDX_RX             cbi
00147         #endif
00148 #endif
00149 
00150 
00151 #ifdef UART_HDX_BIT
00152 
00158 static ureg_t hdx_control;
00159 #endif
00160 
00161 #ifdef UART_RTS_BIT
00162 
00168 static ureg_t rts_control;
00169 #endif
00170 
00171 #ifdef UART_CTS_BIT
00172 
00178 static ureg_t cts_sense;
00179 #endif
00180 
00181 #ifdef UART_CTS_BIT
00182 
00192 static void AvrUsartCts(void *arg)
00193 {
00194     /* Enable transmit interrupt. */
00195     sbi(UCSRnB, UDRIE);
00196     /* Disable CTS sense interrupt. */
00197     cbi(EIMSK, UART_CTS_BIT);
00198 }
00199 #endif
00200 
00201 #ifdef UART_HDX_BIT
00202 /*
00203  * \brief USARTn transmit complete interrupt handler.
00204  *
00205  * Used with half duplex communication to switch from tranmit to receive
00206  * mode after the last character has been transmitted.
00207  *
00208  * This routine exists only if the hardware configuration defines a
00209  * port bit to switch between receive and transmit mode.
00210  *
00211  * \param arg Pointer to the transmitter ring buffer.
00212  */
00213 static void AvrUsartTxComplete(void *arg)
00214 {
00215     register RINGBUF *rbf = (RINGBUF *) arg;
00216 
00217     /*
00218      * Check if half duplex mode has been enabled and if all characters
00219      * had been sent out.
00220      */
00221     if (hdx_control && rbf->rbf_cnt == 0) {
00222         /* Switch to receiver mode. */
00223         UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
00224     }
00225 }
00226 #endif
00227 
00228 /*
00229  * \brief USARTn transmit data register empty interrupt handler.
00230  *
00231  * \param arg Pointer to the transmitter ring buffer.
00232  */
00233 #ifdef USE_USART
00234 
00235 SIGNAL( SIG_UART_DATA ) {
00236     register RINGBUF *rbf = &dcb_usart.dcb_tx_rbf;
00237 
00238 #else
00239 
00240 static void AvrUsartTxEmpty(void *arg) {
00241     register RINGBUF *rbf = (RINGBUF *) arg;
00242 
00243 #endif
00244 
00245     register uint8_t *cp = rbf->rbf_tail;
00246 
00247 
00248 #ifdef NUTTRACER
00249     TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_ENTER,TRACE_INT_UART_TXEMPTY);
00250 #endif
00251 
00252 #ifndef UART_NO_SW_FLOWCONTROL
00253 
00254     /*
00255      * Process pending software flow controls first.
00256      */
00257     if (flow_control & (XON_PENDING | XOFF_PENDING)) {
00258         if (flow_control & XON_PENDING) {
00259             outb(UDRn, ASCII_XOFF);
00260             flow_control |= XOFF_SENT;
00261         } else {
00262             outb(UDRn, ASCII_XON);
00263             flow_control &= ~XOFF_SENT;
00264         }
00265         flow_control &= ~(XON_PENDING | XOFF_PENDING);
00266 #ifdef NUTTRACER
00267         TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_TXEMPTY);
00268 #endif
00269         return;
00270     }
00271 
00272     if (flow_control & XOFF_RCVD) {
00273         /*
00274          * If XOFF has been received, we disable the transmit interrupts
00275          * and return without sending anything.
00276          */
00277         cbi(UCSRnB, UDRIE);
00278 #ifdef NUTTRACER
00279         TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_TXEMPTY);
00280 #endif
00281         return;
00282         }
00283 #endif /* UART_NO_SW_FLOWCONTROL */
00284 
00285     if (rbf->rbf_cnt) {
00286 
00287 #ifdef UART_CTS_BIT
00288         /*
00289          * If CTS has been disabled, we disable the transmit interrupts
00290          * and return without sending anything.
00291          */
00292         if (cts_sense && bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00293             cbi(UCSRnB, UDRIE);
00294             sbi(EIMSK, UART_CTS_BIT);
00295 #ifdef NUTTRACER
00296             TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_TXEMPTY);
00297 #endif
00298             return;
00299         }
00300 #endif
00301         rbf->rbf_cnt--;
00302 
00303         /*
00304          * The data sheet doesn't exactly tell us, if this bit is retained
00305          * or cleared after the character has been sent out. So we do it
00306          * the save way.
00307          */
00308         if (tx_aframe) {
00309             sbi(UCSRnB, TXB8);
00310         } else {
00311             cbi(UCSRnB, TXB8);
00312         }
00313 
00314         /*
00315          * Start transmission of the next character.
00316          */
00317         outb(UDRn, *cp);
00318 
00319         /*
00320          * Wrap around the buffer pointer if we reached its end.
00321          */
00322         if (++cp == rbf->rbf_last) {
00323             cp = rbf->rbf_start;
00324         }
00325         rbf->rbf_tail = cp;
00326         if (rbf->rbf_cnt == rbf->rbf_lwm) {
00327             NutEventPostFromIrq(&rbf->rbf_que);
00328         }
00329     }
00330 
00331     /*
00332      * Nothing left to transmit, disable interrupt.
00333      */
00334     else {
00335         cbi(UCSRnB, UDRIE);
00336         rbf->rbf_cnt = 0;
00337         NutEventPostFromIrq(&rbf->rbf_que);
00338     }
00339 #ifdef NUTTRACER
00340     TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_TXEMPTY);
00341 #endif
00342 }
00343 
00344 
00345 /*
00346  * \brief USARTn receive complete interrupt handler.
00347  *
00348  *
00349  * \param arg Pointer to the receiver ring buffer.
00350  */
00351 
00352 #ifdef USE_USART
00353 SIGNAL( SIG_UART_RECV ){
00354     register RINGBUF *rbf = &dcb_usart.dcb_rx_rbf;
00355 
00356 #else
00357 
00358 static void AvrUsartRxComplete(void *arg) {
00359     register RINGBUF *rbf = (RINGBUF *) arg;
00360 
00361 #endif
00362 
00363     register size_t cnt;
00364     register uint8_t ch;
00365 
00366 
00367 #ifdef NUTTRACER
00368     TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_ENTER,TRACE_INT_UART_RXCOMPL);
00369 #endif
00370 
00371 #ifdef UART_READMULTIBYTE
00372     register uint8_t postEvent = 0;
00373     do {
00374 #endif
00375 
00376         /*
00377          * We read the received character as early as possible to avoid overflows
00378          * caused by interrupt latency. However, reading the error flags must come
00379          * first, because reading the ATmega128 data register clears the status.
00380          */
00381         rx_errors |= inb(UCSRnA);
00382         ch = inb(UDRn);
00383 
00384 #ifndef UART_NO_SW_FLOWCONTROL
00385         /*
00386          * Handle software handshake. We have to do this before checking the
00387          * buffer, because flow control must work in write-only mode, where
00388          * there is no receive buffer.
00389          */
00390         if (flow_control) {
00391             /* XOFF character disables transmit interrupts. */
00392             if (ch == ASCII_XOFF) {
00393                 cbi(UCSRnB, UDRIE);
00394                 flow_control |= XOFF_RCVD;
00395 #ifdef NUTTRACER
00396                 TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_RXCOMPL);
00397 #endif
00398                 return;
00399             }
00400             /* XON enables transmit interrupts. */
00401             else if (ch == ASCII_XON) {
00402                 sbi(UCSRnB, UDRIE);
00403                 flow_control &= ~XOFF_RCVD;
00404 #ifdef NUTTRACER
00405                 TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_RXCOMPL);
00406 #endif
00407                 return;
00408             }
00409         }
00410 #endif
00411 
00412         /*
00413          * Check buffer overflow.
00414          */
00415         cnt = rbf->rbf_cnt;
00416         if (cnt >= rbf->rbf_siz) {
00417             rx_errors |= _BV(DOR);
00418 #ifdef NUTTRACER
00419             TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_RXCOMPL);
00420 #endif
00421             return;
00422         }
00423 
00424         /* Wake up waiting threads if this is the first byte in the buffer. */
00425         if (cnt++ == 0){
00426 #ifdef UART_READMULTIBYTE
00427             // we do this later, to get the other bytes in time..
00428             postEvent = 1;
00429 #else
00430             NutEventPostFromIrq(&rbf->rbf_que);
00431 #endif
00432         }
00433 
00434 #ifndef UART_NO_SW_FLOWCONTROL
00435 
00436         /*
00437          * Check the high watermark for software handshake. If the number of
00438          * buffered bytes is above this mark, then send XOFF.
00439          */
00440         else if (flow_control) {
00441             if(cnt >= rbf->rbf_hwm) {
00442                 if((flow_control & XOFF_SENT) == 0) {
00443                     if (inb(UCSRnA) & _BV(UDRE)) {
00444                         outb(UDRn, ASCII_XOFF);
00445                         flow_control |= XOFF_SENT;
00446                         flow_control &= ~XOFF_PENDING;
00447                     } else {
00448                         flow_control |= XOFF_PENDING;
00449                     }
00450                 }
00451             }
00452         }
00453 #endif
00454 
00455 
00456 #ifdef UART_RTS_BIT
00457         /*
00458          * Check the high watermark for hardware handshake. If the number of
00459          * buffered bytes is above this mark, then disable RTS.
00460          */
00461         else if (rts_control && cnt >= rbf->rbf_hwm) {
00462             sbi(UART_RTS_PORT, UART_RTS_BIT);
00463         }
00464 #endif
00465 
00466         /*
00467          * Store the character and increment and the ring buffer pointer.
00468          */
00469         *rbf->rbf_head++ = ch;
00470         if (rbf->rbf_head == rbf->rbf_last) {
00471             rbf->rbf_head = rbf->rbf_start;
00472         }
00473 
00474         /* Update the ring buffer counter. */
00475         rbf->rbf_cnt = cnt;
00476 
00477 #ifdef UART_READMULTIBYTE
00478     } while ( inb(UCSRnA) & _BV(RXC) ); // byte in buffer?
00479 
00480     // Eventually post event to wake thread
00481     if (postEvent)
00482         NutEventPostFromIrq(&rbf->rbf_que);
00483 #endif
00484 
00485 #ifdef NUTTRACER
00486     TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_RXCOMPL);
00487 #endif
00488     
00489 }
00490 
00491 
00498 static void AvrUsartEnable(void)
00499 {
00500     NutEnterCritical();
00501 
00502     outb(UCSRnB, _BV(RXCIE) | _BV(UDRIE) | _BV(RXEN) | _BV(TXEN));
00503 
00504 #ifdef UART_HDX_BIT
00505     if (hdx_control) {
00506         /* Enable transmit complete interrupt. */
00507         sbi(UCSRnB, TXCIE);
00508     }
00509 #endif
00510 
00511     NutExitCritical();
00512 }
00513 
00517 static void AvrUsartDisable(void)
00518 {
00519     /*
00520      * Disable USART interrupts.
00521      */
00522     NutEnterCritical();
00523     cbi(UCSRnB, RXCIE);
00524     cbi(UCSRnB, TXCIE);
00525     cbi(UCSRnB, UDRIE);
00526     NutExitCritical();
00527 
00528     /*
00529      * Allow incoming or outgoing character to finish.
00530      */
00531     NutDelay(10);
00532 
00533     /*
00534      * Disable USART transmit and receive.
00535      */
00536     cbi(UCSRnB, RXEN);
00537     cbi(UCSRnB, TXEN);
00538 }
00539 
00548 static uint32_t AvrUsartGetSpeed(void)
00549 {
00550     uint32_t fct;
00551     uint16_t sv = (uint16_t) inb(UBRRnL);
00552 
00553 #ifdef __AVR_ENHANCED__
00554     sv |= ((uint16_t) inb(UBRRnH) << 8);
00555 
00556     /* Synchronous mode. */
00557     if (bit_is_set(UCSRnC, UMSEL)) {
00558         fct = 2UL;
00559     }
00560 
00561     /* Double rate mode. */
00562     else if (bit_is_set(UCSRnA, U2X)) {
00563         fct = 8UL;
00564     }
00565 
00566     /* Normal mode. */
00567     else {
00568         fct = 16UL;
00569     }
00570 #else
00571     fct = 16UL;
00572 #endif
00573 
00574     return NutGetCpuClock() / (fct * ((uint32_t) sv + 1UL));
00575 }
00576 
00587 static int AvrUsartSetSpeed(uint32_t rate)
00588 {
00589     uint16_t sv;
00590 
00591     AvrUsartDisable();
00592 
00593     /*
00594      * Modified Robert Hildebrand's refined calculation.
00595      */
00596 #ifdef __AVR_ENHANCED__
00597     if (bit_is_clear(UCSRnC, UMSEL)) {
00598         if (bit_is_set(UCSRnA, U2X)) {
00599             rate <<= 2;
00600         } else {
00601             rate <<= 3;
00602         }
00603     }
00604 #else
00605     rate <<= 3;
00606 #endif
00607     sv = (uint16_t) ((NutGetCpuClock() / rate + 1UL) / 2UL) - 1;
00608 
00609     outb(UBRRnL, (uint8_t) sv);
00610 #ifdef __AVR_ENHANCED__
00611     outb(UBRRnH, (uint8_t) (sv >> 8));
00612 #endif
00613     AvrUsartEnable();
00614 
00615     return 0;
00616 }
00617 
00626 static uint8_t AvrUsartGetDataBits(void)
00627 {
00628     if (bit_is_set(UCSRnB, UCSZ2)) {
00629         return 9;
00630     }
00631 #ifdef __AVR_ENHANCED__
00632     if (bit_is_set(UCSRnC, UCSZ1)) {
00633         if (bit_is_set(UCSRnC, UCSZ0)) {
00634             return 8;
00635         } else {
00636             return 7;
00637         }
00638     } else if (bit_is_set(UCSRnC, UCSZ0)) {
00639         return 6;
00640     }
00641     return 5;
00642 #else
00643     return 8;
00644 #endif
00645 }
00646 
00655 static int AvrUsartSetDataBits(uint8_t bits)
00656 {
00657     AvrUsartDisable();
00658     cbi(UCSRnB, UCSZ2);
00659 #ifdef __AVR_ENHANCED__
00660     cbi(UCSRnC, UCSZ0);
00661     cbi(UCSRnC, UCSZ1);
00662     switch (bits) {
00663     case 6:
00664         sbi(UCSRnC, UCSZ0);
00665         break;
00666     case 9:
00667         sbi(UCSRnB, UCSZ2);
00668     case 8:
00669         sbi(UCSRnC, UCSZ0);
00670     case 7:
00671         sbi(UCSRnC, UCSZ1);
00672         break;
00673     }
00674 #else
00675     if(bits == 9) {
00676         sbi(UCSRnB, UCSZ2);
00677     }
00678 #endif
00679     AvrUsartEnable();
00680 
00681     /*
00682      * Verify the result.
00683      */
00684     if (AvrUsartGetDataBits() != bits) {
00685         return -1;
00686     }
00687     return 0;
00688 }
00689 
00698 static uint8_t AvrUsartGetParity(void)
00699 {
00700 #ifdef __AVR_ENHANCED__
00701     if (bit_is_set(UCSRnC, UPM1)) {
00702         if (bit_is_set(UCSRnC, UPM0)) {
00703             return 1;
00704         } else {
00705             return 2;
00706         }
00707     }
00708 #endif
00709     return 0;
00710 }
00711 
00722 static int AvrUsartSetParity(uint8_t mode)
00723 {
00724 #ifdef __AVR_ENHANCED__
00725     AvrUsartDisable();
00726     switch (mode) {
00727     case 0:
00728         cbi(UCSRnC, UPM0);
00729         cbi(UCSRnC, UPM1);
00730         break;
00731     case 1:
00732         sbi(UCSRnC, UPM0);
00733         sbi(UCSRnC, UPM1);
00734         break;
00735     case 2:
00736         cbi(UCSRnC, UPM0);
00737         sbi(UCSRnC, UPM1);
00738         break;
00739     }
00740     AvrUsartEnable();
00741 #endif
00742 
00743     /*
00744      * Verify the result.
00745      */
00746     if (AvrUsartGetParity() != mode) {
00747         return -1;
00748     }
00749     return 0;
00750 }
00751 
00760 static uint8_t AvrUsartGetStopBits(void)
00761 {
00762 #ifdef __AVR_ENHANCED__
00763     if (bit_is_set(UCSRnC, USBS)) {
00764         return 2;
00765     }
00766 #endif
00767     return 1;
00768 }
00769 
00778 static int AvrUsartSetStopBits(uint8_t bits)
00779 {
00780 #ifdef __AVR_ENHANCED__
00781     AvrUsartDisable();
00782     if (bits == 1) {
00783         cbi(UCSRnC, USBS);
00784     } else if (bits == 2) {
00785         sbi(UCSRnC, USBS);
00786     }
00787     AvrUsartEnable();
00788 #endif
00789 
00790     /*
00791      * Verify the result.
00792      */
00793     if (AvrUsartGetStopBits() != bits) {
00794         return -1;
00795     }
00796     return 0;
00797 }
00798 
00804 static uint32_t AvrUsartGetStatus(void)
00805 {
00806     uint32_t rc = 0;
00807 
00808     /*
00809      * Set receiver error flags.
00810      */
00811     if ((rx_errors & _BV(FE)) != 0) {
00812         rc |= UART_FRAMINGERROR;
00813     }
00814     if ((rx_errors & _BV(DOR)) != 0) {
00815         rc |= UART_OVERRUNERROR;
00816     }
00817 #ifdef __AVR_ENHANCED__
00818     if ((rx_errors & _BV(UPE)) != 0) {
00819         rc |= UART_PARITYERROR;
00820     }
00821 #endif
00822 
00823     /*
00824      * Determine software handshake status. The flow control status may
00825      * change during interrupt, but this doesn't really hurt us.
00826      */
00827     if (flow_control) {
00828         if (flow_control & XOFF_SENT) {
00829             rc |= UART_RXDISABLED;
00830         }
00831         if (flow_control & XOFF_RCVD) {
00832             rc |= UART_TXDISABLED;
00833         }
00834     }
00835 #ifdef UART_RTS_BIT
00836     /*
00837      * Determine hardware handshake control status.
00838      */
00839     if (bit_is_set(UART_RTS_PORT, UART_RTS_BIT)) {
00840         rc |= UART_RTSDISABLED;
00841         if (rts_control) {
00842             rc |= UART_TXDISABLED;
00843         }
00844     } else {
00845         rc |= UART_RTSENABLED;
00846     }
00847 #endif
00848 
00849 #ifdef UART_CTS_BIT
00850     /*
00851      * Determine hardware handshake sense status.
00852      */
00853     if (bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00854         rc |= UART_CTSDISABLED;
00855         if (cts_sense) {
00856             rc |= UART_RXDISABLED;
00857         }
00858     } else {
00859         rc |= UART_CTSENABLED;
00860     }
00861 #endif
00862 
00863 #ifdef UART_DTR_BIT
00864         /*
00865         * Determine DTS status.
00866         */
00867         if ( bit_is_set( UART_DTR_PORT, UART_DTR_BIT ) ) {
00868                 rc |= UART_DTRENABLED;
00869         } else {
00870                 rc |= UART_DTRDISABLED;
00871         }
00872 #endif
00873 
00874     /*
00875      * If transmitter and receiver haven't been detected disabled by any
00876      * of the checks above, then they are probably enabled.
00877      */
00878     if ((rc & UART_RXDISABLED) == 0) {
00879         rc |= UART_RXENABLED;
00880     }
00881     if ((rc & UART_TXDISABLED) == 0) {
00882         rc |= UART_TXENABLED;
00883     }
00884 
00885     /*
00886      * Process multidrop setting.
00887      */
00888     if (tx_aframe) {
00889         rc |= UART_TXADDRFRAME;
00890     } else {
00891         rc |= UART_TXNORMFRAME;
00892     }
00893 
00894 #ifdef __AVR_ENHANCED__
00895     if (bit_is_set(UCSRnA, MPCM)) {
00896         rc |= UART_RXADDRFRAME;
00897     } else {
00898         rc |= UART_RXNORMFRAME;
00899     }
00900 #else
00901     rc |= UART_RXNORMFRAME;
00902 #endif
00903 
00904     return rc;
00905 }
00906 
00914 static int AvrUsartSetStatus(uint32_t flags)
00915 {
00916     /*
00917      * Process software handshake control.
00918      */
00919     if (flow_control) {
00920 
00921         /* Access to the flow control status must be atomic. */
00922         NutEnterCritical();
00923 
00924         /*
00925          * Enabling or disabling the receiver means to behave like
00926          * having sent a XON or XOFF character resp.
00927          */
00928         if (flags & UART_RXENABLED) {
00929             flow_control &= ~XOFF_SENT;
00930         } else if (flags & UART_RXDISABLED) {
00931             flow_control |= XOFF_SENT;
00932         }
00933 
00934         /*
00935          * Enabling or disabling the transmitter means to behave like
00936          * having received a XON or XOFF character resp.
00937          */
00938         if (flags & UART_TXENABLED) {
00939             flow_control &= ~XOFF_RCVD;
00940         } else if (flags & UART_TXDISABLED) {
00941             flow_control |= XOFF_RCVD;
00942         }
00943         NutExitCritical();
00944     }
00945 #ifdef UART_RTS_BIT
00946     /*
00947      * Process hardware handshake control.
00948      */
00949     if (rts_control) {
00950         if (flags & UART_RXDISABLED) {
00951             sbi(UART_RTS_PORT, UART_RTS_BIT);
00952         }
00953         if (flags & UART_RXENABLED) {
00954             cbi(UART_RTS_PORT, UART_RTS_BIT);
00955         }
00956     }
00957     if (flags & UART_RTSDISABLED) {
00958         sbi(UART_RTS_PORT, UART_RTS_BIT);
00959     }
00960     if (flags & UART_RTSENABLED) {
00961         cbi(UART_RTS_PORT, UART_RTS_BIT);
00962     }
00963 #endif
00964 
00965 #ifdef UART_DTR_BIT
00966         if ( flags & UART_DTRDISABLED ) {
00967                 sbi(UART_DTR_DDR, UART_DTR_BIT);
00968                 sbi(UART_DTR_PORT, UART_DTR_BIT);
00969         }
00970         if ( flags & UART_DTRENABLED ) {
00971                 sbi(UART_DTR_DDR, UART_DTR_BIT);
00972                 cbi(UART_DTR_PORT, UART_DTR_BIT);
00973         }
00974 #endif
00975 
00976     /*
00977      * Process multidrop setting.
00978      */
00979     if (flags & UART_TXADDRFRAME) {
00980         tx_aframe = 1;
00981     }
00982     if (flags & UART_TXNORMFRAME) {
00983         tx_aframe = 0;
00984     }
00985 #ifdef __AVR_ENHANCED__
00986     if (flags & UART_RXADDRFRAME) {
00987         sbi(UCSRnA, MPCM);
00988     }
00989     if (flags & UART_RXNORMFRAME) {
00990         cbi(UCSRnA, MPCM);
00991     }
00992 #endif
00993 
00994     /*
00995      * Clear UART receive errors.
00996      */
00997     if (flags & UART_FRAMINGERROR) {
00998         rx_errors &= ~_BV(FE);
00999     }
01000     if (flags & UART_OVERRUNERROR) {
01001         rx_errors &= ~_BV(DOR);
01002     }
01003 #ifdef __AVR_ENHANCED__
01004     if (flags & UART_PARITYERROR) {
01005         rx_errors &= ~_BV(UPE);
01006     }
01007 #endif
01008 
01009     /*
01010      * Verify the result.
01011      */
01012     if ((AvrUsartGetStatus() & ~UART_ERRORS) != flags) {
01013         return -1;
01014     }
01015     return 0;
01016 }
01017 
01027 static uint8_t AvrUsartGetClockMode(void)
01028 {
01029     uint8_t rc = 0;
01030 
01031 #ifdef __AVR_ENHANCED__
01032     if (bit_is_set(UCSRnC, UMSEL)) {
01033         rc |= UART_SYNC;
01034         if (bit_is_set(DDRE, 2)) {
01035             rc |= UART_MASTER;
01036         }
01037         if (bit_is_set(UCSRnC, UCPOL)) {
01038             rc |= UART_NCLOCK;
01039         }
01040     } else if (bit_is_set(UCSRnA, U2X)) {
01041         rc |= UART_HIGHSPEED;
01042     }
01043 #endif
01044 
01045     return rc;
01046 }
01047 
01059 static int AvrUsartSetClockMode(uint8_t mode)
01060 {
01061 #ifdef __AVR_ENHANCED__
01062     AvrUsartDisable();
01063 
01064     /*
01065      * Handle synchronous mode.
01066      */
01067     if (mode & UART_SYNC) {
01068         if (mode & UART_MASTER) {
01069             /* Enable master mode. */
01070             sbi(DDRE, 2);
01071         } else {
01072             /* Disable master mode. */
01073             cbi(DDRE, 2);
01074         }
01075         if (mode & UART_NCLOCK) {
01076             /* Enable negated clock. */
01077             sbi(UCSRnC, UCPOL);
01078         } else {
01079             /* Disable negated clock. */
01080             cbi(UCSRnC, UCPOL);
01081         }
01082         /* Disable high speed. */
01083         cbi(UCSRnA, U2X);
01084         /* Enable synchronous mode. */
01085         sbi(UCSRnC, UMSEL);
01086     }
01087 
01088     /*
01089      * Handle asynchronous mode.
01090      */
01091     else {
01092         if (mode & UART_HIGHSPEED) {
01093             /* Enable high speed. */
01094             sbi(UCSRnA, U2X);
01095         } else {
01096             /* Disable high speed. */
01097             cbi(UCSRnA, U2X);
01098         }
01099         /* Disable negated clock. */
01100         cbi(UCSRnC, UCPOL);
01101         /* Disable synchronous mode. */
01102         cbi(UCSRnC, UMSEL);
01103     }
01104     AvrUsartEnable();
01105 #endif
01106 
01107     /*
01108      * Verify the result.
01109      */
01110     if (AvrUsartGetClockMode() != mode) {
01111         return -1;
01112     }
01113     return 0;
01114 }
01115 
01124 static uint32_t AvrUsartGetFlowControl(void)
01125 {
01126     uint32_t rc = 0;
01127 
01128     if (flow_control) {
01129         rc |= USART_MF_XONXOFF;
01130     } else {
01131         rc &= ~USART_MF_XONXOFF;
01132     }
01133 
01134 #ifdef UART_RTS_BIT
01135     if (rts_control) {
01136         rc |= USART_MF_RTSCONTROL;
01137     } else {
01138         rc &= ~USART_MF_RTSCONTROL;
01139     }
01140 #endif
01141 
01142 #ifdef UART_CTS_BIT
01143     if (cts_sense) {
01144         rc |= USART_MF_CTSSENSE;
01145     } else {
01146         rc &= ~USART_MF_CTSSENSE;
01147     }
01148 #endif
01149 
01150 #ifdef UART_HDX_BIT
01151     if (hdx_control) {
01152         rc |= USART_MF_HALFDUPLEX;
01153     } else {
01154         rc &= ~USART_MF_HALFDUPLEX;
01155     }
01156 #endif
01157 
01158     return rc;
01159 }
01160 
01171 static int AvrUsartSetFlowControl(uint32_t flags)
01172 {
01173     /*
01174      * Set software handshake mode.
01175      */
01176     if (flags & USART_MF_XONXOFF) {
01177         if(flow_control == 0) {
01178             NutEnterCritical();
01179             flow_control = 1 | XOFF_SENT;  /* force XON to be sent on next read */
01180             NutExitCritical();
01181         }
01182     } else {
01183         NutEnterCritical();
01184         flow_control = 0;
01185         NutExitCritical();
01186     }
01187 
01188 #ifdef UART_RTS_BIT
01189     /*
01190      * Set RTS control mode.
01191      */
01192     if (flags & USART_MF_RTSCONTROL) {
01193         sbi(UART_RTS_PORT, UART_RTS_BIT);
01194         sbi(UART_RTS_DDR, UART_RTS_BIT);
01195         rts_control = 1;
01196     } else if (rts_control) {
01197         rts_control = 0;
01198         cbi(UART_RTS_DDR, UART_RTS_BIT);
01199     }
01200 #endif
01201 
01202 #ifdef UART_CTS_BIT
01203     /*
01204      * Set CTS sense mode.
01205      */
01206     if (flags & USART_MF_CTSSENSE) {
01207         /* Register CTS sense interrupt. */
01208         if (NutRegisterIrqHandler(&UART_CTS_SIGNAL, AvrUsartCts, 0)) {
01209             return -1;
01210         }
01211         sbi(UART_CTS_PORT, UART_CTS_BIT);
01212         cbi(UART_CTS_DDR, UART_CTS_BIT);
01213         cts_sense = 1;
01214     } else if (cts_sense) {
01215         cts_sense = 0;
01216         /* Deregister CTS sense interrupt. */
01217         NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0);
01218         cbi(UART_CTS_DDR, UART_CTS_BIT);
01219     }
01220 #endif
01221 
01222 #ifdef UART_HDX_BIT
01223     /*
01224      * Set half duplex mode.
01225      */
01226     if (flags & USART_MF_HALFDUPLEX) {
01227         /* Register transmit complete interrupt. */
01228         if (NutRegisterIrqHandler(&sig_UART_TRANS, AvrUsartTxComplete, &dcb_usart.dcb_tx_rbf)) {
01229             return -1;
01230         }
01231         /* Initially enable the receiver. */
01232         UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
01233         sbi(UART_HDX_DDR, UART_HDX_BIT);
01234         hdx_control = 1;
01235         /* Enable transmit complete interrupt. */
01236         sbi(UCSRnB, TXCIE);
01237     } else if (hdx_control) {
01238         hdx_control = 0;
01239         /* disable transmit complete interrupt */
01240         cbi(UCSRnB, TXCIE);
01241         /* Deregister transmit complete interrupt. */
01242         NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
01243         cbi(UART_HDX_DDR, UART_HDX_BIT);
01244     }
01245 #endif
01246 
01247     /*
01248      * Verify the result.
01249      */
01250     if (AvrUsartGetFlowControl() != flags) {
01251         return -1;
01252     }
01253     return 0;
01254 }
01255 
01263 static void AvrUsartTxStart(void)
01264 {
01265 #ifdef UART_HDX_BIT
01266     if (hdx_control) {
01267         /* Enable half duplex transmitter. */
01268         UART_HDX_TX(UART_HDX_PORT, UART_HDX_BIT);
01269     }
01270 #endif
01271     /* Enable transmit interrupts. */
01272     sbi(UCSRnB, UDRIE);
01273 }
01274 
01283 static void AvrUsartRxStart(void)
01284 {
01285     /*
01286      * Do any required software flow control.
01287      */
01288     if (flow_control && (flow_control & XOFF_SENT) != 0) {
01289         NutEnterCritical();
01290         if (inb(UCSRnA) & _BV(UDRE)) {
01291             outb(UDRn, ASCII_XON);
01292             flow_control &= ~XON_PENDING;
01293         } else {
01294             flow_control |= XON_PENDING;
01295         }
01296         flow_control &= ~(XOFF_SENT | XOFF_PENDING);
01297         NutExitCritical();
01298     }
01299 #ifdef UART_RTS_BIT
01300     if (rts_control) {
01301         /* Enable RTS. */
01302         cbi(UART_RTS_PORT, UART_RTS_BIT);
01303     }
01304 #endif
01305 }
01306 
01307 /*
01308  * \brief Initialize the USART hardware driver.
01309  *
01310  * This function is called during device registration by the upper level
01311  * USART driver through the USARTDCB jump table.
01312  *
01313  * \return 0 on success, -1 otherwise.
01314  */
01315 static int AvrUsartInit(void)
01316 {
01317 #ifndef USE_USART
01318     /*
01319      * Register receive and transmit interrupts.
01320      */
01321     if (NutRegisterIrqHandler(&sig_UART_RECV, AvrUsartRxComplete, &dcb_usart.dcb_rx_rbf))
01322         return -1;
01323     if (NutRegisterIrqHandler(&sig_UART_DATA, AvrUsartTxEmpty, &dcb_usart.dcb_tx_rbf)) {
01324         NutRegisterIrqHandler(&sig_UART_RECV, 0, 0);
01325         return -1;
01326     }
01327 #endif
01328 
01329 #ifdef UART_RTS_BIT
01330         sbi(UART_RTS_DDR, UART_RTS_BIT);
01331 #endif
01332 
01333 #ifdef UART_DTR_BIT
01334         sbi(UART_DTR_DDR, UART_DTR_BIT);
01335 #endif
01336 
01337     return 0;
01338 }
01339 
01340 /*
01341  * \brief Deinitialize the USART hardware driver.
01342  *
01343  * This function is called during device deregistration by the upper
01344  * level USART driver through the USARTDCB jump table.
01345  *
01346  * \return 0 on success, -1 otherwise.
01347  */
01348 static int AvrUsartDeinit(void)
01349 {
01350 
01351 #ifndef USE_USART
01352     /* Deregister receive and transmit interrupts. */
01353     NutRegisterIrqHandler(&sig_UART_RECV, 0, 0);
01354     NutRegisterIrqHandler(&sig_UART_DATA, 0, 0);
01355 #endif
01356 
01357     /*
01358      * Disabling flow control shouldn't be required here, because it's up
01359      * to the upper level to do this on the last close or during
01360      * deregistration.
01361      */
01362 #ifdef UART_HDX_BIT
01363     /* Deregister transmit complete interrupt. */
01364     if (hdx_control) {
01365         hdx_control = 0;
01366         NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
01367     }
01368 #endif
01369 
01370 #ifdef UART_CTS_BIT
01371     if (cts_sense) {
01372         cts_sense = 0;
01373         cbi(UART_CTS_DDR, UART_CTS_BIT);
01374         /* Deregister CTS sense interrupt. */
01375         NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0);
01376     }
01377 #endif
01378 
01379 #ifdef UART_RTS_BIT
01380     if (rts_control) {
01381         rts_control = 0;
01382         cbi(UART_RTS_DDR, UART_RTS_BIT);
01383     }
01384 #endif
01385 
01386 #ifdef UART_DTR_BIT
01387         cbi(UART_DTR_DDR, UART_DTR_BIT);
01388 #endif
01389 
01390     return 0;
01391 }
01392