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

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