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

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