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

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/