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.11  2008/08/11 06:59:13  haraldkipp
00041  * BSD types replaced by stdint types (feature request #1282721).
00042  *
00043  * Revision 1.10  2008/07/31 09:43:25  haraldkipp
00044  * Initializing peripheral control registers in a more general way.
00045  * Fixes bug #2032960.
00046  *
00047  * Revision 1.9  2008/04/18 13:24:56  haraldkipp
00048  * Added Szemzo Andras' RS485 patch.
00049  *
00050  * Revision 1.8  2008/02/15 16:59:27  haraldkipp
00051  * Spport for AT91SAM7SE512 added.
00052  *
00053  * Revision 1.7  2007/10/04 20:05:51  olereinhardt
00054  * Support for SAM7S256 added
00055  *
00056  * Revision 1.6  2006/08/31 19:01:44  haraldkipp
00057  * Using the processor clock for baud rate calculations failed
00058  * on the SAM9, if the master clock is further divided. This
00059  * had been fixed.
00060  *
00061  * Revision 1.5  2006/08/05 11:54:06  haraldkipp
00062  * Special register functions should not be based on MCU definitions but on
00063  * register definitions.
00064  *
00065  * Revision 1.4  2006/07/05 07:55:23  haraldkipp
00066  * Daidai's support for AT91SAM7X added.
00067  *
00068  * Revision 1.3  2006/06/28 17:18:40  haraldkipp
00069  * Temporarly exclude AT91R40008 specific register settings from building
00070  * for AT91SAM7X.
00071  *
00072  * Revision 1.2  2006/01/05 16:47:32  haraldkipp
00073  * Baudrate calculation is now based on NutGetCpuClock().
00074  *
00075  * Revision 1.1  2005/11/20 14:40:28  haraldkipp
00076  * Added interrupt driven UART driver for AT91.
00077  *
00078  */
00079 
00080 #include <cfg/clock.h>
00081 
00082 #include <sys/atom.h>
00083 #include <sys/event.h>
00084 #include <sys/timer.h>
00085 
00086 #include <dev/irqreg.h>
00087 
00088 #include <dev/usartat91.h>
00089 
00094 
00095 /* \brief ASCII code for software flow control, starts transmitter. */
00096 #define ASCII_XON   0x11
00097 /* \brief ASCII code for software flow control, stops transmitter. */
00098 #define ASCII_XOFF  0x13
00099 
00100 /* \brief XON transmit pending flag. */
00101 #define XON_PENDING     0x10
00102 /* \brief XOFF transmit pending flag. */
00103 #define XOFF_PENDING    0x20
00104 /* \brief XOFF sent flag. */
00105 #define XOFF_SENT       0x40
00106 /* \brief XOFF received flag. */
00107 #define XOFF_RCVD       0x80
00108 
00109 
00113 static ureg_t rx_errors;
00114 
00118 static ureg_t flow_control;
00119 
00123 static ureg_t tx_aframe;
00124 
00125 #ifdef UART_HDX_BIT
00126     /* define in cfg/modem.h */
00127     #ifdef UART_HDX_FLIP_BIT    /* same as RTS toggle by Windows NT driver */
00128         #define UART_HDX_TX     cbi
00129         #define UART_HDX_RX     sbi
00130     #else                       /* previous usage by Ethernut */
00131         #define UART_HDX_TX     sbi
00132         #define UART_HDX_RX     cbi
00133     #endif
00134 #endif
00135 
00136 
00137 #ifdef UART_HDX_BIT
00138 
00144 static ureg_t hdx_control;
00145 #endif
00146 
00147 #ifdef UART_RTS_BIT
00148 
00154 static ureg_t rts_control;
00155 #endif
00156 
00157 #ifdef UART_CTS_BIT
00158 
00164 static ureg_t cts_sense;
00165 #endif
00166 
00167 #ifdef UART_CTS_BIT
00168 
00178 static void At91UsartCts(void *arg)
00179 {
00180     /* Enable transmit interrupt. */
00181     //sbi(UCSRnB, UDRIE);
00182     /* Disable CTS sense interrupt. */
00183     //cbi(EIMSK, UART_CTS_BIT);
00184 }
00185 #endif
00186 
00187 #ifdef UART_HDX_BIT
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  * This routine exists only if the hardware configuration defines a
00195  * port bit to switch between receive and transmit mode.
00196  *
00197  * \param arg Pointer to the transmitter ring buffer.
00198  */
00199 static void At91UsartTxEmpty(RINGBUF *rbf)
00200 {
00201     /*
00202      * Check if half duplex mode has been enabled and if all characters
00203      * had been sent out.
00204      */
00205     if (hdx_control && rbf->rbf_cnt == 0) {
00206         /* Switch to receiver mode. */
00207         UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
00208     }
00209 }
00210 #endif
00211 
00212 /*
00213  * \brief USARTn transmitter ready interrupt handler.
00214  *
00215  * \param rbf Pointer to the transmitter ring buffer.
00216  */
00217 static void At91UsartTxReady(RINGBUF *rbf) 
00218 {
00219     register uint8_t *cp = rbf->rbf_tail;
00220 
00221     /*
00222      * Process pending software flow controls first.
00223      */
00224     if (flow_control & (XON_PENDING | XOFF_PENDING)) {
00225         if (flow_control & XON_PENDING) {
00226             outr(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00227             flow_control |= XOFF_SENT;
00228         } else {
00229             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
00230             flow_control &= ~XOFF_SENT;
00231         }
00232         flow_control &= ~(XON_PENDING | XOFF_PENDING);
00233         return;
00234     }
00235 
00236     if (flow_control & XOFF_RCVD) {
00237         /*
00238          * If XOFF has been received, we disable the transmit interrupts
00239          * and return without sending anything.
00240          */
00241         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00242         return;
00243     }
00244 
00245     if (rbf->rbf_cnt) {
00246 
00247 #ifdef UART_CTS_BIT
00248         /*
00249          * If CTS has been disabled, we disable the transmit interrupts
00250          * and return without sending anything.
00251          */
00252         if (cts_sense && bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00253             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00254             sbi(EIMSK, UART_CTS_BIT);
00255             return;
00256         }
00257 #endif
00258         rbf->rbf_cnt--;
00259 
00260         /*
00261          * Send address in multidrop mode.
00262          */
00263         if (tx_aframe) {
00264             outr(USARTn_BASE + US_CR_OFF, US_SENDA);
00265         }
00266 
00267         /*
00268          * Start transmission of the next character.
00269          */
00270         outr(USARTn_BASE + US_THR_OFF, *cp);
00271 
00272         /*
00273          * Wrap around the buffer pointer if we reached its end.
00274          */
00275         if (++cp == rbf->rbf_last) {
00276             cp = rbf->rbf_start;
00277         }
00278         rbf->rbf_tail = cp;
00279         if (rbf->rbf_cnt == rbf->rbf_lwm) {
00280             NutEventPostFromIrq(&rbf->rbf_que);
00281         }
00282     }
00283 
00284     /*
00285      * Nothing left to transmit, disable interrupt.
00286      */
00287     else {
00288         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00289         rbf->rbf_cnt = 0;
00290         NutEventPostFromIrq(&rbf->rbf_que);
00291     }
00292 }
00293 
00294 
00295 /*
00296  * \brief USARTn receiver ready interrupt handler.
00297  *
00298  *
00299  * \param rbf Pointer to the receiver ring buffer.
00300  */
00301 
00302 static void At91UsartRxReady(RINGBUF *rbf) 
00303 {
00304     register size_t cnt;
00305     register uint8_t ch;
00306 
00307     /*
00308      * We read the received character as early as possible to avoid overflows
00309      * caused by interrupt latency.
00310      */
00311     ch = inb(USARTn_BASE + US_RHR_OFF);
00312 
00313     /* Collect receiver errors. */
00314     rx_errors |= inr(USARTn_BASE + US_CSR_OFF) & (US_OVRE | US_FRAME | US_PARE);
00315 
00316     /*
00317      * Handle software handshake. We have to do this before checking the
00318      * buffer, because flow control must work in write-only mode, where
00319      * there is no receive buffer.
00320      */
00321     if (flow_control) {
00322         /* XOFF character disables transmit interrupts. */
00323         if (ch == ASCII_XOFF) {
00324             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00325             flow_control |= XOFF_RCVD;
00326             return;
00327         }
00328         /* XON enables transmit interrupts. */
00329         else if (ch == ASCII_XON) {
00330             outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00331             flow_control &= ~XOFF_RCVD;
00332             return;
00333         }
00334     }
00335 
00336     /*
00337      * Check buffer overflow.
00338      */
00339     cnt = rbf->rbf_cnt;
00340     if (cnt >= rbf->rbf_siz) {
00341         rx_errors |= US_OVRE;
00342         return;
00343     }
00344 
00345     /* Wake up waiting threads if this is the first byte in the buffer. */
00346     if (cnt++ == 0){
00347         NutEventPostFromIrq(&rbf->rbf_que);
00348     }
00349 
00350     /*
00351      * Check the high watermark for software handshake. If the number of
00352      * buffered bytes is above this mark, then send XOFF.
00353      */
00354     else if (flow_control) {
00355         if(cnt >= rbf->rbf_hwm) {
00356             if((flow_control & XOFF_SENT) == 0) {
00357                 if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00358                     outb(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00359                     flow_control |= XOFF_SENT;
00360                     flow_control &= ~XOFF_PENDING;
00361                 } else {
00362                     flow_control |= XOFF_PENDING;
00363                 }
00364             }
00365         }
00366     }
00367 
00368 #ifdef UART_RTS_BIT
00369     /*
00370      * Check the high watermark for hardware handshake. If the number of
00371      * buffered bytes is above this mark, then disable RTS.
00372      */
00373     else if (rts_control && cnt >= rbf->rbf_hwm) {
00374         sbi(UART_RTS_PORT, UART_RTS_BIT);
00375     }
00376 #endif
00377 
00378     /*
00379      * Store the character and increment and the ring buffer pointer.
00380      */
00381     *rbf->rbf_head++ = ch;
00382     if (rbf->rbf_head == rbf->rbf_last) {
00383         rbf->rbf_head = rbf->rbf_start;
00384     }
00385 
00386     /* Update the ring buffer counter. */
00387     rbf->rbf_cnt = cnt;
00388 }
00389 
00395 static void At91UsartInterrupt(void *arg)
00396 {
00397     USARTDCB *dcb = (USARTDCB *)arg;
00398     ureg_t csr = inr(USARTn_BASE + US_CSR_OFF);
00399 
00400     if (csr & US_RXRDY) {
00401         At91UsartRxReady(&dcb->dcb_rx_rbf);
00402     }
00403     if (csr & US_TXRDY) {
00404         At91UsartTxReady(&dcb->dcb_tx_rbf);
00405     }
00406 
00407 #ifdef UART_HDX_BIT
00408     if (csr & US_TXEMPTY) {
00409         At91UsartTxEmpty(&dcb->dcb_tx_rbf);
00410     }
00411 #endif /*  UART_HDX_BIT */
00412 }
00413 
00420 static void At91UsartEnable(void)
00421 {
00422     NutEnterCritical();
00423 
00424     /* Enable UART receiver and transmitter. */
00425     outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
00426 
00427     /* Enable UART receiver and transmitter interrupts. */
00428     outr(USARTn_BASE + US_IER_OFF, US_RXRDY | US_TXRDY);
00429     NutIrqEnable(&SIG_UART);
00430 
00431 #ifdef UART_HDX_BIT
00432     if (hdx_control) {
00433         /* Enable transmit complete interrupt. */
00434         sbi(UCSRnB, TXCIE);
00435     }
00436 #endif
00437 
00438     NutExitCritical();
00439 }
00440 
00444 static void At91UsartDisable(void)
00445 {
00446     /*
00447      * Disable USART interrupts.
00448      */
00449     NutEnterCritical();
00450     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
00451     NutExitCritical();
00452 
00453     /*
00454      * Allow incoming or outgoing character to finish.
00455      */
00456     NutDelay(10);
00457 
00458     /*
00459      * Disable USART transmit and receive.
00460      */
00461     outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXDIS);
00462 }
00463 
00472 static uint32_t At91UsartGetSpeed(void)
00473 {
00474     ureg_t cs = inr(USARTn_BASE + US_MR_OFF);
00475     uint32_t clk;
00476 
00477 #if defined(AT91_PLL_MAINCK)
00478     clk = At91GetMasterClock();
00479 #else
00480     clk = NutGetCpuClock();
00481 #endif
00482     if ((cs & US_CLKS) == US_CLKS_MCK8) {
00483         clk /= 8;
00484     }
00485     else if ((cs & US_CLKS) != US_CLKS_MCK) {
00486         clk = 0;
00487     }
00488     return clk / (16UL * (inr(USARTn_BASE + US_BRGR_OFF) & 0xFFFF));
00489 }
00490 
00501 static int At91UsartSetSpeed(uint32_t rate)
00502 {
00503     At91UsartDisable();
00504 #if defined(AT91_PLL_MAINCK)
00505     outr(USARTn_BASE + US_BRGR_OFF, (At91GetMasterClock() / (8 * (rate)) + 1) / 2);
00506 #else
00507     outr(USARTn_BASE + US_BRGR_OFF, (NutGetCpuClock() / (8 * (rate)) + 1) / 2);
00508 #endif
00509     At91UsartEnable();
00510 
00511     return 0;
00512 }
00513 
00522 static uint8_t At91UsartGetDataBits(void)
00523 {
00524     ureg_t val = inr(USARTn_BASE + US_MR_OFF);
00525 
00526     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00527         val = 9;
00528     }
00529     else {
00530         val &= US_CHRL;
00531         if (val == US_CHRL_5) {
00532             val = 5;
00533         }
00534         else if (val == US_CHRL_6) {
00535             val = 6;
00536         }
00537         else if (val == US_CHRL_7) {
00538             val = 7;
00539         }
00540         else {
00541             val = 8;
00542         }
00543     }
00544     return (uint8_t)val;
00545 }
00546 
00555 static int At91UsartSetDataBits(uint8_t bits)
00556 {
00557     ureg_t val = inr(USARTn_BASE + US_MR_OFF);
00558 
00559     if (bits == 9) {
00560         val &= ~US_PAR;
00561         val |= US_PAR_MULTIDROP;
00562     }
00563     else {
00564         val &= ~US_CHRL;
00565         if (bits == 5) {
00566             val |= US_CHRL_5;
00567         }
00568         else if (bits == 6) {
00569             val |= US_CHRL_6;
00570         }
00571         else if (bits == 7) {
00572             val |= US_CHRL_7;
00573         }
00574         else if (bits == 8) {
00575             val |= US_CHRL_8;
00576         }
00577     }
00578 
00579     At91UsartDisable();
00580     outr(USARTn_BASE + US_MR_OFF, val);
00581     At91UsartEnable();
00582 
00583     /*
00584      * Verify the result.
00585      */
00586     if (At91UsartGetDataBits() != bits) {
00587         return -1;
00588     }
00589     return 0;
00590 }
00591 
00600 static uint8_t At91UsartGetParity(void)
00601 {
00602     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_PAR;
00603 
00604     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00605         val = 9;
00606     }
00607     else {
00608         if (val == US_PAR_ODD) {
00609             val = 1;
00610         }
00611         else if (val == US_PAR_EVEN) {
00612             val = 2;
00613         }
00614         else {
00615             val = 0;
00616         }
00617     }
00618     return (uint8_t)val;
00619 }
00620 
00631 static int At91UsartSetParity(uint8_t mode)
00632 {
00633     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_PAR;
00634 
00635     switch (mode) {
00636     case 0:
00637         val |= US_PAR_NO;
00638         break;
00639     case 1:
00640         val |= US_PAR_ODD;
00641         break;
00642     case 2:
00643         val |= US_PAR_EVEN;
00644         break;
00645     }
00646     At91UsartDisable();
00647     outr(USARTn_BASE + US_MR_OFF, val);
00648     At91UsartEnable();
00649 
00650     /*
00651      * Verify the result.
00652      */
00653     if (At91UsartGetParity() != mode) {
00654         return -1;
00655     }
00656     return 0;
00657 }
00658 
00667 static uint8_t At91UsartGetStopBits(void)
00668 {
00669     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_NBSTOP;
00670     if (val == US_NBSTOP_1) {
00671         val = 1;
00672     }
00673     else if (val == US_NBSTOP_2) {
00674         val = 2;
00675     }
00676     else {
00677         val = 3;
00678     }
00679     return (uint8_t)val;
00680 }
00681 
00690 static int At91UsartSetStopBits(uint8_t bits)
00691 {
00692     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_NBSTOP;
00693 
00694     switch(bits) {
00695     case 1:
00696         val |= US_NBSTOP_1;
00697         break;
00698     case 2:
00699         val |= US_NBSTOP_2;
00700         break;
00701     case 3:
00702         val |= US_NBSTOP_1_5;
00703         break;
00704     }
00705     At91UsartDisable();
00706     outr(USARTn_BASE + US_MR_OFF, val);
00707     At91UsartEnable();
00708 
00709     /*
00710      * Verify the result.
00711      */
00712     if (At91UsartGetStopBits() != bits) {
00713         return -1;
00714     }
00715     return 0;
00716 }
00717 
00723 static uint32_t At91UsartGetStatus(void)
00724 {
00725     uint32_t rc = 0;
00726 
00727     /*
00728      * Set receiver error flags.
00729      */
00730     if ((rx_errors & US_FRAME) != 0) {
00731         rc |= UART_FRAMINGERROR;
00732     }
00733     if ((rx_errors & US_OVRE) != 0) {
00734         rc |= UART_OVERRUNERROR;
00735     }
00736     if ((rx_errors & US_PARE) != 0) {
00737         rc |= UART_PARITYERROR;
00738     }
00739 
00740     /*
00741      * Determine software handshake status. The flow control status may
00742      * change during interrupt, but this doesn't really hurt us.
00743      */
00744     if (flow_control) {
00745         if (flow_control & XOFF_SENT) {
00746             rc |= UART_RXDISABLED;
00747         }
00748         if (flow_control & XOFF_RCVD) {
00749             rc |= UART_TXDISABLED;
00750         }
00751     }
00752 #ifdef UART_RTS_BIT
00753     /*
00754      * Determine hardware handshake control status.
00755      */
00756     if (bit_is_set(UART_RTS_PORT, UART_RTS_BIT)) {
00757         rc |= UART_RTSDISABLED;
00758         if (rts_control) {
00759             rc |= UART_RXDISABLED;
00760         }
00761     } else {
00762         rc |= UART_RTSENABLED;
00763     }
00764 #endif
00765 
00766 #ifdef UART_CTS_BIT
00767     /*
00768      * Determine hardware handshake sense status.
00769      */
00770     if (bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00771         rc |= UART_CTSDISABLED;
00772         if (cts_sense) {
00773             rc |= UART_RXDISABLED;
00774         }
00775     } else {
00776         rc |= UART_CTSENABLED;
00777     }
00778 #endif
00779 
00780     /*
00781      * If transmitter and receiver haven't been detected disabled by any
00782      * of the checks above, then they are probably enabled.
00783      */
00784     if ((rc & UART_RXDISABLED) == 0) {
00785         rc |= UART_RXENABLED;
00786     }
00787     if ((rc & UART_TXDISABLED) == 0) {
00788         rc |= UART_TXENABLED;
00789     }
00790 
00791     /*
00792      * Process multidrop setting.
00793      */
00794     if (tx_aframe) {
00795         rc |= UART_TXADDRFRAME;
00796     } else {
00797         rc |= UART_TXNORMFRAME;
00798     }
00799     return rc;
00800 }
00801 
00809 static int At91UsartSetStatus(uint32_t flags)
00810 {
00811     /*
00812      * Process software handshake control.
00813      */
00814     if (flow_control) {
00815 
00816         /* Access to the flow control status must be atomic. */
00817         NutEnterCritical();
00818 
00819         /*
00820          * Enabling or disabling the receiver means to behave like
00821          * having sent a XON or XOFF character resp.
00822          */
00823         if (flags & UART_RXENABLED) {
00824             flow_control &= ~XOFF_SENT;
00825         } else if (flags & UART_RXDISABLED) {
00826             flow_control |= XOFF_SENT;
00827         }
00828 
00829         /*
00830          * Enabling or disabling the transmitter means to behave like
00831          * having received a XON or XOFF character resp.
00832          */
00833         if (flags & UART_TXENABLED) {
00834             flow_control &= ~XOFF_RCVD;
00835         } else if (flags & UART_TXDISABLED) {
00836             flow_control |= XOFF_RCVD;
00837         }
00838         NutExitCritical();
00839     }
00840 #ifdef UART_RTS_BIT
00841     /*
00842      * Process hardware handshake control.
00843      */
00844     if (rts_control) {
00845         if (flags & UART_RXDISABLED) {
00846             sbi(UART_RTS_PORT, UART_RTS_BIT);
00847         }
00848         if (flags & UART_RXENABLED) {
00849             cbi(UART_RTS_PORT, UART_RTS_BIT);
00850         }
00851     }
00852     if (flags & UART_RTSDISABLED) {
00853         sbi(UART_RTS_PORT, UART_RTS_BIT);
00854     }
00855     if (flags & UART_RTSENABLED) {
00856         cbi(UART_RTS_PORT, UART_RTS_BIT);
00857     }
00858 #endif
00859 
00860     /*
00861      * Process multidrop setting.
00862      */
00863     if (flags & UART_TXADDRFRAME) {
00864         tx_aframe = 1;
00865     }
00866     if (flags & UART_TXNORMFRAME) {
00867         tx_aframe = 0;
00868     }
00869 
00870     /*
00871      * Clear UART receive errors.
00872      */
00873     if (flags & UART_ERRORS) {
00874         outr(USARTn_BASE + US_CR_OFF, US_RSTSTA);
00875     }
00876 
00877     /*
00878      * Verify the result.
00879      */
00880     if ((At91UsartGetStatus() & ~UART_ERRORS) != flags) {
00881         return -1;
00882     }
00883     return 0;
00884 }
00885 
00895 static uint8_t At91UsartGetClockMode(void)
00896 {
00897     uint8_t rc = 0;
00898 
00899     return rc;
00900 }
00901 
00913 static int At91UsartSetClockMode(uint8_t mode)
00914 {
00915     /*
00916      * Verify the result.
00917      */
00918     if (At91UsartGetClockMode() != mode) {
00919         return -1;
00920     }
00921     return 0;
00922 }
00923 
00932 static uint32_t At91UsartGetFlowControl(void)
00933 {
00934     uint32_t rc = 0;
00935 
00936     if (flow_control) {
00937         rc |= USART_MF_XONXOFF;
00938     } else {
00939         rc &= ~USART_MF_XONXOFF;
00940     }
00941 
00942 #ifdef UART_RTS_BIT
00943     if (rts_control) {
00944         rc |= USART_MF_RTSCONTROL;
00945     } else {
00946         rc &= ~USART_MF_RTSCONTROL;
00947     }
00948 #endif
00949 
00950 #ifdef UART_CTS_BIT
00951     if (cts_sense) {
00952         rc |= USART_MF_CTSSENSE;
00953     } else {
00954         rc &= ~USART_MF_CTSSENSE;
00955     }
00956 #endif
00957 
00958 #ifdef UART_HDX_BIT
00959     if (hdx_control) {
00960         rc |= USART_MF_HALFDUPLEX;
00961     } else {
00962         rc &= ~USART_MF_HALFDUPLEX;
00963     }
00964 #endif
00965 
00966     return rc;
00967 }
00968 
00979 static int At91UsartSetFlowControl(uint32_t flags)
00980 {
00981     /*
00982      * Set software handshake mode.
00983      */
00984     if (flags & USART_MF_XONXOFF) {
00985         if(flow_control == 0) {
00986             NutEnterCritical();
00987             flow_control = 1 | XOFF_SENT;  /* force XON to be sent on next read */
00988             NutExitCritical();
00989         }
00990     } else {
00991         NutEnterCritical();
00992         flow_control = 0;
00993         NutExitCritical();
00994     }
00995 
00996 #ifdef UART_RTS_BIT
00997     /*
00998      * Set RTS control mode.
00999      */
01000     if (flags & USART_MF_RTSCONTROL) {
01001         sbi(UART_RTS_PORT, UART_RTS_BIT);
01002         sbi(UART_RTS_DDR, UART_RTS_BIT);
01003         rts_control = 1;
01004     } else if (rts_control) {
01005         rts_control = 0;
01006         cbi(UART_RTS_DDR, UART_RTS_BIT);
01007     }
01008 #endif
01009 
01010 #ifdef UART_CTS_BIT
01011     /*
01012      * Set CTS sense mode.
01013      */
01014     if (flags & USART_MF_CTSSENSE) {
01015         /* Register CTS sense interrupt. */
01016         if (NutRegisterIrqHandler(&UART_CTS_SIGNAL, At91UsartCts, 0)) {
01017             return -1;
01018         }
01019         sbi(UART_CTS_PORT, UART_CTS_BIT);
01020         cbi(UART_CTS_DDR, UART_CTS_BIT);
01021         cts_sense = 1;
01022     } else if (cts_sense) {
01023         cts_sense = 0;
01024         /* Deregister CTS sense interrupt. */
01025         NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0);
01026         cbi(UART_CTS_DDR, UART_CTS_BIT);
01027     }
01028 #endif
01029 
01030 #ifdef UART_HDX_BIT
01031     /*
01032      * Set half duplex mode.
01033      */
01034     if (flags & USART_MF_HALFDUPLEX) {
01035         /* Register transmit complete interrupt. */
01036         if (NutRegisterIrqHandler(&sig_UART_TRANS, At91UsartTxComplete, &dcb_usart.dcb_rx_rbf)) {
01037             return -1;
01038         }
01039         /* Initially enable the receiver. */
01040         UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
01041         sbi(UART_HDX_DDR, UART_HDX_BIT);
01042         hdx_control = 1;
01043         /* Enable transmit complete interrupt. */
01044         sbi(UCSRnB, TXCIE);
01045     } else if (hdx_control) {
01046         hdx_control = 0;
01047         /* disable transmit complete interrupt */
01048         cbi(UCSRnB, TXCIE);
01049         /* Deregister transmit complete interrupt. */
01050         NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
01051         cbi(UART_HDX_DDR, UART_HDX_BIT);
01052     }
01053 #endif
01054 
01055     /*
01056      * Verify the result.
01057      */
01058     if (At91UsartGetFlowControl() != flags) {
01059         return -1;
01060     }
01061     return 0;
01062 }
01063 
01071 static void At91UsartTxStart(void)
01072 {
01073 #ifdef UART_HDX_BIT
01074     if (hdx_control) {
01075         /* Enable half duplex transmitter. */
01076         UART_HDX_TX(UART_HDX_PORT, UART_HDX_BIT);
01077     }
01078 #endif
01079     /* Enable transmit interrupts. */
01080     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
01081 }
01082 
01091 static void At91UsartRxStart(void)
01092 {
01093     /*
01094      * Do any required software flow control.
01095      */
01096     if (flow_control && (flow_control & XOFF_SENT) != 0) {
01097         NutEnterCritical();
01098         if ((inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY)) {
01099             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
01100             flow_control &= ~XON_PENDING;
01101         } else {
01102             flow_control |= XON_PENDING;
01103         }
01104         flow_control &= ~(XOFF_SENT | XOFF_PENDING);
01105         NutExitCritical();
01106     }
01107 #ifdef UART_RTS_BIT
01108     if (rts_control) {
01109         /* Enable RTS. */
01110         cbi(UART_RTS_PORT, UART_RTS_BIT);
01111     }
01112 #endif
01113 }
01114 
01115 /*
01116  * \brief Initialize the USART hardware driver.
01117  *
01118  * This function is called during device registration by the upper level
01119  * USART driver through the USARTDCB jump table.
01120  *
01121  * \return 0 on success, -1 otherwise.
01122  */
01123 static int At91UsartInit(void)
01124 {
01125     /*
01126      * Register receive and transmit interrupts.
01127      */
01128     if (NutRegisterIrqHandler(&SIG_UART, At91UsartInterrupt, &dcb_usart)) {
01129         return -1;
01130     }
01131 
01132     /* Enable UART clock. */
01133 #if defined(US_ID)
01134 #if defined(PS_PCER)
01135     outr(PS_PCER, _BV(US_ID));
01136 #endif
01137 #if defined(PMC_PCER)
01138     outr(PMC_PCER, _BV(US_ID));
01139 #endif
01140 #endif
01141 
01142     /* Disable GPIO on UART tx/rx pins. */
01143 #if defined(PIO_PDR) && defined(US_PIO_PINS)
01144     outr(PIO_PDR, US_PIO_PINS);
01145 #endif
01146 
01147 #if defined(PIOA_PDR) && defined(US_PIOA_PINS)
01148     outr(PIOA_PDR, US_PIOA_PINS);
01149 #endif
01150 #if defined(PIOA_ASR) && defined(US_PIOA_PINS_A)
01151     outr(PIOA_ASR, US_PIOA_PINS_A);
01152 #endif
01153 #if defined(PIOA_BSR) && defined(US_PIOA_PINS_B)
01154     outr(PIOA_BSR, US_PIOA_PINS_B);
01155 #endif
01156 
01157 #if defined(PIOB_PDR) && defined(US_PIOB_PINS)
01158     outr(PIOB_PDR, US_PIOB_PINS);
01159 #endif
01160 #if defined(PIOB_ASR) && defined(US_PIOB_PINS_A)
01161     outr(PIOB_ASR, US_PIOB_PINS_A);
01162 #endif
01163 #if defined(PIOB_BSR) && defined(US_PIOB_PINS_B)
01164     outr(PIOB_BSR, US_PIOB_PINS_B);
01165 #endif
01166 
01167 #if defined(PIOC_PDR) && defined(US_PIOC_PINS)
01168     outr(PIOC_PDR, US_PIOC_PINS);
01169 #endif
01170 #if defined(PIOC_ASR) && defined(US_PIOC_PINS_A)
01171     outr(PIOC_ASR, US_PIOC_PINS_A);
01172 #endif
01173 #if defined(PIOC_BSR) && defined(US_PIOC_PINS_B)
01174     outr(PIOC_BSR, US_PIOC_PINS_B);
01175 #endif
01176 
01177     /* Reset UART. */
01178     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01179     /* Disable all UART interrupts. */
01180     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01181     /* Clear UART counter registers. */
01182 #if defined (US_RCR_OFF)
01183     outr(USARTn_BASE + US_RCR_OFF, 0);
01184 #endif
01185 #if defined (US_TCR_OFF)
01186     outr(USARTn_BASE + US_TCR_OFF, 0);
01187 #endif
01188     /* Set UART baud rate generator register. */
01189 #if defined(AT91_PLL_MAINCK)
01190     outr(USARTn_BASE + US_BRGR_OFF, (At91GetMasterClock() / (8 * (115200)) + 1) / 2);
01191 #else
01192     outr(USARTn_BASE + US_BRGR_OFF, (NutGetCpuClock() / (8 * (115200)) + 1) / 2);
01193 #endif
01194     /* Set UART mode to 8 data bits, no parity and 1 stop bit. */
01195 
01196 #ifdef AT91_UART_RS485_MODE
01197     outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1 | US_MODE_RS485);
01198 #else
01199     outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1);
01200 #endif
01201 
01202     return 0;
01203 }
01204 
01205 /*
01206  * \brief Deinitialize the USART hardware driver.
01207  *
01208  * This function is called during device deregistration by the upper
01209  * level USART driver through the USARTDCB jump table.
01210  *
01211  * \return 0 on success, -1 otherwise.
01212  */
01213 static int At91UsartDeinit(void)
01214 {
01215     /* Deregister receive and transmit interrupts. */
01216     NutRegisterIrqHandler(&SIG_UART, 0, 0);
01217 
01218     /* Reset UART. */
01219     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01220     /* Disable all UART interrupts. */
01221     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01222 
01223     /* Disable UART clock. */
01224 #if defined (US_ID)
01225 #if defined(PS_PCDR)
01226     outr(PS_PCDR, _BV(US_ID));
01227 #endif
01228 #if defined(PMC_PCDR)
01229     outr(PMC_PCDR, _BV(US_ID));
01230 #endif
01231 #endif
01232 
01233     /* Enable GPIO on UART tx/rx pins. */
01234 #if defined(PIO_PER) && defined(US_PIO_PINS)
01235     outr(PIO_PER, US_PIO_PINS);
01236 #endif
01237 #if defined(PIOA_PER) && defined(US_PIOA_PINS)
01238     outr(PIOA_PER, US_PIOA_PINS);
01239 #endif
01240 #if defined(PIOB_PER) && defined(US_PIOB_PINS)
01241     outr(PIOB_PER, US_PIOB_PINS);
01242 #endif
01243 #if defined(PIOC_PER) && defined(US_PIOC_PINS)
01244     outr(PIOC_PER, US_PIOC_PINS);
01245 #endif
01246 
01247     /*
01248      * Disabling flow control shouldn't be required here, because it's up
01249      * to the upper level to do this on the last close or during
01250      * deregistration.
01251      */
01252 #ifdef UART_HDX_BIT
01253     /* Deregister transmit complete interrupt. */
01254     if (hdx_control) {
01255         hdx_control = 0;
01256         NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
01257     }
01258 #endif
01259 
01260 #ifdef UART_CTS_BIT
01261     if (cts_sense) {
01262         cts_sense = 0;
01263         cbi(UART_CTS_DDR, UART_CTS_BIT);
01264         /* Deregister CTS sense interrupt. */
01265         NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0);
01266     }
01267 #endif
01268 
01269 #ifdef UART_RTS_BIT
01270     if (rts_control) {
01271         rts_control = 0;
01272         cbi(UART_RTS_DDR, UART_RTS_BIT);
01273     }
01274 #endif
01275 
01276     return 0;
01277 }
01278 

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