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

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