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

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