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.12  2008/10/23 08:50:43  haraldkipp
00041  * Prepared AT91 UART hardware handshake.
00042  *
00043  * Revision 1.11  2008/08/11 06:59:13  haraldkipp
00044  * BSD types replaced by stdint types (feature request #1282721).
00045  *
00046  * Revision 1.10  2008/07/31 09:43:25  haraldkipp
00047  * Initializing peripheral control registers in a more general way.
00048  * Fixes bug #2032960.
00049  *
00050  * Revision 1.9  2008/04/18 13:24:56  haraldkipp
00051  * Added Szemzo Andras' RS485 patch.
00052  *
00053  * Revision 1.8  2008/02/15 16:59:27  haraldkipp
00054  * Spport for AT91SAM7SE512 added.
00055  *
00056  * Revision 1.7  2007/10/04 20:05:51  olereinhardt
00057  * Support for SAM7S256 added
00058  *
00059  * Revision 1.6  2006/08/31 19:01:44  haraldkipp
00060  * Using the processor clock for baud rate calculations failed
00061  * on the SAM9, if the master clock is further divided. This
00062  * had been fixed.
00063  *
00064  * Revision 1.5  2006/08/05 11:54:06  haraldkipp
00065  * Special register functions should not be based on MCU definitions but on
00066  * register definitions.
00067  *
00068  * Revision 1.4  2006/07/05 07:55:23  haraldkipp
00069  * Daidai's support for AT91SAM7X added.
00070  *
00071  * Revision 1.3  2006/06/28 17:18:40  haraldkipp
00072  * Temporarly exclude AT91R40008 specific register settings from building
00073  * for AT91SAM7X.
00074  *
00075  * Revision 1.2  2006/01/05 16:47:32  haraldkipp
00076  * Baudrate calculation is now based on NutGetCpuClock().
00077  *
00078  * Revision 1.1  2005/11/20 14:40:28  haraldkipp
00079  * Added interrupt driven UART driver for AT91.
00080  *
00081  */
00082 
00083 #include <cfg/clock.h>
00084 
00085 #include <sys/atom.h>
00086 #include <sys/event.h>
00087 #include <sys/timer.h>
00088 
00089 #include <dev/irqreg.h>
00090 
00091 #include <dev/usartat91.h>
00092 
00097 
00098 /* \brief ASCII code for software flow control, starts transmitter. */
00099 #define ASCII_XON   0x11
00100 /* \brief ASCII code for software flow control, stops transmitter. */
00101 #define ASCII_XOFF  0x13
00102 
00103 /* \brief XON transmit pending flag. */
00104 #define XON_PENDING     0x10
00105 /* \brief XOFF transmit pending flag. */
00106 #define XOFF_PENDING    0x20
00107 /* \brief XOFF sent flag. */
00108 #define XOFF_SENT       0x40
00109 /* \brief XOFF received flag. */
00110 #define XOFF_RCVD       0x80
00111 
00112 
00116 static ureg_t rx_errors;
00117 
00121 static uint_fast8_t flow_control;
00122 
00126 static uint_fast8_t tx_aframe;
00127 
00128 #ifdef UART_HDX_BIT
00129     /* define in cfg/modem.h */
00130     #ifdef UART_HDX_FLIP_BIT    /* same as RTS toggle by Windows NT driver */
00131         #define UART_HDX_TX     cbi
00132         #define UART_HDX_RX     sbi
00133     #else                       /* previous usage by Ethernut */
00134         #define UART_HDX_TX     sbi
00135         #define UART_HDX_RX     cbi
00136     #endif
00137 #endif
00138 
00139 
00140 #ifdef UART_HDX_BIT
00141 
00147 static uint_fast8_t hdx_control;
00148 #endif
00149 
00150 //#if defined(UART_RTS_BIT) || defined(US_MODE_HWHANDSHAKE)
00157 static uint_fast8_t rts_control;
00158 //#endif
00159 
00160 //#if defined(UART_CTS_BIT) || defined(US_MODE_HWHANDSHAKE)
00167 static uint_fast8_t cts_sense;
00168 //#endif
00169 
00170 #ifdef UART_CTS_BIT
00171 
00181 static void At91UsartCts(void *arg)
00182 {
00183     /* Enable transmit interrupt. */
00184     //sbi(UCSRnB, UDRIE);
00185     /* Disable CTS sense interrupt. */
00186     //cbi(EIMSK, UART_CTS_BIT);
00187 }
00188 #endif
00189 
00190 #ifdef UART_HDX_BIT
00191 /*
00192  * \brief USARTn transmitter empty interrupt handler.
00193  *
00194  * Used with half duplex communication to switch from tranmit to receive
00195  * mode after the last character has been transmitted.
00196  *
00197  * This routine exists only if the hardware configuration defines a
00198  * port bit to switch between receive and transmit mode.
00199  *
00200  * \param arg Pointer to the transmitter ring buffer.
00201  */
00202 static void At91UsartTxEmpty(RINGBUF *rbf)
00203 {
00204     /*
00205      * Check if half duplex mode has been enabled and if all characters
00206      * had been sent out.
00207      */
00208     if (hdx_control && rbf->rbf_cnt == 0) {
00209         /* Switch to receiver mode. */
00210         UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
00211     }
00212 }
00213 #endif
00214 
00215 /*
00216  * \brief USARTn transmitter ready interrupt handler.
00217  *
00218  * \param rbf Pointer to the transmitter ring buffer.
00219  */
00220 static void At91UsartTxReady(RINGBUF *rbf) 
00221 {
00222     register uint8_t *cp = rbf->rbf_tail;
00223 
00224     /*
00225      * Process pending software flow controls first.
00226      */
00227     if (flow_control & (XON_PENDING | XOFF_PENDING)) {
00228         if (flow_control & XON_PENDING) {
00229             outr(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00230             flow_control |= XOFF_SENT;
00231         } else {
00232             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
00233             flow_control &= ~XOFF_SENT;
00234         }
00235         flow_control &= ~(XON_PENDING | XOFF_PENDING);
00236         return;
00237     }
00238 
00239     if (flow_control & XOFF_RCVD) {
00240         /*
00241          * If XOFF has been received, we disable the transmit interrupts
00242          * and return without sending anything.
00243          */
00244         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00245         return;
00246     }
00247 
00248     if (rbf->rbf_cnt) {
00249 
00250 #ifdef UART_CTS_BIT
00251         /*
00252          * If CTS has been disabled, we disable the transmit interrupts
00253          * and return without sending anything.
00254          */
00255         if (cts_sense && bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00256             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00257             sbi(EIMSK, UART_CTS_BIT);
00258             return;
00259         }
00260 #endif
00261         rbf->rbf_cnt--;
00262 
00263         /*
00264          * Send address in multidrop mode.
00265          */
00266         if (tx_aframe) {
00267             outr(USARTn_BASE + US_CR_OFF, US_SENDA);
00268         }
00269 
00270         /*
00271          * Start transmission of the next character.
00272          */
00273         outr(USARTn_BASE + US_THR_OFF, *cp);
00274 
00275         /*
00276          * Wrap around the buffer pointer if we reached its end.
00277          */
00278         if (++cp == rbf->rbf_last) {
00279             cp = rbf->rbf_start;
00280         }
00281         rbf->rbf_tail = cp;
00282         if (rbf->rbf_cnt == rbf->rbf_lwm) {
00283             NutEventPostFromIrq(&rbf->rbf_que);
00284         }
00285     }
00286 
00287     /*
00288      * Nothing left to transmit, disable interrupt.
00289      */
00290     else {
00291         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00292         rbf->rbf_cnt = 0;
00293         NutEventPostFromIrq(&rbf->rbf_que);
00294     }
00295 }
00296 
00297 
00298 /*
00299  * \brief USARTn receiver ready interrupt handler.
00300  *
00301  *
00302  * \param rbf Pointer to the receiver ring buffer.
00303  */
00304 
00305 static void At91UsartRxReady(RINGBUF *rbf) 
00306 {
00307     register size_t cnt;
00308     register uint8_t ch;
00309 
00310     /*
00311      * We read the received character as early as possible to avoid overflows
00312      * caused by interrupt latency.
00313      */
00314     ch = inb(USARTn_BASE + US_RHR_OFF);
00315 
00316     /* Collect receiver errors. */
00317     rx_errors |= inr(USARTn_BASE + US_CSR_OFF) & (US_OVRE | US_FRAME | US_PARE);
00318 
00319     /*
00320      * Handle software handshake. We have to do this before checking the
00321      * buffer, because flow control must work in write-only mode, where
00322      * there is no receive buffer.
00323      */
00324     if (flow_control) {
00325         /* XOFF character disables transmit interrupts. */
00326         if (ch == ASCII_XOFF) {
00327             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00328             flow_control |= XOFF_RCVD;
00329             return;
00330         }
00331         /* XON enables transmit interrupts. */
00332         else if (ch == ASCII_XON) {
00333             outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00334             flow_control &= ~XOFF_RCVD;
00335             return;
00336         }
00337     }
00338 
00339     /*
00340      * Check buffer overflow.
00341      */
00342     cnt = rbf->rbf_cnt;
00343     if (cnt >= rbf->rbf_siz) {
00344         rx_errors |= US_OVRE;
00345         return;
00346     }
00347 
00348     /* Wake up waiting threads if this is the first byte in the buffer. */
00349     if (cnt++ == 0){
00350         NutEventPostFromIrq(&rbf->rbf_que);
00351     }
00352 
00353     /*
00354      * Check the high watermark for software handshake. If the number of
00355      * buffered bytes is above this mark, then send XOFF.
00356      */
00357     else if (flow_control) {
00358         if(cnt >= rbf->rbf_hwm) {
00359             if((flow_control & XOFF_SENT) == 0) {
00360                 if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00361                     outb(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00362                     flow_control |= XOFF_SENT;
00363                     flow_control &= ~XOFF_PENDING;
00364                 } else {
00365                     flow_control |= XOFF_PENDING;
00366                 }
00367             }
00368         }
00369     }
00370 
00371 #ifdef UART_RTS_BIT
00372     /*
00373      * Check the high watermark for hardware handshake. If the number of
00374      * buffered bytes is above this mark, then disable RTS.
00375      */
00376     else if (rts_control && cnt >= rbf->rbf_hwm) {
00377         sbi(UART_RTS_PORT, UART_RTS_BIT);
00378     }
00379 #endif
00380 
00381     /*
00382      * Store the character and increment and the ring buffer pointer.
00383      */
00384     *rbf->rbf_head++ = ch;
00385     if (rbf->rbf_head == rbf->rbf_last) {
00386         rbf->rbf_head = rbf->rbf_start;
00387     }
00388 
00389     /* Update the ring buffer counter. */
00390     rbf->rbf_cnt = cnt;
00391 }
00392 
00398 static void At91UsartInterrupt(void *arg)
00399 {
00400     USARTDCB *dcb = (USARTDCB *)arg;
00401     ureg_t csr = inr(USARTn_BASE + US_CSR_OFF);
00402 
00403     if (csr & US_RXRDY) {
00404         At91UsartRxReady(&dcb->dcb_rx_rbf);
00405     }
00406     if (csr & US_TXRDY) {
00407         At91UsartTxReady(&dcb->dcb_tx_rbf);
00408     }
00409 
00410 #ifdef UART_HDX_BIT
00411     if (csr & US_TXEMPTY) {
00412         At91UsartTxEmpty(&dcb->dcb_tx_rbf);
00413     }
00414 #endif /*  UART_HDX_BIT */
00415 }
00416 
00423 static void At91UsartEnable(void)
00424 {
00425     NutEnterCritical();
00426 
00427     /* Enable UART receiver and transmitter. */
00428     outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
00429 
00430     /* Enable UART receiver and transmitter interrupts. */
00431     outr(USARTn_BASE + US_IER_OFF, US_RXRDY | US_TXRDY);
00432     NutIrqEnable(&SIG_UART);
00433 
00434 #ifdef UART_HDX_BIT
00435     if (hdx_control) {
00436         /* Enable transmit complete interrupt. */
00437         sbi(UCSRnB, TXCIE);
00438     }
00439 #endif
00440 
00441     NutExitCritical();
00442 }
00443 
00447 static void At91UsartDisable(void)
00448 {
00449     /*
00450      * Disable USART interrupts.
00451      */
00452     NutEnterCritical();
00453     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
00454     NutExitCritical();
00455 
00456     /*
00457      * Allow incoming or outgoing character to finish.
00458      */
00459     NutDelay(10);
00460 
00461     /*
00462      * Disable USART transmit and receive.
00463      */
00464     outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXDIS);
00465 }
00466 
00475 static uint32_t At91UsartGetSpeed(void)
00476 {
00477     ureg_t cs = inr(USARTn_BASE + US_MR_OFF);
00478     uint32_t clk;
00479 
00480     clk = NutClockGet(NUT_HWCLK_PERIPHERAL);
00481     if ((cs & US_CLKS) == US_CLKS_MCK8) {
00482         clk /= 8;
00483     }
00484     else if ((cs & US_CLKS) != US_CLKS_MCK) {
00485         clk = 0;
00486     }
00487     return clk / (16UL * (inr(USARTn_BASE + US_BRGR_OFF) & 0xFFFF));
00488 }
00489 
00500 static int At91UsartSetSpeed(uint32_t rate)
00501 {
00502     At91UsartDisable();
00503     outr(USARTn_BASE + US_BRGR_OFF, (NutClockGet(NUT_HWCLK_PERIPHERAL) / (8 * (rate)) + 1) / 2);
00504     At91UsartEnable();
00505 
00506     return 0;
00507 }
00508 
00517 static uint8_t At91UsartGetDataBits(void)
00518 {
00519     ureg_t val = inr(USARTn_BASE + US_MR_OFF);
00520 
00521     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00522         val = 9;
00523     }
00524     else {
00525         val &= US_CHRL;
00526         if (val == US_CHRL_5) {
00527             val = 5;
00528         }
00529         else if (val == US_CHRL_6) {
00530             val = 6;
00531         }
00532         else if (val == US_CHRL_7) {
00533             val = 7;
00534         }
00535         else {
00536             val = 8;
00537         }
00538     }
00539     return (uint8_t)val;
00540 }
00541 
00550 static int At91UsartSetDataBits(uint8_t bits)
00551 {
00552     ureg_t val = inr(USARTn_BASE + US_MR_OFF);
00553 
00554     if (bits == 9) {
00555         val &= ~US_PAR;
00556         val |= US_PAR_MULTIDROP;
00557     }
00558     else {
00559         val &= ~US_CHRL;
00560         if (bits == 5) {
00561             val |= US_CHRL_5;
00562         }
00563         else if (bits == 6) {
00564             val |= US_CHRL_6;
00565         }
00566         else if (bits == 7) {
00567             val |= US_CHRL_7;
00568         }
00569         else if (bits == 8) {
00570             val |= US_CHRL_8;
00571         }
00572     }
00573 
00574     At91UsartDisable();
00575     outr(USARTn_BASE + US_MR_OFF, val);
00576     At91UsartEnable();
00577 
00578     /*
00579      * Verify the result.
00580      */
00581     if (At91UsartGetDataBits() != bits) {
00582         return -1;
00583     }
00584     return 0;
00585 }
00586 
00595 static uint8_t At91UsartGetParity(void)
00596 {
00597     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_PAR;
00598 
00599     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00600         val = 9;
00601     }
00602     else {
00603         if (val == US_PAR_ODD) {
00604             val = 1;
00605         }
00606         else if (val == US_PAR_EVEN) {
00607             val = 2;
00608         }
00609         else {
00610             val = 0;
00611         }
00612     }
00613     return (uint8_t)val;
00614 }
00615 
00626 static int At91UsartSetParity(uint8_t mode)
00627 {
00628     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_PAR;
00629 
00630     switch (mode) {
00631     case 0:
00632         val |= US_PAR_NO;
00633         break;
00634     case 1:
00635         val |= US_PAR_ODD;
00636         break;
00637     case 2:
00638         val |= US_PAR_EVEN;
00639         break;
00640     }
00641     At91UsartDisable();
00642     outr(USARTn_BASE + US_MR_OFF, val);
00643     At91UsartEnable();
00644 
00645     /*
00646      * Verify the result.
00647      */
00648     if (At91UsartGetParity() != mode) {
00649         return -1;
00650     }
00651     return 0;
00652 }
00653 
00662 static uint8_t At91UsartGetStopBits(void)
00663 {
00664     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_NBSTOP;
00665     if (val == US_NBSTOP_1) {
00666         val = 1;
00667     }
00668     else if (val == US_NBSTOP_2) {
00669         val = 2;
00670     }
00671     else {
00672         val = 3;
00673     }
00674     return (uint8_t)val;
00675 }
00676 
00685 static int At91UsartSetStopBits(uint8_t bits)
00686 {
00687     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_NBSTOP;
00688 
00689     switch(bits) {
00690     case 1:
00691         val |= US_NBSTOP_1;
00692         break;
00693     case 2:
00694         val |= US_NBSTOP_2;
00695         break;
00696     case 3:
00697         val |= US_NBSTOP_1_5;
00698         break;
00699     }
00700     At91UsartDisable();
00701     outr(USARTn_BASE + US_MR_OFF, val);
00702     At91UsartEnable();
00703 
00704     /*
00705      * Verify the result.
00706      */
00707     if (At91UsartGetStopBits() != bits) {
00708         return -1;
00709     }
00710     return 0;
00711 }
00712 
00718 static uint32_t At91UsartGetStatus(void)
00719 {
00720     uint32_t rc = 0;
00721 #if defined(US_MODE_HWHANDSHAKE)
00722     uint32_t csr = inr(USARTn_BASE + US_CSR_OFF);
00723 #endif
00724 
00725     /*
00726      * Set receiver error flags.
00727      */
00728     if ((rx_errors & US_FRAME) != 0) {
00729         rc |= UART_FRAMINGERROR;
00730     }
00731     if ((rx_errors & US_OVRE) != 0) {
00732         rc |= UART_OVERRUNERROR;
00733     }
00734     if ((rx_errors & US_PARE) != 0) {
00735         rc |= UART_PARITYERROR;
00736     }
00737 
00738     /*
00739      * Determine software handshake status. The flow control status may
00740      * change during interrupt, but this doesn't really hurt us.
00741      */
00742     if (flow_control) {
00743         if (flow_control & XOFF_SENT) {
00744             rc |= UART_RXDISABLED;
00745         }
00746         if (flow_control & XOFF_RCVD) {
00747             rc |= UART_TXDISABLED;
00748         }
00749     }
00750 
00751     /*
00752      * Determine hardware handshake control status.
00753      */
00754 #if defined(UART_RTS_BIT)
00755     if (bit_is_set(UART_RTS_PORT, UART_RTS_BIT)) {
00756         rc |= UART_RTSDISABLED;
00757         if (rts_control) {
00758             rc |= UART_RXDISABLED;
00759         }
00760     } else {
00761         rc |= UART_RTSENABLED;
00762     }
00763 #elif defined(US_MODE_HWHANDSHAKE)
00764     /* How to find out? */
00765 #endif
00766 
00767     /*
00768      * Determine hardware handshake sense status.
00769      */
00770 #ifdef UART_CTS_BIT
00771     if (bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00772         rc |= UART_CTSDISABLED;
00773         if (cts_sense) {
00774             rc |= UART_RXDISABLED;
00775         }
00776     } else {
00777         rc |= UART_CTSENABLED;
00778     }
00779 #elif defined(US_MODE_HWHANDSHAKE)
00780     if (csr & US_CTS) {
00781         rc |= UART_CTSDISABLED;
00782         if (cts_sense) {
00783             rc |= UART_RXDISABLED;
00784         }
00785     } else {
00786         rc |= UART_CTSENABLED;
00787     }
00788 #endif
00789 
00790     /*
00791      * Determine hardware modem sense status.
00792      */
00793 #if defined(US_MODE_HWHANDSHAKE) && 0
00794     /* I'm confused. Awful flag mismatch? Why do we have uart.h and usart.h? */
00795     if (csr & US_RI) {
00796         rc |= UART_RIDISABLED;
00797     } else {
00798         rc |= UART_RIENABLED;
00799     }
00800     if (csr & US_DSR) {
00801         rc |= UART_DSRDISABLED;
00802     } else {
00803         rc |= UART_DSRENABLED;
00804     }
00805     if (csr & US_DCD) {
00806         rc |= UART_DCDDISABLED;
00807     } else {
00808         rc |= UART_DCDENABLED;
00809     }
00810 #endif
00811 
00812     /*
00813      * If transmitter and receiver haven't been detected disabled by any
00814      * of the checks above, then they are probably enabled.
00815      */
00816     if ((rc & UART_RXDISABLED) == 0) {
00817         rc |= UART_RXENABLED;
00818     }
00819     if ((rc & UART_TXDISABLED) == 0) {
00820         rc |= UART_TXENABLED;
00821     }
00822 
00823     /*
00824      * Process multidrop setting.
00825      */
00826     if (tx_aframe) {
00827         rc |= UART_TXADDRFRAME;
00828     } else {
00829         rc |= UART_TXNORMFRAME;
00830     }
00831     return rc;
00832 }
00833 
00841 static int At91UsartSetStatus(uint32_t flags)
00842 {
00843     /*
00844      * Process software handshake control.
00845      */
00846     if (flow_control) {
00847 
00848         /* Access to the flow control status must be atomic. */
00849         NutEnterCritical();
00850 
00851         /*
00852          * Enabling or disabling the receiver means to behave like
00853          * having sent a XON or XOFF character resp.
00854          */
00855         if (flags & UART_RXENABLED) {
00856             flow_control &= ~XOFF_SENT;
00857         } else if (flags & UART_RXDISABLED) {
00858             flow_control |= XOFF_SENT;
00859         }
00860 
00861         /*
00862          * Enabling or disabling the transmitter means to behave like
00863          * having received a XON or XOFF character resp.
00864          */
00865         if (flags & UART_TXENABLED) {
00866             flow_control &= ~XOFF_RCVD;
00867         } else if (flags & UART_TXDISABLED) {
00868             flow_control |= XOFF_RCVD;
00869         }
00870         NutExitCritical();
00871     }
00872 
00873     /*
00874      * Process hardware handshake control.
00875      */
00876 #if defined(UART_RTS_BIT)
00877     /* Manually controlled via GPIO. */
00878     if (rts_control) {
00879         if (flags & UART_RXDISABLED) {
00880             sbi(UART_RTS_PORT, UART_RTS_BIT);
00881         }
00882         if (flags & UART_RXENABLED) {
00883             cbi(UART_RTS_PORT, UART_RTS_BIT);
00884         }
00885     }
00886     if (flags & UART_RTSDISABLED) {
00887         sbi(UART_RTS_PORT, UART_RTS_BIT);
00888     }
00889     if (flags & UART_RTSENABLED) {
00890         cbi(UART_RTS_PORT, UART_RTS_BIT);
00891     }
00892 #elif defined(US_MODE_HWHANDSHAKE)
00893     /* Build in hardware. */
00894     if (rts_control) {
00895         if (flags & UART_RXDISABLED) {
00896             outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
00897         }
00898         if (flags & UART_RXENABLED) {
00899             outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
00900         }
00901     }
00902     if (flags & UART_RTSDISABLED) {
00903         outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
00904     }
00905     if (flags & UART_RTSENABLED) {
00906         outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
00907     }
00908 #endif
00909 
00910     /*
00911      * Process hardware modem control.
00912      */
00913 #if defined(UART_DTR_BIT)
00914     /* Manually controlled via GPIO. */
00915     if (flags & UART_DTRDISABLED) {
00916         sbi(UART_DTR_PORT, UART_DTR_BIT);
00917     }
00918     if (flags & UART_DTRENABLED) {
00919         cbi(UART_DTR_PORT, UART_DTR_BIT);
00920     }
00921 #elif defined(US_MODE_HWHANDSHAKE)
00922     /* Build in hardware. */
00923     if (flags & UART_DTRDISABLED) {
00924         outr(USARTn_BASE + US_CR_OFF, US_DTRDIS);
00925     }
00926     if (flags & UART_DTRENABLED) {
00927         outr(USARTn_BASE + US_CR_OFF, US_DTREN);
00928     }
00929 #endif
00930 
00931     /*
00932      * Process multidrop setting.
00933      */
00934     if (flags & UART_TXADDRFRAME) {
00935         tx_aframe = 1;
00936     }
00937     if (flags & UART_TXNORMFRAME) {
00938         tx_aframe = 0;
00939     }
00940 
00941     /*
00942      * Clear UART receive errors.
00943      */
00944     if (flags & UART_ERRORS) {
00945         outr(USARTn_BASE + US_CR_OFF, US_RSTSTA);
00946     }
00947 
00948     /*
00949      * Verify the result.
00950      */
00951     if ((At91UsartGetStatus() & ~UART_ERRORS) != flags) {
00952         return -1;
00953     }
00954     return 0;
00955 }
00956 
00966 static uint8_t At91UsartGetClockMode(void)
00967 {
00968     uint8_t rc = 0;
00969 
00970     return rc;
00971 }
00972 
00984 static int At91UsartSetClockMode(uint8_t mode)
00985 {
00986     /*
00987      * Verify the result.
00988      */
00989     if (At91UsartGetClockMode() != mode) {
00990         return -1;
00991     }
00992     return 0;
00993 }
00994 
01003 static uint32_t At91UsartGetFlowControl(void)
01004 {
01005     uint32_t rc = 0;
01006 
01007     if (flow_control) {
01008         rc |= USART_MF_XONXOFF;
01009     } else {
01010         rc &= ~USART_MF_XONXOFF;
01011     }
01012 
01013 #ifdef UART_RTS_BIT
01014     if (rts_control) {
01015         rc |= USART_MF_RTSCONTROL;
01016     } else {
01017         rc &= ~USART_MF_RTSCONTROL;
01018     }
01019 #endif
01020 
01021 #ifdef UART_CTS_BIT
01022     if (cts_sense) {
01023         rc |= USART_MF_CTSSENSE;
01024     } else {
01025         rc &= ~USART_MF_CTSSENSE;
01026     }
01027 #endif
01028 
01029 #ifdef UART_HDX_BIT
01030     if (hdx_control) {
01031         rc |= USART_MF_HALFDUPLEX;
01032     } else {
01033         rc &= ~USART_MF_HALFDUPLEX;
01034     }
01035 #endif
01036 
01037     return rc;
01038 }
01039 
01050 static int At91UsartSetFlowControl(uint32_t flags)
01051 {
01052     /*
01053      * Set software handshake mode.
01054      */
01055     if (flags & USART_MF_XONXOFF) {
01056         if(flow_control == 0) {
01057             NutEnterCritical();
01058             flow_control = 1 | XOFF_SENT;  /* force XON to be sent on next read */
01059             NutExitCritical();
01060         }
01061     } else {
01062         NutEnterCritical();
01063         flow_control = 0;
01064         NutExitCritical();
01065     }
01066 
01067     /*
01068      * Set RTS control mode.
01069      */
01070     if (flags & USART_MF_RTSCONTROL) {
01071 #if defined(UART_RTS_BIT)
01072         sbi(UART_RTS_PORT, UART_RTS_BIT);
01073         sbi(UART_RTS_DDR, UART_RTS_BIT);
01074         rts_control = 1;
01075 #endif
01076     } else if (rts_control) {
01077         rts_control = 0;
01078 #if defined(UART_RTS_BIT)
01079         cbi(UART_RTS_DDR, UART_RTS_BIT);
01080 #endif
01081     }
01082 
01083 /*
01084  * Set CTS sense mode.
01085  */
01086     if (flags & USART_MF_CTSSENSE) {
01087 #if defined(UART_CTS_BIT)
01088         /* Register CTS sense interrupt. */
01089         if (NutRegisterIrqHandler(&UART_CTS_SIGNAL, At91UsartCts, 0)) {
01090             return -1;
01091         }
01092         sbi(UART_CTS_PORT, UART_CTS_BIT);
01093         cbi(UART_CTS_DDR, UART_CTS_BIT);
01094         cts_sense = 1;
01095 #elif defined(US_MODE_HWHANDSHAKE)
01096         uint32_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_MODE;
01097 
01098         outr(USARTn_BASE + US_MR_OFF, val | US_MODE_HWHANDSHAKE);
01099         cts_sense = 1;
01100         rts_control = 1;
01101 #endif
01102     } else if (cts_sense) {
01103 #if defined(UART_CTS_BIT)
01104         /* Deregister CTS sense interrupt. */
01105         NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0);
01106         cbi(UART_CTS_DDR, UART_CTS_BIT);
01107 #elif defined(US_MODE_HWHANDSHAKE)
01108         uint32_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_MODE;
01109 
01110         outr(USARTn_BASE + US_MR_OFF, val);
01111         rts_control = 0;
01112 #endif
01113         cts_sense = 0;
01114     }
01115 
01116 #ifdef UART_HDX_BIT
01117     /*
01118      * Set half duplex mode.
01119      */
01120     if (flags & USART_MF_HALFDUPLEX) {
01121         /* Register transmit complete interrupt. */
01122         if (NutRegisterIrqHandler(&sig_UART_TRANS, At91UsartTxComplete, &dcb_usart.dcb_rx_rbf)) {
01123             return -1;
01124         }
01125         /* Initially enable the receiver. */
01126         UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
01127         sbi(UART_HDX_DDR, UART_HDX_BIT);
01128         hdx_control = 1;
01129         /* Enable transmit complete interrupt. */
01130         sbi(UCSRnB, TXCIE);
01131     } else if (hdx_control) {
01132         hdx_control = 0;
01133         /* disable transmit complete interrupt */
01134         cbi(UCSRnB, TXCIE);
01135         /* Deregister transmit complete interrupt. */
01136         NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
01137         cbi(UART_HDX_DDR, UART_HDX_BIT);
01138     }
01139 #endif
01140 
01141     /*
01142      * Verify the result.
01143      */
01144     if (At91UsartGetFlowControl() != flags) {
01145         return -1;
01146     }
01147     return 0;
01148 }
01149 
01157 static void At91UsartTxStart(void)
01158 {
01159 #ifdef UART_HDX_BIT
01160     if (hdx_control) {
01161         /* Enable half duplex transmitter. */
01162         UART_HDX_TX(UART_HDX_PORT, UART_HDX_BIT);
01163     }
01164 #endif
01165     /* Enable transmit interrupts. */
01166     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
01167 }
01168 
01177 static void At91UsartRxStart(void)
01178 {
01179     /*
01180      * Do any required software flow control.
01181      */
01182     if (flow_control && (flow_control & XOFF_SENT) != 0) {
01183         NutEnterCritical();
01184         if ((inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY)) {
01185             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
01186             flow_control &= ~XON_PENDING;
01187         } else {
01188             flow_control |= XON_PENDING;
01189         }
01190         flow_control &= ~(XOFF_SENT | XOFF_PENDING);
01191         NutExitCritical();
01192     }
01193 #ifdef UART_RTS_BIT
01194     if (rts_control) {
01195         /* Enable RTS. */
01196         cbi(UART_RTS_PORT, UART_RTS_BIT);
01197     }
01198 #endif
01199 }
01200 
01201 /*
01202  * \brief Initialize the USART hardware driver.
01203  *
01204  * This function is called during device registration by the upper level
01205  * USART driver through the USARTDCB jump table.
01206  *
01207  * \return 0 on success, -1 otherwise.
01208  */
01209 static int At91UsartInit(void)
01210 {
01211     /*
01212      * Register receive and transmit interrupts.
01213      */
01214     if (NutRegisterIrqHandler(&SIG_UART, At91UsartInterrupt, &dcb_usart)) {
01215         return -1;
01216     }
01217 
01218     /* Enable UART clock. */
01219 #if defined(US_ID)
01220 #if defined(PS_PCER)
01221     outr(PS_PCER, _BV(US_ID));
01222 #endif
01223 #if defined(PMC_PCER)
01224     outr(PMC_PCER, _BV(US_ID));
01225 #endif
01226 #endif
01227 
01228     /* Disable GPIO on UART tx/rx pins. */
01229 #if defined(PIO_PDR) && defined(US_PIO_PINS)
01230     outr(PIO_PDR, US_PIO_PINS);
01231 #endif
01232 
01233 #if defined(PIOA_PDR) && defined(US_PIOA_PINS)
01234     outr(PIOA_PDR, US_PIOA_PINS);
01235 #endif
01236 #if defined(PIOA_ASR) && defined(US_PIOA_PINS_A)
01237     outr(PIOA_ASR, US_PIOA_PINS_A);
01238 #endif
01239 #if defined(PIOA_BSR) && defined(US_PIOA_PINS_B)
01240     outr(PIOA_BSR, US_PIOA_PINS_B);
01241 #endif
01242 
01243 #if defined(PIOB_PDR) && defined(US_PIOB_PINS)
01244     outr(PIOB_PDR, US_PIOB_PINS);
01245 #endif
01246 #if defined(PIOB_ASR) && defined(US_PIOB_PINS_A)
01247     outr(PIOB_ASR, US_PIOB_PINS_A);
01248 #endif
01249 #if defined(PIOB_BSR) && defined(US_PIOB_PINS_B)
01250     outr(PIOB_BSR, US_PIOB_PINS_B);
01251 #endif
01252 
01253 #if defined(PIOC_PDR) && defined(US_PIOC_PINS)
01254     outr(PIOC_PDR, US_PIOC_PINS);
01255 #endif
01256 #if defined(PIOC_ASR) && defined(US_PIOC_PINS_A)
01257     outr(PIOC_ASR, US_PIOC_PINS_A);
01258 #endif
01259 #if defined(PIOC_BSR) && defined(US_PIOC_PINS_B)
01260     outr(PIOC_BSR, US_PIOC_PINS_B);
01261 #endif
01262 
01263     /* Reset UART. */
01264     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01265     /* Disable all UART interrupts. */
01266     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01267     /* Clear UART counter registers. */
01268 #if defined (US_RCR_OFF)
01269     outr(USARTn_BASE + US_RCR_OFF, 0);
01270 #endif
01271 #if defined (US_TCR_OFF)
01272     outr(USARTn_BASE + US_TCR_OFF, 0);
01273 #endif
01274     /* Set UART baud rate generator register. */
01275 #if defined(AT91_PLL_MAINCK)
01276     outr(USARTn_BASE + US_BRGR_OFF, (At91GetMasterClock() / (8 * (115200)) + 1) / 2);
01277 #else
01278     outr(USARTn_BASE + US_BRGR_OFF, (NutGetCpuClock() / (8 * (115200)) + 1) / 2);
01279 #endif
01280     /* Set UART mode to 8 data bits, no parity and 1 stop bit. */
01281 
01282 #ifdef AT91_UART_RS485_MODE
01283     outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1 | US_MODE_RS485);
01284 #else
01285     outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1);
01286 #endif
01287 
01288     return 0;
01289 }
01290 
01291 /*
01292  * \brief Deinitialize the USART hardware driver.
01293  *
01294  * This function is called during device deregistration by the upper
01295  * level USART driver through the USARTDCB jump table.
01296  *
01297  * \return 0 on success, -1 otherwise.
01298  */
01299 static int At91UsartDeinit(void)
01300 {
01301     /* Deregister receive and transmit interrupts. */
01302     NutRegisterIrqHandler(&SIG_UART, 0, 0);
01303 
01304     /* Reset UART. */
01305     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01306     /* Disable all UART interrupts. */
01307     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01308 
01309     /* Disable UART clock. */
01310 #if defined (US_ID)
01311 #if defined(PS_PCDR)
01312     outr(PS_PCDR, _BV(US_ID));
01313 #endif
01314 #if defined(PMC_PCDR)
01315     outr(PMC_PCDR, _BV(US_ID));
01316 #endif
01317 #endif
01318 
01319     /* Enable GPIO on UART tx/rx pins. */
01320 #if defined(PIO_PER) && defined(US_PIO_PINS)
01321     outr(PIO_PER, US_PIO_PINS);
01322 #endif
01323 #if defined(PIOA_PER) && defined(US_PIOA_PINS)
01324     outr(PIOA_PER, US_PIOA_PINS);
01325 #endif
01326 #if defined(PIOB_PER) && defined(US_PIOB_PINS)
01327     outr(PIOB_PER, US_PIOB_PINS);
01328 #endif
01329 #if defined(PIOC_PER) && defined(US_PIOC_PINS)
01330     outr(PIOC_PER, US_PIOC_PINS);
01331 #endif
01332 
01333     /*
01334      * Disabling flow control shouldn't be required here, because it's up
01335      * to the upper level to do this on the last close or during
01336      * deregistration.
01337      */
01338 #ifdef UART_HDX_BIT
01339     /* Deregister transmit complete interrupt. */
01340     if (hdx_control) {
01341         hdx_control = 0;
01342         NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
01343     }
01344 #endif
01345 
01346 #ifdef UART_CTS_BIT
01347     if (cts_sense) {
01348         cts_sense = 0;
01349         cbi(UART_CTS_DDR, UART_CTS_BIT);
01350         /* Deregister CTS sense interrupt. */
01351         NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0);
01352     }
01353 #endif
01354 
01355 #ifdef UART_RTS_BIT
01356     if (rts_control) {
01357         rts_control = 0;
01358         cbi(UART_RTS_DDR, UART_RTS_BIT);
01359     }
01360 #endif
01361 
01362     return 0;
01363 }
01364 

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