usartat91.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2001-2006 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: usartat91.c,v $
00040  * Revision 1.7  2007/10/04 20:05:51  olereinhardt
00041  * Support for SAM7S256 added
00042  *
00043  * Revision 1.6  2006/08/31 19:01:44  haraldkipp
00044  * Using the processor clock for baud rate calculations failed
00045  * on the SAM9, if the master clock is further divided. This
00046  * had been fixed.
00047  *
00048  * Revision 1.5  2006/08/05 11:54:06  haraldkipp
00049  * Special register functions should not be based on MCU definitions but on
00050  * register definitions.
00051  *
00052  * Revision 1.4  2006/07/05 07:55:23  haraldkipp
00053  * Daidai's support for AT91SAM7X added.
00054  *
00055  * Revision 1.3  2006/06/28 17:18:40  haraldkipp
00056  * Temporarly exclude AT91R40008 specific register settings from building
00057  * for AT91SAM7X.
00058  *
00059  * Revision 1.2  2006/01/05 16:47:32  haraldkipp
00060  * Baudrate calculation is now based on NutGetCpuClock().
00061  *
00062  * Revision 1.1  2005/11/20 14:40:28  haraldkipp
00063  * Added interrupt driven UART driver for AT91.
00064  *
00065  */
00066 
00067 #include <cfg/clock.h>
00068 
00069 #include <sys/atom.h>
00070 #include <sys/event.h>
00071 #include <sys/timer.h>
00072 
00073 #include <dev/irqreg.h>
00074 
00075 #include <dev/usartat91.h>
00076 
00081 
00082 /* \brief ASCII code for software flow control, starts transmitter. */
00083 #define ASCII_XON   0x11
00084 /* \brief ASCII code for software flow control, stops transmitter. */
00085 #define ASCII_XOFF  0x13
00086 
00087 /* \brief XON transmit pending flag. */
00088 #define XON_PENDING     0x10
00089 /* \brief XOFF transmit pending flag. */
00090 #define XOFF_PENDING    0x20
00091 /* \brief XOFF sent flag. */
00092 #define XOFF_SENT       0x40
00093 /* \brief XOFF received flag. */
00094 #define XOFF_RCVD       0x80
00095 
00096 
00100 static ureg_t rx_errors;
00101 
00105 static ureg_t flow_control;
00106 
00110 static ureg_t tx_aframe;
00111 
00112 #ifdef UART_HDX_BIT
00113     /* define in cfg/modem.h */
00114     #ifdef UART_HDX_FLIP_BIT    /* same as RTS toggle by Windows NT driver */
00115         #define UART_HDX_TX     cbi
00116         #define UART_HDX_RX     sbi
00117     #else                       /* previous usage by Ethernut */
00118         #define UART_HDX_TX     sbi
00119         #define UART_HDX_RX     cbi
00120     #endif
00121 #endif
00122 
00123 
00124 #ifdef UART_HDX_BIT
00125 
00131 static ureg_t hdx_control;
00132 #endif
00133 
00134 #ifdef UART_RTS_BIT
00135 
00141 static ureg_t rts_control;
00142 #endif
00143 
00144 #ifdef UART_CTS_BIT
00145 
00151 static ureg_t cts_sense;
00152 #endif
00153 
00154 #ifdef UART_CTS_BIT
00155 
00165 static void At91UsartCts(void *arg)
00166 {
00167     /* Enable transmit interrupt. */
00168     //sbi(UCSRnB, UDRIE);
00169     /* Disable CTS sense interrupt. */
00170     //cbi(EIMSK, UART_CTS_BIT);
00171 }
00172 #endif
00173 
00174 #ifdef UART_HDX_BIT
00175 /*
00176  * \brief USARTn transmitter empty interrupt handler.
00177  *
00178  * Used with half duplex communication to switch from tranmit to receive
00179  * mode after the last character has been transmitted.
00180  *
00181  * This routine exists only if the hardware configuration defines a
00182  * port bit to switch between receive and transmit mode.
00183  *
00184  * \param arg Pointer to the transmitter ring buffer.
00185  */
00186 static void At91UsartTxEmpty(RINGBUF *rbf)
00187 {
00188     /*
00189      * Check if half duplex mode has been enabled and if all characters
00190      * had been sent out.
00191      */
00192     if (hdx_control && rbf->rbf_cnt == 0) {
00193         /* Switch to receiver mode. */
00194         UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
00195     }
00196 }
00197 #endif
00198 
00199 /*
00200  * \brief USARTn transmitter ready interrupt handler.
00201  *
00202  * \param rbf Pointer to the transmitter ring buffer.
00203  */
00204 static void At91UsartTxReady(RINGBUF *rbf) 
00205 {
00206     register u_char *cp = rbf->rbf_tail;
00207 
00208     /*
00209      * Process pending software flow controls first.
00210      */
00211     if (flow_control & (XON_PENDING | XOFF_PENDING)) {
00212         if (flow_control & XON_PENDING) {
00213             outr(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00214             flow_control |= XOFF_SENT;
00215         } else {
00216             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
00217             flow_control &= ~XOFF_SENT;
00218         }
00219         flow_control &= ~(XON_PENDING | XOFF_PENDING);
00220         return;
00221     }
00222 
00223     if (flow_control & XOFF_RCVD) {
00224         /*
00225          * If XOFF has been received, we disable the transmit interrupts
00226          * and return without sending anything.
00227          */
00228         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00229         return;
00230     }
00231 
00232     if (rbf->rbf_cnt) {
00233 
00234 #ifdef UART_CTS_BIT
00235         /*
00236          * If CTS has been disabled, we disable the transmit interrupts
00237          * and return without sending anything.
00238          */
00239         if (cts_sense && bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00240             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00241             sbi(EIMSK, UART_CTS_BIT);
00242             return;
00243         }
00244 #endif
00245         rbf->rbf_cnt--;
00246 
00247         /*
00248          * Send address in multidrop mode.
00249          */
00250         if (tx_aframe) {
00251             outr(USARTn_BASE + US_CR_OFF, US_SENDA);
00252         }
00253 
00254         /*
00255          * Start transmission of the next character.
00256          */
00257         outr(USARTn_BASE + US_THR_OFF, *cp);
00258 
00259         /*
00260          * Wrap around the buffer pointer if we reached its end.
00261          */
00262         if (++cp == rbf->rbf_last) {
00263             cp = rbf->rbf_start;
00264         }
00265         rbf->rbf_tail = cp;
00266         if (rbf->rbf_cnt == rbf->rbf_lwm) {
00267             NutEventPostFromIrq(&rbf->rbf_que);
00268         }
00269     }
00270 
00271     /*
00272      * Nothing left to transmit, disable interrupt.
00273      */
00274     else {
00275         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00276         rbf->rbf_cnt = 0;
00277         NutEventPostFromIrq(&rbf->rbf_que);
00278     }
00279 }
00280 
00281 
00282 /*
00283  * \brief USARTn receiver ready interrupt handler.
00284  *
00285  *
00286  * \param rbf Pointer to the receiver ring buffer.
00287  */
00288 
00289 static void At91UsartRxReady(RINGBUF *rbf) 
00290 {
00291     register size_t cnt;
00292     register u_char ch;
00293 
00294     /*
00295      * We read the received character as early as possible to avoid overflows
00296      * caused by interrupt latency.
00297      */
00298     ch = inb(USARTn_BASE + US_RHR_OFF);
00299 
00300     /* Collect receiver errors. */
00301     rx_errors |= inr(USARTn_BASE + US_CSR_OFF) & (US_OVRE | US_FRAME | US_PARE);
00302 
00303     /*
00304      * Handle software handshake. We have to do this before checking the
00305      * buffer, because flow control must work in write-only mode, where
00306      * there is no receive buffer.
00307      */
00308     if (flow_control) {
00309         /* XOFF character disables transmit interrupts. */
00310         if (ch == ASCII_XOFF) {
00311             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00312             flow_control |= XOFF_RCVD;
00313             return;
00314         }
00315         /* XON enables transmit interrupts. */
00316         else if (ch == ASCII_XON) {
00317             outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00318             flow_control &= ~XOFF_RCVD;
00319             return;
00320         }
00321     }
00322 
00323     /*
00324      * Check buffer overflow.
00325      */
00326     cnt = rbf->rbf_cnt;
00327     if (cnt >= rbf->rbf_siz) {
00328         rx_errors |= US_OVRE;
00329         return;
00330     }
00331 
00332     /* Wake up waiting threads if this is the first byte in the buffer. */
00333     if (cnt++ == 0){
00334         NutEventPostFromIrq(&rbf->rbf_que);
00335     }
00336 
00337     /*
00338      * Check the high watermark for software handshake. If the number of
00339      * buffered bytes is above this mark, then send XOFF.
00340      */
00341     else if (flow_control) {
00342         if(cnt >= rbf->rbf_hwm) {
00343             if((flow_control & XOFF_SENT) == 0) {
00344                 if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00345                     outb(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00346                     flow_control |= XOFF_SENT;
00347                     flow_control &= ~XOFF_PENDING;
00348                 } else {
00349                     flow_control |= XOFF_PENDING;
00350                 }
00351             }
00352         }
00353     }
00354 
00355 #ifdef UART_RTS_BIT
00356     /*
00357      * Check the high watermark for hardware handshake. If the number of
00358      * buffered bytes is above this mark, then disable RTS.
00359      */
00360     else if (rts_control && cnt >= rbf->rbf_hwm) {
00361         sbi(UART_RTS_PORT, UART_RTS_BIT);
00362     }
00363 #endif
00364 
00365     /*
00366      * Store the character and increment and the ring buffer pointer.
00367      */
00368     *rbf->rbf_head++ = ch;
00369     if (rbf->rbf_head == rbf->rbf_last) {
00370         rbf->rbf_head = rbf->rbf_start;
00371     }
00372 
00373     /* Update the ring buffer counter. */
00374     rbf->rbf_cnt = cnt;
00375 }
00376 
00382 static void At91UsartInterrupt(void *arg)
00383 {
00384     USARTDCB *dcb = (USARTDCB *)arg;
00385     ureg_t csr = inr(USARTn_BASE + US_CSR_OFF);
00386 
00387     if (csr & US_RXRDY) {
00388         At91UsartRxReady(&dcb->dcb_rx_rbf);
00389     }
00390     if (csr & US_TXRDY) {
00391         At91UsartTxReady(&dcb->dcb_tx_rbf);
00392     }
00393 
00394 #ifdef UART_HDX_BIT
00395     if (csr & US_TXEMPTY) {
00396         At91UsartTxEmpty(&dcb->dcb_tx_rbf);
00397     }
00398 #endif /*  UART_HDX_BIT */
00399 }
00400 
00407 static void At91UsartEnable(void)
00408 {
00409     NutEnterCritical();
00410 
00411     /* Enable UART receiver and transmitter. */
00412     outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
00413 
00414     /* Enable UART receiver and transmitter interrupts. */
00415     outr(USARTn_BASE + US_IER_OFF, US_RXRDY | US_TXRDY);
00416     NutIrqEnable(&SIG_UART);
00417 
00418 #ifdef UART_HDX_BIT
00419     if (hdx_control) {
00420         /* Enable transmit complete interrupt. */
00421         sbi(UCSRnB, TXCIE);
00422     }
00423 #endif
00424 
00425     NutExitCritical();
00426 }
00427 
00431 static void At91UsartDisable(void)
00432 {
00433     /*
00434      * Disable USART interrupts.
00435      */
00436     NutEnterCritical();
00437     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
00438     NutExitCritical();
00439 
00440     /*
00441      * Allow incoming or outgoing character to finish.
00442      */
00443     NutDelay(10);
00444 
00445     /*
00446      * Disable USART transmit and receive.
00447      */
00448     outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXDIS);
00449 }
00450 
00459 static u_long At91UsartGetSpeed(void)
00460 {
00461     ureg_t cs = inr(USARTn_BASE + US_MR_OFF);
00462     u_long clk;
00463 
00464 #if defined(AT91_PLL_MAINCK)
00465     clk = At91GetMasterClock();
00466 #else
00467     clk = NutGetCpuClock();
00468 #endif
00469     if ((cs & US_CLKS) == US_CLKS_MCK8) {
00470         clk /= 8;
00471     }
00472     else if ((cs & US_CLKS) != US_CLKS_MCK) {
00473         clk = 0;
00474     }
00475     return clk / (16UL * (inr(USARTn_BASE + US_BRGR_OFF) & 0xFFFF));
00476 }
00477 
00488 static int At91UsartSetSpeed(u_long rate)
00489 {
00490     At91UsartDisable();
00491 #if defined(AT91_PLL_MAINCK)
00492     outr(USARTn_BASE + US_BRGR_OFF, (At91GetMasterClock() / (8 * (rate)) + 1) / 2);
00493 #else
00494     outr(USARTn_BASE + US_BRGR_OFF, (NutGetCpuClock() / (8 * (rate)) + 1) / 2);
00495 #endif
00496     At91UsartEnable();
00497 
00498     return 0;
00499 }
00500 
00509 static u_char At91UsartGetDataBits(void)
00510 {
00511     ureg_t val = inr(USARTn_BASE + US_MR_OFF);
00512 
00513     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00514         val = 9;
00515     }
00516     else {
00517         val &= US_CHRL;
00518         if (val == US_CHRL_5) {
00519             val = 5;
00520         }
00521         else if (val == US_CHRL_6) {
00522             val = 6;
00523         }
00524         else if (val == US_CHRL_7) {
00525             val = 7;
00526         }
00527         else {
00528             val = 8;
00529         }
00530     }
00531     return (u_char)val;
00532 }
00533 
00542 static int At91UsartSetDataBits(u_char bits)
00543 {
00544     ureg_t val = inr(USARTn_BASE + US_MR_OFF);
00545 
00546     if (bits == 9) {
00547         val &= ~US_PAR;
00548         val |= US_PAR_MULTIDROP;
00549     }
00550     else {
00551         val &= ~US_CHRL;
00552         if (bits == 5) {
00553             val |= US_CHRL_5;
00554         }
00555         else if (bits == 6) {
00556             val |= US_CHRL_6;
00557         }
00558         else if (bits == 7) {
00559             val |= US_CHRL_7;
00560         }
00561         else if (bits == 8) {
00562             val |= US_CHRL_8;
00563         }
00564     }
00565 
00566     At91UsartDisable();
00567     outr(USARTn_BASE + US_MR_OFF, val);
00568     At91UsartEnable();
00569 
00570     /*
00571      * Verify the result.
00572      */
00573     if (At91UsartGetDataBits() != bits) {
00574         return -1;
00575     }
00576     return 0;
00577 }
00578 
00587 static u_char At91UsartGetParity(void)
00588 {
00589     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_PAR;
00590 
00591     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00592         val = 9;
00593     }
00594     else {
00595         if (val == US_PAR_ODD) {
00596             val = 1;
00597         }
00598         else if (val == US_PAR_EVEN) {
00599             val = 2;
00600         }
00601         else {
00602             val = 0;
00603         }
00604     }
00605     return (u_char)val;
00606 }
00607 
00618 static int At91UsartSetParity(u_char mode)
00619 {
00620     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_PAR;
00621 
00622     switch (mode) {
00623     case 0:
00624         val |= US_PAR_NO;
00625         break;
00626     case 1:
00627         val |= US_PAR_ODD;
00628         break;
00629     case 2:
00630         val |= US_PAR_EVEN;
00631         break;
00632     }
00633     At91UsartDisable();
00634     outr(USARTn_BASE + US_MR_OFF, val);
00635     At91UsartEnable();
00636 
00637     /*
00638      * Verify the result.
00639      */
00640     if (At91UsartGetParity() != mode) {
00641         return -1;
00642     }
00643     return 0;
00644 }
00645 
00654 static u_char At91UsartGetStopBits(void)
00655 {
00656     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_NBSTOP;
00657     if (val == US_NBSTOP_1) {
00658         val = 1;
00659     }
00660     else if (val == US_NBSTOP_2) {
00661         val = 2;
00662     }
00663     else {
00664         val = 3;
00665     }
00666     return (u_char)val;
00667 }
00668 
00677 static int At91UsartSetStopBits(u_char bits)
00678 {
00679     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_NBSTOP;
00680 
00681     switch(bits) {
00682     case 1:
00683         val |= US_NBSTOP_1;
00684         break;
00685     case 2:
00686         val |= US_NBSTOP_2;
00687         break;
00688     case 3:
00689         val |= US_NBSTOP_1_5;
00690         break;
00691     }
00692     At91UsartDisable();
00693     outr(USARTn_BASE + US_MR_OFF, val);
00694     At91UsartEnable();
00695 
00696     /*
00697      * Verify the result.
00698      */
00699     if (At91UsartGetStopBits() != bits) {
00700         return -1;
00701     }
00702     return 0;
00703 }
00704 
00710 static u_long At91UsartGetStatus(void)
00711 {
00712     u_long rc = 0;
00713 
00714     /*
00715      * Set receiver error flags.
00716      */
00717     if ((rx_errors & US_FRAME) != 0) {
00718         rc |= UART_FRAMINGERROR;
00719     }
00720     if ((rx_errors & US_OVRE) != 0) {
00721         rc |= UART_OVERRUNERROR;
00722     }
00723     if ((rx_errors & US_PARE) != 0) {
00724         rc |= UART_PARITYERROR;
00725     }
00726 
00727     /*
00728      * Determine software handshake status. The flow control status may
00729      * change during interrupt, but this doesn't really hurt us.
00730      */
00731     if (flow_control) {
00732         if (flow_control & XOFF_SENT) {
00733             rc |= UART_RXDISABLED;
00734         }
00735         if (flow_control & XOFF_RCVD) {
00736             rc |= UART_TXDISABLED;
00737         }
00738     }
00739 #ifdef UART_RTS_BIT
00740     /*
00741      * Determine hardware handshake control status.
00742      */
00743     if (bit_is_set(UART_RTS_PORT, UART_RTS_BIT)) {
00744         rc |= UART_RTSDISABLED;
00745         if (rts_control) {
00746             rc |= UART_RXDISABLED;
00747         }
00748     } else {
00749         rc |= UART_RTSENABLED;
00750     }
00751 #endif
00752 
00753 #ifdef UART_CTS_BIT
00754     /*
00755      * Determine hardware handshake sense status.
00756      */
00757     if (bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00758         rc |= UART_CTSDISABLED;
00759         if (cts_sense) {
00760             rc |= UART_RXDISABLED;
00761         }
00762     } else {
00763         rc |= UART_CTSENABLED;
00764     }
00765 #endif
00766 
00767     /*
00768      * If transmitter and receiver haven't been detected disabled by any
00769      * of the checks above, then they are probably enabled.
00770      */
00771     if ((rc & UART_RXDISABLED) == 0) {
00772         rc |= UART_RXENABLED;
00773     }
00774     if ((rc & UART_TXDISABLED) == 0) {
00775         rc |= UART_TXENABLED;
00776     }
00777 
00778     /*
00779      * Process multidrop setting.
00780      */
00781     if (tx_aframe) {
00782         rc |= UART_TXADDRFRAME;
00783     } else {
00784         rc |= UART_TXNORMFRAME;
00785     }
00786     return rc;
00787 }
00788 
00796 static int At91UsartSetStatus(u_long flags)
00797 {
00798     /*
00799      * Process software handshake control.
00800      */
00801     if (flow_control) {
00802 
00803         /* Access to the flow control status must be atomic. */
00804         NutEnterCritical();
00805 
00806         /*
00807          * Enabling or disabling the receiver means to behave like
00808          * having sent a XON or XOFF character resp.
00809          */
00810         if (flags & UART_RXENABLED) {
00811             flow_control &= ~XOFF_SENT;
00812         } else if (flags & UART_RXDISABLED) {
00813             flow_control |= XOFF_SENT;
00814         }
00815 
00816         /*
00817          * Enabling or disabling the transmitter means to behave like
00818          * having received a XON or XOFF character resp.
00819          */
00820         if (flags & UART_TXENABLED) {
00821             flow_control &= ~XOFF_RCVD;
00822         } else if (flags & UART_TXDISABLED) {
00823             flow_control |= XOFF_RCVD;
00824         }
00825         NutExitCritical();
00826     }
00827 #ifdef UART_RTS_BIT
00828     /*
00829      * Process hardware handshake control.
00830      */
00831     if (rts_control) {
00832         if (flags & UART_RXDISABLED) {
00833             sbi(UART_RTS_PORT, UART_RTS_BIT);
00834         }
00835         if (flags & UART_RXENABLED) {
00836             cbi(UART_RTS_PORT, UART_RTS_BIT);
00837         }
00838     }
00839     if (flags & UART_RTSDISABLED) {
00840         sbi(UART_RTS_PORT, UART_RTS_BIT);
00841     }
00842     if (flags & UART_RTSENABLED) {
00843         cbi(UART_RTS_PORT, UART_RTS_BIT);
00844     }
00845 #endif
00846 
00847     /*
00848      * Process multidrop setting.
00849      */
00850     if (flags & UART_TXADDRFRAME) {
00851         tx_aframe = 1;
00852     }
00853     if (flags & UART_TXNORMFRAME) {
00854         tx_aframe = 0;
00855     }
00856 
00857     /*
00858      * Clear UART receive errors.
00859      */
00860     if (flags & UART_ERRORS) {
00861         outr(USARTn_BASE + US_CR_OFF, US_RSTSTA);
00862     }
00863 
00864     /*
00865      * Verify the result.
00866      */
00867     if ((At91UsartGetStatus() & ~UART_ERRORS) != flags) {
00868         return -1;
00869     }
00870     return 0;
00871 }
00872 
00882 static u_char At91UsartGetClockMode(void)
00883 {
00884     u_char rc = 0;
00885 
00886     return rc;
00887 }
00888 
00900 static int At91UsartSetClockMode(u_char mode)
00901 {
00902     /*
00903      * Verify the result.
00904      */
00905     if (At91UsartGetClockMode() != mode) {
00906         return -1;
00907     }
00908     return 0;
00909 }
00910 
00919 static u_long At91UsartGetFlowControl(void)
00920 {
00921     u_long rc = 0;
00922 
00923     if (flow_control) {
00924         rc |= USART_MF_XONXOFF;
00925     } else {
00926         rc &= ~USART_MF_XONXOFF;
00927     }
00928 
00929 #ifdef UART_RTS_BIT
00930     if (rts_control) {
00931         rc |= USART_MF_RTSCONTROL;
00932     } else {
00933         rc &= ~USART_MF_RTSCONTROL;
00934     }
00935 #endif
00936 
00937 #ifdef UART_CTS_BIT
00938     if (cts_sense) {
00939         rc |= USART_MF_CTSSENSE;
00940     } else {
00941         rc &= ~USART_MF_CTSSENSE;
00942     }
00943 #endif
00944 
00945 #ifdef UART_HDX_BIT
00946     if (hdx_control) {
00947         rc |= USART_MF_HALFDUPLEX;
00948     } else {
00949         rc &= ~USART_MF_HALFDUPLEX;
00950     }
00951 #endif
00952 
00953     return rc;
00954 }
00955 
00966 static int At91UsartSetFlowControl(u_long flags)
00967 {
00968     /*
00969      * Set software handshake mode.
00970      */
00971     if (flags & USART_MF_XONXOFF) {
00972         if(flow_control == 0) {
00973             NutEnterCritical();
00974             flow_control = 1 | XOFF_SENT;  /* force XON to be sent on next read */
00975             NutExitCritical();
00976         }
00977     } else {
00978         NutEnterCritical();
00979         flow_control = 0;
00980         NutExitCritical();
00981     }
00982 
00983 #ifdef UART_RTS_BIT
00984     /*
00985      * Set RTS control mode.
00986      */
00987     if (flags & USART_MF_RTSCONTROL) {
00988         sbi(UART_RTS_PORT, UART_RTS_BIT);
00989         sbi(UART_RTS_DDR, UART_RTS_BIT);
00990         rts_control = 1;
00991     } else if (rts_control) {
00992         rts_control = 0;
00993         cbi(UART_RTS_DDR, UART_RTS_BIT);
00994     }
00995 #endif
00996 
00997 #ifdef UART_CTS_BIT
00998     /*
00999      * Set CTS sense mode.
01000      */
01001     if (flags & USART_MF_CTSSENSE) {
01002         /* Register CTS sense interrupt. */
01003         if (NutRegisterIrqHandler(&UART_CTS_SIGNAL, At91UsartCts, 0)) {
01004             return -1;
01005         }
01006         sbi(UART_CTS_PORT, UART_CTS_BIT);
01007         cbi(UART_CTS_DDR, UART_CTS_BIT);
01008         cts_sense = 1;
01009     } else if (cts_sense) {
01010         cts_sense = 0;
01011         /* Deregister CTS sense interrupt. */
01012         NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0);
01013         cbi(UART_CTS_DDR, UART_CTS_BIT);
01014     }
01015 #endif
01016 
01017 #ifdef UART_HDX_BIT
01018     /*
01019      * Set half duplex mode.
01020      */
01021     if (flags & USART_MF_HALFDUPLEX) {
01022         /* Register transmit complete interrupt. */
01023         if (NutRegisterIrqHandler(&sig_UART_TRANS, At91UsartTxComplete, &dcb_usart.dcb_rx_rbf)) {
01024             return -1;
01025         }
01026         /* Initially enable the receiver. */
01027         UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
01028         sbi(UART_HDX_DDR, UART_HDX_BIT);
01029         hdx_control = 1;
01030         /* Enable transmit complete interrupt. */
01031         sbi(UCSRnB, TXCIE);
01032     } else if (hdx_control) {
01033         hdx_control = 0;
01034         /* disable transmit complete interrupt */
01035         cbi(UCSRnB, TXCIE);
01036         /* Deregister transmit complete interrupt. */
01037         NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
01038         cbi(UART_HDX_DDR, UART_HDX_BIT);
01039     }
01040 #endif
01041 
01042     /*
01043      * Verify the result.
01044      */
01045     if (At91UsartGetFlowControl() != flags) {
01046         return -1;
01047     }
01048     return 0;
01049 }
01050 
01058 static void At91UsartTxStart(void)
01059 {
01060 #ifdef UART_HDX_BIT
01061     if (hdx_control) {
01062         /* Enable half duplex transmitter. */
01063         UART_HDX_TX(UART_HDX_PORT, UART_HDX_BIT);
01064     }
01065 #endif
01066     /* Enable transmit interrupts. */
01067     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
01068 }
01069 
01078 static void At91UsartRxStart(void)
01079 {
01080     /*
01081      * Do any required software flow control.
01082      */
01083     if (flow_control && (flow_control & XOFF_SENT) != 0) {
01084         NutEnterCritical();
01085         if ((inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY)) {
01086             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
01087             flow_control &= ~XON_PENDING;
01088         } else {
01089             flow_control |= XON_PENDING;
01090         }
01091         flow_control &= ~(XOFF_SENT | XOFF_PENDING);
01092         NutExitCritical();
01093     }
01094 #ifdef UART_RTS_BIT
01095     if (rts_control) {
01096         /* Enable RTS. */
01097         cbi(UART_RTS_PORT, UART_RTS_BIT);
01098     }
01099 #endif
01100 }
01101 
01102 /*
01103  * \brief Initialize the USART hardware driver.
01104  *
01105  * This function is called during device registration by the upper level
01106  * USART driver through the USARTDCB jump table.
01107  *
01108  * \return 0 on success, -1 otherwise.
01109  */
01110 static int At91UsartInit(void)
01111 {
01112     /*
01113      * Register receive and transmit interrupts.
01114      */
01115     if (NutRegisterIrqHandler(&SIG_UART, At91UsartInterrupt, &dcb_usart)) {
01116         return -1;
01117     }
01118 
01119 #if defined (MCU_AT91R40008)
01120     /* Enable UART clock. */
01121     outr(PS_PCER, _BV(US_ID));
01122     /* Disable GPIO on UART tx/rx pins. */
01123     outr(PIO_PDR, US_GPIO_PINS);
01124 #elif defined (MCU_AT91SAM7X256) || defined (MCU_AT91SAM7S256)
01125     outr(PMC_PCER, _BV(US_ID));
01126     outr(PIOA_PDR, US_GPIO_PINS);
01127 #endif
01128     /* Reset UART. */
01129     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01130     /* Disable all UART interrupts. */
01131     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01132     /* Clear UART counter registers. */
01133 #if defined (US_RCR_OFF)
01134     outr(USARTn_BASE + US_RCR_OFF, 0);
01135 #endif
01136 #if defined (US_TCR_OFF)
01137     outr(USARTn_BASE + US_TCR_OFF, 0);
01138 #endif
01139     /* Set UART baud rate generator register. */
01140 #if defined(AT91_PLL_MAINCK)
01141     outr(USARTn_BASE + US_BRGR_OFF, (At91GetMasterClock() / (8 * (115200)) + 1) / 2);
01142 #else
01143     outr(USARTn_BASE + US_BRGR_OFF, (NutGetCpuClock() / (8 * (115200)) + 1) / 2);
01144 #endif
01145     /* Set UART mode to 8 data bits, no parity and 1 stop bit. */
01146     outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1);
01147 
01148     return 0;
01149 }
01150 
01151 /*
01152  * \brief Deinitialize the USART hardware driver.
01153  *
01154  * This function is called during device deregistration by the upper
01155  * level USART driver through the USARTDCB jump table.
01156  *
01157  * \return 0 on success, -1 otherwise.
01158  */
01159 static int At91UsartDeinit(void)
01160 {
01161     /* Deregister receive and transmit interrupts. */
01162     NutRegisterIrqHandler(&SIG_UART, 0, 0);
01163 
01164     /* Reset UART. */
01165     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01166     /* Disable all UART interrupts. */
01167     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01168 #if defined (MCU_AT91R40008)
01169     /* Disable UART clock. */
01170     outr(PS_PCDR, _BV(US_ID));
01171     /* Enable GPIO on UART tx/rx pins. */
01172     outr(PIO_PER, US_GPIO_PINS);
01173 #elif defined (MCU_AT91SAM7X256) || defined (MCU_AT91SAM7S256)
01174     outr(PMC_PCDR, _BV(US_ID));
01175     outr(PIOA_PER, US_GPIO_PINS);
01176 #endif
01177 
01178     /*
01179      * Disabling flow control shouldn't be required here, because it's up
01180      * to the upper level to do this on the last close or during
01181      * deregistration.
01182      */
01183 #ifdef UART_HDX_BIT
01184     /* Deregister transmit complete interrupt. */
01185     if (hdx_control) {
01186         hdx_control = 0;
01187         NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
01188     }
01189 #endif
01190 
01191 #ifdef UART_CTS_BIT
01192     if (cts_sense) {
01193         cts_sense = 0;
01194         cbi(UART_CTS_DDR, UART_CTS_BIT);
01195         /* Deregister CTS sense interrupt. */
01196         NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0);
01197     }
01198 #endif
01199 
01200 #ifdef UART_RTS_BIT
01201     if (rts_control) {
01202         rts_control = 0;
01203         cbi(UART_RTS_DDR, UART_RTS_BIT);
01204     }
01205 #endif
01206 
01207     return 0;
01208 }
01209 

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