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$
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 
00146 static uint_fast8_t hdx_control;
00147 
00148 //#if defined(UART_RTS_BIT) || defined(US_MODE_HWHANDSHAKE)
00155 static uint_fast8_t rts_control;
00156 //#endif
00157 
00158 //#if defined(UART_CTS_BIT) || defined(US_MODE_HWHANDSHAKE)
00165 static uint_fast8_t cts_sense;
00166 //#endif
00167 
00168 #ifdef UART_CTS_BIT
00169 
00179 static void At91UsartCts(void *arg)
00180 {
00181     /* Enable transmit interrupt. */
00182     //sbi(UCSRnB, UDRIE);
00183     /* Disable CTS sense interrupt. */
00184     //cbi(EIMSK, UART_CTS_BIT);
00185 }
00186 #endif
00187 
00188 /*
00189  * \brief USARTn transmitter empty interrupt handler.
00190  *
00191  * Used with half duplex communication to switch from tranmit to receive
00192  * mode after the last character has been transmitted.
00193  *
00194  * \param arg Pointer to the transmitter ring buffer.
00195  */
00196 static void At91UsartTxEmpty(RINGBUF *rbf)
00197 {
00198     /*
00199      * Check if half duplex mode has been enabled and if all characters
00200      * had been sent out.
00201      */
00202     if (hdx_control && (rbf->rbf_cnt == 0)) {
00203         /*
00204          * Switch to receiver mode:
00205          * Enable USART receive, disable transmit.
00206          * Disable TX-Empty IRQ
00207          */
00208         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXDIS);
00209         //USDBG_PIN1_HIGH();
00210 #if defined(UART_HDX_BIT)
00211         UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
00212 #endif
00213     }
00214 }
00215 
00216 /*
00217  * \brief USARTn transmitter ready interrupt handler.
00218  *
00219  * \param rbf Pointer to the transmitter ring buffer.
00220  */
00221 static void At91UsartTxReady(RINGBUF *rbf) 
00222 {
00223     register uint8_t *cp = rbf->rbf_tail;
00224 
00225     /*
00226      * Process pending software flow controls first.
00227      */
00228     if (flow_control & (XON_PENDING | XOFF_PENDING)) {
00229         if (flow_control & XON_PENDING) {
00230             outr(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00231             flow_control |= XOFF_SENT;
00232         } else {
00233             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
00234             flow_control &= ~XOFF_SENT;
00235         }
00236         flow_control &= ~(XON_PENDING | XOFF_PENDING);
00237         return;
00238     }
00239 
00240     if (flow_control & XOFF_RCVD) {
00241         /*
00242          * If XOFF has been received, we disable the transmit interrupts
00243          * and return without sending anything.
00244          */
00245         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00246         return;
00247     }
00248 
00249     if (rbf->rbf_cnt) {
00250 
00251 #ifdef UART_CTS_BIT
00252         /*
00253          * If CTS has been disabled, we disable the transmit interrupts
00254          * and return without sending anything.
00255          */
00256         if (cts_sense && bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00257             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00258             sbi(EIMSK, UART_CTS_BIT);
00259             return;
00260         }
00261 #endif
00262         rbf->rbf_cnt--;
00263 
00264         /*
00265          * Send address in multidrop mode.
00266          */
00267         if (tx_aframe) {
00268             outr(USARTn_BASE + US_CR_OFF, US_SENDA);
00269         }
00270 
00271         /*
00272          * Start transmission of the next character.
00273          */
00274         outr(USARTn_BASE + US_THR_OFF, *cp);
00275 
00276         /*
00277          * Wrap around the buffer pointer if we reached its end.
00278          */
00279         if (++cp == rbf->rbf_last) {
00280             cp = rbf->rbf_start;
00281         }
00282         rbf->rbf_tail = cp;
00283         if (rbf->rbf_cnt == rbf->rbf_lwm) {
00284             NutEventPostFromIrq(&rbf->rbf_que);
00285         }
00286 
00287         /* 
00288          * if software half duplex enabled, we need TX-Empty IRQ for
00289          * detection if last bit of last byte transmission is finished.
00290          */
00291         if( hdx_control && (rbf->rbf_cnt ==0)) {
00292             outr(USARTn_BASE + US_IER_OFF, US_TXEMPTY);     // enable TX-Empty IRQ to enable RX again
00293         }
00294     }
00295 
00296     /*
00297      * Nothing left to transmit, disable interrupt.
00298      */
00299     else {
00300         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00301         rbf->rbf_cnt = 0;
00302         NutEventPostFromIrq(&rbf->rbf_que);
00303     }
00304 }
00305 
00306 
00307 /*
00308  * \brief USARTn receiver ready interrupt handler.
00309  *
00310  *
00311  * \param rbf Pointer to the receiver ring buffer.
00312  */
00313 
00314 static void At91UsartRxReady(RINGBUF *rbf) 
00315 {
00316     register size_t cnt;
00317     register uint8_t ch;
00318 
00319     /*
00320      * We read the received character as early as possible to avoid overflows
00321      * caused by interrupt latency.
00322      */
00323     ch = inb(USARTn_BASE + US_RHR_OFF);
00324 
00325     /* Collect receiver errors. */
00326     rx_errors |= inr(USARTn_BASE + US_CSR_OFF) & (US_OVRE | US_FRAME | US_PARE);
00327 
00328     /*
00329      * Handle software handshake. We have to do this before checking the
00330      * buffer, because flow control must work in write-only mode, where
00331      * there is no receive buffer.
00332      */
00333     if (flow_control) {
00334         /* XOFF character disables transmit interrupts. */
00335         if (ch == ASCII_XOFF) {
00336             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00337             flow_control |= XOFF_RCVD;
00338             return;
00339         }
00340         /* XON enables transmit interrupts. */
00341         else if (ch == ASCII_XON) {
00342             outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00343             flow_control &= ~XOFF_RCVD;
00344             return;
00345         }
00346     }
00347 
00348     /*
00349      * Check buffer overflow.
00350      */
00351     cnt = rbf->rbf_cnt;
00352     if (cnt >= rbf->rbf_siz) {
00353         rx_errors |= US_OVRE;
00354         return;
00355     }
00356 
00357     /* Wake up waiting threads if this is the first byte in the buffer. */
00358     if (cnt++ == 0){
00359         NutEventPostFromIrq(&rbf->rbf_que);
00360     }
00361 
00362     /*
00363      * Check the high watermark for software handshake. If the number of
00364      * buffered bytes is above this mark, then send XOFF.
00365      */
00366     else if (flow_control) {
00367         if(cnt >= rbf->rbf_hwm) {
00368             if((flow_control & XOFF_SENT) == 0) {
00369                 if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00370                     outb(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00371                     flow_control |= XOFF_SENT;
00372                     flow_control &= ~XOFF_PENDING;
00373                 } else {
00374                     flow_control |= XOFF_PENDING;
00375                 }
00376             }
00377         }
00378     }
00379 
00380 #ifdef UART_RTS_BIT
00381     /*
00382      * Check the high watermark for hardware handshake. If the number of
00383      * buffered bytes is above this mark, then disable RTS.
00384      */
00385     else if (rts_control && cnt >= rbf->rbf_hwm) {
00386         sbi(UART_RTS_PORT, UART_RTS_BIT);
00387     }
00388 #endif
00389 
00390     /*
00391      * Store the character and increment and the ring buffer pointer.
00392      */
00393     *rbf->rbf_head++ = ch;
00394     if (rbf->rbf_head == rbf->rbf_last) {
00395         rbf->rbf_head = rbf->rbf_start;
00396     }
00397 
00398     /* Update the ring buffer counter. */
00399     rbf->rbf_cnt = cnt;
00400 }
00401 
00407 static void At91UsartInterrupt(void *arg)
00408 {
00409     USARTDCB *dcb = (USARTDCB *)arg;
00410     ureg_t csr = inr(USARTn_BASE + US_CSR_OFF);
00411 
00412     if (csr & US_RXRDY) {
00413         At91UsartRxReady(&dcb->dcb_rx_rbf);
00414     }
00415     if (csr & US_TXRDY) {
00416         At91UsartTxReady(&dcb->dcb_tx_rbf);
00417     }
00418 
00419     if (csr & US_TXEMPTY) {
00420         At91UsartTxEmpty(&dcb->dcb_tx_rbf);
00421     }
00422 }
00423 
00430 static void At91UsartEnable(void)
00431 {
00432     NutEnterCritical();
00433 
00434     /* Enable UART receiver and transmitter. */
00435     outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
00436 
00437     /* Enable UART receiver and transmitter interrupts. */
00438     outr(USARTn_BASE + US_IER_OFF, US_RXRDY | US_TXRDY);
00439 
00440     if (hdx_control) {
00441         /* Enable transmit complete interrupt. */
00442         outr(USARTn_BASE + US_IER_OFF, US_TXEMPTY);
00443     }
00444 
00445     NutIrqEnable(&SIG_UART);
00446     NutExitCritical();
00447 }
00448 
00452 static void At91UsartDisable(void)
00453 {
00454     /*
00455      * Disable USART interrupts.
00456      */
00457     NutEnterCritical();
00458     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
00459     NutExitCritical();
00460 
00461     /*
00462      * Allow incoming or outgoing character to finish.
00463      */
00464     NutDelay(10);
00465 
00466     /*
00467      * Disable USART transmit and receive.
00468      */
00469     outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXDIS);
00470     outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
00471 }
00472 
00481 static uint32_t At91UsartGetSpeed(void)
00482 {
00483     ureg_t cs = inr(USARTn_BASE + US_MR_OFF);
00484     uint32_t clk;
00485 
00486     clk = NutClockGet(NUT_HWCLK_PERIPHERAL);
00487     if ((cs & US_CLKS) == US_CLKS_MCK8) {
00488         clk /= 8;
00489     }
00490     else if ((cs & US_CLKS) != US_CLKS_MCK) {
00491         clk = 0;
00492     }
00493     return clk / (16UL * (inr(USARTn_BASE + US_BRGR_OFF) & 0xFFFF));
00494 }
00495 
00506 static int At91UsartSetSpeed(uint32_t rate)
00507 {
00508     At91UsartDisable();
00509     outr(USARTn_BASE + US_BRGR_OFF, (NutClockGet(NUT_HWCLK_PERIPHERAL) / (8 * (rate)) + 1) / 2);
00510     At91UsartEnable();
00511 
00512     return 0;
00513 }
00514 
00523 static uint8_t At91UsartGetDataBits(void)
00524 {
00525     ureg_t val = inr(USARTn_BASE + US_MR_OFF);
00526 
00527     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00528         val = 9;
00529     }
00530     else {
00531         val &= US_CHRL;
00532         if (val == US_CHRL_5) {
00533             val = 5;
00534         }
00535         else if (val == US_CHRL_6) {
00536             val = 6;
00537         }
00538         else if (val == US_CHRL_7) {
00539             val = 7;
00540         }
00541         else {
00542             val = 8;
00543         }
00544     }
00545     return (uint8_t)val;
00546 }
00547 
00556 static int At91UsartSetDataBits(uint8_t bits)
00557 {
00558     ureg_t val = inr(USARTn_BASE + US_MR_OFF);
00559 
00560     if (bits == 9) {
00561         val &= ~US_PAR;
00562         val |= US_PAR_MULTIDROP;
00563     }
00564     else {
00565         val &= ~US_CHRL;
00566         if (bits == 5) {
00567             val |= US_CHRL_5;
00568         }
00569         else if (bits == 6) {
00570             val |= US_CHRL_6;
00571         }
00572         else if (bits == 7) {
00573             val |= US_CHRL_7;
00574         }
00575         else if (bits == 8) {
00576             val |= US_CHRL_8;
00577         }
00578     }
00579 
00580     At91UsartDisable();
00581     outr(USARTn_BASE + US_MR_OFF, val);
00582     At91UsartEnable();
00583 
00584     /*
00585      * Verify the result.
00586      */
00587     if (At91UsartGetDataBits() != bits) {
00588         return -1;
00589     }
00590     return 0;
00591 }
00592 
00601 static uint8_t At91UsartGetParity(void)
00602 {
00603     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_PAR;
00604 
00605     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00606         val = 9;
00607     }
00608     else {
00609         if (val == US_PAR_ODD) {
00610             val = 1;
00611         }
00612         else if (val == US_PAR_EVEN) {
00613             val = 2;
00614         }
00615         else {
00616             val = 0;
00617         }
00618     }
00619     return (uint8_t)val;
00620 }
00621 
00632 static int At91UsartSetParity(uint8_t mode)
00633 {
00634     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_PAR;
00635 
00636     switch (mode) {
00637     case 0:
00638         val |= US_PAR_NO;
00639         break;
00640     case 1:
00641         val |= US_PAR_ODD;
00642         break;
00643     case 2:
00644         val |= US_PAR_EVEN;
00645         break;
00646     }
00647     At91UsartDisable();
00648     outr(USARTn_BASE + US_MR_OFF, val);
00649     At91UsartEnable();
00650 
00651     /*
00652      * Verify the result.
00653      */
00654     if (At91UsartGetParity() != mode) {
00655         return -1;
00656     }
00657     return 0;
00658 }
00659 
00668 static uint8_t At91UsartGetStopBits(void)
00669 {
00670     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_NBSTOP;
00671     if (val == US_NBSTOP_1) {
00672         val = 1;
00673     }
00674     else if (val == US_NBSTOP_2) {
00675         val = 2;
00676     }
00677     else {
00678         val = 3;
00679     }
00680     return (uint8_t)val;
00681 }
00682 
00691 static int At91UsartSetStopBits(uint8_t bits)
00692 {
00693     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_NBSTOP;
00694 
00695     switch(bits) {
00696     case 1:
00697         val |= US_NBSTOP_1;
00698         break;
00699     case 2:
00700         val |= US_NBSTOP_2;
00701         break;
00702     case 3:
00703         val |= US_NBSTOP_1_5;
00704         break;
00705     }
00706     At91UsartDisable();
00707     outr(USARTn_BASE + US_MR_OFF, val);
00708     At91UsartEnable();
00709 
00710     /*
00711      * Verify the result.
00712      */
00713     if (At91UsartGetStopBits() != bits) {
00714         return -1;
00715     }
00716     return 0;
00717 }
00718 
00724 static uint32_t At91UsartGetStatus(void)
00725 {
00726     uint32_t rc = 0;
00727 #if defined(US_MODE_HWHANDSHAKE)
00728     uint32_t csr = inr(USARTn_BASE + US_CSR_OFF);
00729 #endif
00730 
00731     /*
00732      * Set receiver error flags.
00733      */
00734     if ((rx_errors & US_FRAME) != 0) {
00735         rc |= UART_FRAMINGERROR;
00736     }
00737     if ((rx_errors & US_OVRE) != 0) {
00738         rc |= UART_OVERRUNERROR;
00739     }
00740     if ((rx_errors & US_PARE) != 0) {
00741         rc |= UART_PARITYERROR;
00742     }
00743 
00744     /*
00745      * Determine software handshake status. The flow control status may
00746      * change during interrupt, but this doesn't really hurt us.
00747      */
00748     if (flow_control) {
00749         if (flow_control & XOFF_SENT) {
00750             rc |= UART_RXDISABLED;
00751         }
00752         if (flow_control & XOFF_RCVD) {
00753             rc |= UART_TXDISABLED;
00754         }
00755     }
00756 
00757     /*
00758      * Determine hardware handshake control status.
00759      */
00760 #if defined(UART_RTS_BIT)
00761     if (bit_is_set(UART_RTS_PORT, UART_RTS_BIT)) {
00762         rc |= UART_RTSDISABLED;
00763         if (rts_control) {
00764             rc |= UART_RXDISABLED;
00765         }
00766     } else {
00767         rc |= UART_RTSENABLED;
00768     }
00769 #elif defined(US_MODE_HWHANDSHAKE)
00770     /* How to find out? */
00771 #endif
00772 
00773     /*
00774      * Determine hardware handshake sense status.
00775      */
00776 #ifdef UART_CTS_BIT
00777     if (bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00778         rc |= UART_CTSDISABLED;
00779         if (cts_sense) {
00780             rc |= UART_RXDISABLED;
00781         }
00782     } else {
00783         rc |= UART_CTSENABLED;
00784     }
00785 #elif defined(US_MODE_HWHANDSHAKE)
00786     if (csr & US_CTS) {
00787         rc |= UART_CTSDISABLED;
00788         if (cts_sense) {
00789             rc |= UART_RXDISABLED;
00790         }
00791     } else {
00792         rc |= UART_CTSENABLED;
00793     }
00794 #endif
00795 
00796     /*
00797      * Determine hardware modem sense status.
00798      */
00799 #if defined(US_MODE_HWHANDSHAKE) && 0
00800     /* I'm confused. Awful flag mismatch? Why do we have uart.h and usart.h? */
00801     if (csr & US_RI) {
00802         rc |= UART_RIDISABLED;
00803     } else {
00804         rc |= UART_RIENABLED;
00805     }
00806     if (csr & US_DSR) {
00807         rc |= UART_DSRDISABLED;
00808     } else {
00809         rc |= UART_DSRENABLED;
00810     }
00811     if (csr & US_DCD) {
00812         rc |= UART_DCDDISABLED;
00813     } else {
00814         rc |= UART_DCDENABLED;
00815     }
00816 #endif
00817 
00818     /*
00819      * If transmitter and receiver haven't been detected disabled by any
00820      * of the checks above, then they are probably enabled.
00821      */
00822     if ((rc & UART_RXDISABLED) == 0) {
00823         rc |= UART_RXENABLED;
00824     }
00825     if ((rc & UART_TXDISABLED) == 0) {
00826         rc |= UART_TXENABLED;
00827     }
00828 
00829     /*
00830      * Process multidrop setting.
00831      */
00832     if (tx_aframe) {
00833         rc |= UART_TXADDRFRAME;
00834     } else {
00835         rc |= UART_TXNORMFRAME;
00836     }
00837     return rc;
00838 }
00839 
00847 static int At91UsartSetStatus(uint32_t flags)
00848 {
00849     /*
00850      * Process software handshake control.
00851      */
00852     if (flow_control) {
00853 
00854         /* Access to the flow control status must be atomic. */
00855         NutEnterCritical();
00856 
00857         /*
00858          * Enabling or disabling the receiver means to behave like
00859          * having sent a XON or XOFF character resp.
00860          */
00861         if (flags & UART_RXENABLED) {
00862             flow_control &= ~XOFF_SENT;
00863         } else if (flags & UART_RXDISABLED) {
00864             flow_control |= XOFF_SENT;
00865         }
00866 
00867         /*
00868          * Enabling or disabling the transmitter means to behave like
00869          * having received a XON or XOFF character resp.
00870          */
00871         if (flags & UART_TXENABLED) {
00872             flow_control &= ~XOFF_RCVD;
00873         } else if (flags & UART_TXDISABLED) {
00874             flow_control |= XOFF_RCVD;
00875         }
00876         NutExitCritical();
00877     }
00878 
00879     /*
00880      * Process hardware handshake control.
00881      */
00882 #if defined(UART_RTS_BIT)
00883     /* Manually controlled via GPIO. */
00884     if (rts_control) {
00885         if (flags & UART_RXDISABLED) {
00886             sbi(UART_RTS_PORT, UART_RTS_BIT);
00887         }
00888         if (flags & UART_RXENABLED) {
00889             cbi(UART_RTS_PORT, UART_RTS_BIT);
00890         }
00891     }
00892     if (flags & UART_RTSDISABLED) {
00893         sbi(UART_RTS_PORT, UART_RTS_BIT);
00894     }
00895     if (flags & UART_RTSENABLED) {
00896         cbi(UART_RTS_PORT, UART_RTS_BIT);
00897     }
00898 #elif defined(US_MODE_HWHANDSHAKE)
00899     /* Build in hardware. */
00900     if (rts_control) {
00901         if (flags & UART_RXDISABLED) {
00902             outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
00903         }
00904         if (flags & UART_RXENABLED) {
00905             outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
00906         }
00907     }
00908     if (flags & UART_RTSDISABLED) {
00909         outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
00910     }
00911     if (flags & UART_RTSENABLED) {
00912         outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
00913     }
00914 #endif
00915 
00916     /*
00917      * Process hardware modem control.
00918      */
00919 #if defined(UART_DTR_BIT)
00920     /* Manually controlled via GPIO. */
00921     if (flags & UART_DTRDISABLED) {
00922         sbi(UART_DTR_PORT, UART_DTR_BIT);
00923     }
00924     if (flags & UART_DTRENABLED) {
00925         cbi(UART_DTR_PORT, UART_DTR_BIT);
00926     }
00927 #elif defined(US_MODE_HWHANDSHAKE)
00928     /* Build in hardware. */
00929     if (flags & UART_DTRDISABLED) {
00930         outr(USARTn_BASE + US_CR_OFF, US_DTRDIS);
00931     }
00932     if (flags & UART_DTRENABLED) {
00933         outr(USARTn_BASE + US_CR_OFF, US_DTREN);
00934     }
00935 #endif
00936 
00937     /*
00938      * Process multidrop setting.
00939      */
00940     if (flags & UART_TXADDRFRAME) {
00941         tx_aframe = 1;
00942     }
00943     if (flags & UART_TXNORMFRAME) {
00944         tx_aframe = 0;
00945     }
00946 
00947     /*
00948      * Clear UART receive errors.
00949      */
00950     if (flags & UART_ERRORS) {
00951         outr(USARTn_BASE + US_CR_OFF, US_RSTSTA);
00952     }
00953 
00954     /*
00955      * Verify the result.
00956      */
00957     if ((At91UsartGetStatus() & ~UART_ERRORS) != flags) {
00958         return -1;
00959     }
00960     return 0;
00961 }
00962 
00972 static uint8_t At91UsartGetClockMode(void)
00973 {
00974     uint8_t rc = 0;
00975 
00976     return rc;
00977 }
00978 
00990 static int At91UsartSetClockMode(uint8_t mode)
00991 {
00992     /*
00993      * Verify the result.
00994      */
00995     if (At91UsartGetClockMode() != mode) {
00996         return -1;
00997     }
00998     return 0;
00999 }
01000 
01009 static uint32_t At91UsartGetFlowControl(void)
01010 {
01011     uint32_t rc = 0;
01012 
01013     if (flow_control) {
01014         rc |= USART_MF_XONXOFF;
01015     } else {
01016         rc &= ~USART_MF_XONXOFF;
01017     }
01018 
01019 #ifdef UART_RTS_BIT
01020     if (rts_control) {
01021         rc |= USART_MF_RTSCONTROL;
01022     } else {
01023         rc &= ~USART_MF_RTSCONTROL;
01024     }
01025 #endif
01026 
01027 #ifdef UART_CTS_BIT
01028     if (cts_sense) {
01029         rc |= USART_MF_CTSSENSE;
01030     } else {
01031         rc &= ~USART_MF_CTSSENSE;
01032     }
01033 #endif
01034 
01035     if (hdx_control) {
01036         rc |= USART_MF_HALFDUPLEX;
01037     } else {
01038         rc &= ~USART_MF_HALFDUPLEX;
01039     }
01040 
01041     return rc;
01042 }
01043 
01054 static int At91UsartSetFlowControl(uint32_t flags)
01055 {
01056     /*
01057      * Set software handshake mode.
01058      */
01059     if (flags & USART_MF_XONXOFF) {
01060         if(flow_control == 0) {
01061             NutEnterCritical();
01062             flow_control = 1 | XOFF_SENT;  /* force XON to be sent on next read */
01063             NutExitCritical();
01064         }
01065     } else {
01066         NutEnterCritical();
01067         flow_control = 0;
01068         NutExitCritical();
01069     }
01070 
01071     /*
01072      * Set RTS control mode.
01073      */
01074     if (flags & USART_MF_RTSCONTROL) {
01075 #if defined(UART_RTS_BIT)
01076         sbi(UART_RTS_PORT, UART_RTS_BIT);
01077         sbi(UART_RTS_DDR, UART_RTS_BIT);
01078         rts_control = 1;
01079 #endif
01080     } else if (rts_control) {
01081         rts_control = 0;
01082 #if defined(UART_RTS_BIT)
01083         cbi(UART_RTS_DDR, UART_RTS_BIT);
01084 #endif
01085     }
01086 
01087 /*
01088  * Set CTS sense mode.
01089  */
01090     if (flags & USART_MF_CTSSENSE) {
01091 #if defined(UART_CTS_BIT)
01092         /* Register CTS sense interrupt. */
01093         if (NutRegisterIrqHandler(&UART_CTS_SIGNAL, At91UsartCts, 0)) {
01094             return -1;
01095         }
01096         sbi(UART_CTS_PORT, UART_CTS_BIT);
01097         cbi(UART_CTS_DDR, UART_CTS_BIT);
01098         cts_sense = 1;
01099 #elif defined(US_MODE_HWHANDSHAKE)
01100         uint32_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_MODE;
01101 
01102         outr(USARTn_BASE + US_MR_OFF, val | US_MODE_HWHANDSHAKE);
01103         cts_sense = 1;
01104         rts_control = 1;
01105 #endif
01106     } else if (cts_sense) {
01107 #if defined(UART_CTS_BIT)
01108         /* Deregister CTS sense interrupt. */
01109         NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0);
01110         cbi(UART_CTS_DDR, UART_CTS_BIT);
01111 #elif defined(US_MODE_HWHANDSHAKE)
01112         uint32_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_MODE;
01113 
01114         outr(USARTn_BASE + US_MR_OFF, val);
01115         rts_control = 0;
01116 #endif
01117         cts_sense = 0;
01118     }
01119 
01120     /*
01121      * Set half duplex mode.
01122      */
01123     if (flags & USART_MF_HALFDUPLEX) {
01124 
01125         /* Enable USART receive, disable transmit. */
01126         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXDIS);
01127         /* Enable Half-Duplex Mode */
01128         hdx_control = 1;
01129         /* Enable TX-Empty IRQ */
01130         outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
01131 
01132 #if defined(UART_HDX_BIT)        
01133         /* Initially enable the receiver. */
01134         UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
01135         sbi(UART_HDX_DDR, UART_HDX_BIT);
01136 #endif
01137     } 
01138     else if (hdx_control) {
01139         hdx_control = 0;
01140         /* disable transmit complete interrupt */
01141         outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
01142         /* Deregister transmit complete interrupt. */
01143 //         NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
01144 #if defined(UART_HDX_BIT)        
01145         cbi(UART_HDX_DDR, UART_HDX_BIT);
01146 #endif
01147     }
01148 
01149     /*
01150      * Verify the result.
01151      */
01152     if (At91UsartGetFlowControl() != flags) {
01153         return -1;
01154     }
01155     return 0;
01156 }
01157 
01165 static void At91UsartTxStart(void)
01166 {
01167     if (hdx_control) {
01168         /*
01169         * Disable USART receive, enable transmit.
01170         */
01171         outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXEN);
01172         //USDBG_PIN2_LOW();
01173 #if defined(UART_HDX_BIT)
01174         UART_HDX_TX(UART_HDX_PORT, UART_HDX_BIT);
01175 #endif
01176     }
01177     /* Enable transmit interrupts. */
01178     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
01179 }
01180 
01189 static void At91UsartRxStart(void)
01190 {
01191     /*
01192      * Do any required software flow control.
01193      */
01194     if (flow_control && (flow_control & XOFF_SENT) != 0) {
01195         NutEnterCritical();
01196         if ((inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY)) {
01197             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
01198             flow_control &= ~XON_PENDING;
01199         } else {
01200             flow_control |= XON_PENDING;
01201         }
01202         flow_control &= ~(XOFF_SENT | XOFF_PENDING);
01203         NutExitCritical();
01204     }
01205 #ifdef UART_RTS_BIT
01206     if (rts_control) {
01207         /* Enable RTS. */
01208         cbi(UART_RTS_PORT, UART_RTS_BIT);
01209     }
01210 #endif
01211 }
01212 
01213 /*
01214  * \brief Initialize the USART hardware driver.
01215  *
01216  * This function is called during device registration by the upper level
01217  * USART driver through the USARTDCB jump table.
01218  *
01219  * \return 0 on success, -1 otherwise.
01220  */
01221 static int At91UsartInit(void)
01222 {
01223     /*
01224      * Register receive and transmit interrupts.
01225      */
01226     if (NutRegisterIrqHandler(&SIG_UART, At91UsartInterrupt, &dcb_usart)) {
01227         return -1;
01228     }
01229 
01230     /* Enable UART clock. */
01231 #if defined(US_ID)
01232 #if defined(PS_PCER)
01233     outr(PS_PCER, _BV(US_ID));
01234 #endif
01235 #if defined(PMC_PCER)
01236     outr(PMC_PCER, _BV(US_ID));
01237 #endif
01238 #endif
01239 
01240     /* Disable GPIO on UART tx/rx pins. */
01241 #if defined(PIO_PDR) && defined(US_PIO_PINS)
01242     outr(PIO_PDR, US_PIO_PINS);
01243 #endif
01244 
01245 #if defined(PIOA_PDR) && defined(US_PIOA_PINS)
01246     outr(PIOA_PDR, US_PIOA_PINS);
01247 #endif
01248 #if defined(PIOA_ASR) && defined(US_PIOA_PINS_A)
01249     outr(PIOA_ASR, US_PIOA_PINS_A);
01250 #endif
01251 #if defined(PIOA_BSR) && defined(US_PIOA_PINS_B)
01252     outr(PIOA_BSR, US_PIOA_PINS_B);
01253 #endif
01254 
01255 #if defined(PIOB_PDR) && defined(US_PIOB_PINS)
01256     outr(PIOB_PDR, US_PIOB_PINS);
01257 #endif
01258 #if defined(PIOB_ASR) && defined(US_PIOB_PINS_A)
01259     outr(PIOB_ASR, US_PIOB_PINS_A);
01260 #endif
01261 #if defined(PIOB_BSR) && defined(US_PIOB_PINS_B)
01262     outr(PIOB_BSR, US_PIOB_PINS_B);
01263 #endif
01264 
01265 #if defined(PIOC_PDR) && defined(US_PIOC_PINS)
01266     outr(PIOC_PDR, US_PIOC_PINS);
01267 #endif
01268 #if defined(PIOC_ASR) && defined(US_PIOC_PINS_A)
01269     outr(PIOC_ASR, US_PIOC_PINS_A);
01270 #endif
01271 #if defined(PIOC_BSR) && defined(US_PIOC_PINS_B)
01272     outr(PIOC_BSR, US_PIOC_PINS_B);
01273 #endif
01274 
01275     /* Reset UART. */
01276     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01277     /* Disable all UART interrupts. */
01278     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01279     /* Clear UART counter registers. */
01280 #if defined (US_RCR_OFF)
01281     outr(USARTn_BASE + US_RCR_OFF, 0);
01282 #endif
01283 #if defined (US_TCR_OFF)
01284     outr(USARTn_BASE + US_TCR_OFF, 0);
01285 #endif
01286     /* Set UART baud rate generator register. */
01287 #if defined(AT91_PLL_MAINCK)
01288     outr(USARTn_BASE + US_BRGR_OFF, (At91GetMasterClock() / (8 * (115200)) + 1) / 2);
01289 #else
01290     outr(USARTn_BASE + US_BRGR_OFF, (NutGetCpuClock() / (8 * (115200)) + 1) / 2);
01291 #endif
01292     /* Set UART mode to 8 data bits, no parity and 1 stop bit. */
01293 
01294 #ifdef AT91_UART_RS485_MODE
01295     outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1 | US_MODE_RS485);
01296 #else
01297     outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1);
01298 #endif
01299 
01300     return 0;
01301 }
01302 
01303 /*
01304  * \brief Deinitialize the USART hardware driver.
01305  *
01306  * This function is called during device deregistration by the upper
01307  * level USART driver through the USARTDCB jump table.
01308  *
01309  * \return 0 on success, -1 otherwise.
01310  */
01311 static int At91UsartDeinit(void)
01312 {
01313     /* Deregister receive and transmit interrupts. */
01314     NutRegisterIrqHandler(&SIG_UART, 0, 0);
01315 
01316     /* Reset UART. */
01317     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01318     /* Disable all UART interrupts. */
01319     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01320 
01321     /* Disable UART clock. */
01322 #if defined (US_ID)
01323 #if defined(PS_PCDR)
01324     outr(PS_PCDR, _BV(US_ID));
01325 #endif
01326 #if defined(PMC_PCDR)
01327     outr(PMC_PCDR, _BV(US_ID));
01328 #endif
01329 #endif
01330 
01331     /* Enable GPIO on UART tx/rx pins. */
01332 #if defined(PIO_PER) && defined(US_PIO_PINS)
01333     outr(PIO_PER, US_PIO_PINS);
01334 #endif
01335 #if defined(PIOA_PER) && defined(US_PIOA_PINS)
01336     outr(PIOA_PER, US_PIOA_PINS);
01337 #endif
01338 #if defined(PIOB_PER) && defined(US_PIOB_PINS)
01339     outr(PIOB_PER, US_PIOB_PINS);
01340 #endif
01341 #if defined(PIOC_PER) && defined(US_PIOC_PINS)
01342     outr(PIOC_PER, US_PIOC_PINS);
01343 #endif
01344 
01345     /*
01346      * Disabling flow control shouldn't be required here, because it's up
01347      * to the upper level to do this on the last close or during
01348      * deregistration.
01349      */
01350 #ifdef UART_HDX_BIT
01351     /* Deregister transmit complete interrupt. */
01352     if (hdx_control) {
01353         hdx_control = 0;
01354 //         NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
01355     }
01356 #endif
01357 
01358 #ifdef UART_CTS_BIT
01359     if (cts_sense) {
01360         cts_sense = 0;
01361         cbi(UART_CTS_DDR, UART_CTS_BIT);
01362         /* Deregister CTS sense interrupt. */
01363         NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0);
01364     }
01365 #endif
01366 
01367 #ifdef UART_RTS_BIT
01368     if (rts_control) {
01369         rts_control = 0;
01370         cbi(UART_RTS_DDR, UART_RTS_BIT);
01371     }
01372 #endif
01373 
01374     return 0;
01375 }
01376 

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