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

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