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.6  2006/08/31 19:01:44  haraldkipp
00041  * Using the processor clock for baud rate calculations failed
00042  * on the SAM9, if the master clock is further divided. This
00043  * had been fixed.
00044  *
00045  * Revision 1.5  2006/08/05 11:54:06  haraldkipp
00046  * Special register functions should not be based on MCU definitions but on
00047  * register definitions.
00048  *
00049  * Revision 1.4  2006/07/05 07:55:23  haraldkipp
00050  * Daidai's support for AT91SAM7X added.
00051  *
00052  * Revision 1.3  2006/06/28 17:18:40  haraldkipp
00053  * Temporarly exclude AT91R40008 specific register settings from building
00054  * for AT91SAM7X.
00055  *
00056  * Revision 1.2  2006/01/05 16:47:32  haraldkipp
00057  * Baudrate calculation is now based on NutGetCpuClock().
00058  *
00059  * Revision 1.1  2005/11/20 14:40:28  haraldkipp
00060  * Added interrupt driven UART driver for AT91.
00061  *
00062  */
00063 
00064 #include <cfg/clock.h>
00065 
00066 #include <sys/atom.h>
00067 #include <sys/event.h>
00068 #include <sys/timer.h>
00069 
00070 #include <dev/irqreg.h>
00071 
00072 #include <dev/usartat91.h>
00073 
00078 
00079 /* \brief ASCII code for software flow control, starts transmitter. */
00080 #define ASCII_XON   0x11
00081 /* \brief ASCII code for software flow control, stops transmitter. */
00082 #define ASCII_XOFF  0x13
00083 
00084 /* \brief XON transmit pending flag. */
00085 #define XON_PENDING     0x10
00086 /* \brief XOFF transmit pending flag. */
00087 #define XOFF_PENDING    0x20
00088 /* \brief XOFF sent flag. */
00089 #define XOFF_SENT       0x40
00090 /* \brief XOFF received flag. */
00091 #define XOFF_RCVD       0x80
00092 
00093 
00097 static ureg_t rx_errors;
00098 
00102 static ureg_t flow_control;
00103 
00107 static ureg_t tx_aframe;
00108 
00109 #ifdef UART_HDX_BIT
00110     /* define in cfg/modem.h */
00111     #ifdef UART_HDX_FLIP_BIT    /* same as RTS toggle by Windows NT driver */
00112         #define UART_HDX_TX     cbi
00113         #define UART_HDX_RX     sbi
00114     #else                       /* previous usage by Ethernut */
00115         #define UART_HDX_TX     sbi
00116         #define UART_HDX_RX     cbi
00117     #endif
00118 #endif
00119 
00120 
00121 #ifdef UART_HDX_BIT
00122 
00128 static ureg_t hdx_control;
00129 #endif
00130 
00131 #ifdef UART_RTS_BIT
00132 
00138 static ureg_t rts_control;
00139 #endif
00140 
00141 #ifdef UART_CTS_BIT
00142 
00148 static ureg_t cts_sense;
00149 #endif
00150 
00151 #ifdef UART_CTS_BIT
00152 
00162 static void At91UsartCts(void *arg)
00163 {
00164     /* Enable transmit interrupt. */
00165     //sbi(UCSRnB, UDRIE);
00166     /* Disable CTS sense interrupt. */
00167     //cbi(EIMSK, UART_CTS_BIT);
00168 }
00169 #endif
00170 
00171 #ifdef UART_HDX_BIT
00172 /*
00173  * \brief USARTn transmitter empty interrupt handler.
00174  *
00175  * Used with half duplex communication to switch from tranmit to receive
00176  * mode after the last character has been transmitted.
00177  *
00178  * This routine exists only if the hardware configuration defines a
00179  * port bit to switch between receive and transmit mode.
00180  *
00181  * \param arg Pointer to the transmitter ring buffer.
00182  */
00183 static void At91UsartTxEmpty(RINGBUF *rbf)
00184 {
00185     /*
00186      * Check if half duplex mode has been enabled and if all characters
00187      * had been sent out.
00188      */
00189     if (hdx_control && rbf->rbf_cnt == 0) {
00190         /* Switch to receiver mode. */
00191         UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
00192     }
00193 }
00194 #endif
00195 
00196 /*
00197  * \brief USARTn transmitter ready interrupt handler.
00198  *
00199  * \param rbf Pointer to the transmitter ring buffer.
00200  */
00201 static void At91UsartTxReady(RINGBUF *rbf) 
00202 {
00203     register u_char *cp = rbf->rbf_tail;
00204 
00205     /*
00206      * Process pending software flow controls first.
00207      */
00208     if (flow_control & (XON_PENDING | XOFF_PENDING)) {
00209         if (flow_control & XON_PENDING) {
00210             outr(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00211             flow_control |= XOFF_SENT;
00212         } else {
00213             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
00214             flow_control &= ~XOFF_SENT;
00215         }
00216         flow_control &= ~(XON_PENDING | XOFF_PENDING);
00217         return;
00218     }
00219 
00220     if (flow_control & XOFF_RCVD) {
00221         /*
00222          * If XOFF has been received, we disable the transmit interrupts
00223          * and return without sending anything.
00224          */
00225         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00226         return;
00227     }
00228 
00229     if (rbf->rbf_cnt) {
00230 
00231 #ifdef UART_CTS_BIT
00232         /*
00233          * If CTS has been disabled, we disable the transmit interrupts
00234          * and return without sending anything.
00235          */
00236         if (cts_sense && bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00237             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00238             sbi(EIMSK, UART_CTS_BIT);
00239             return;
00240         }
00241 #endif
00242         rbf->rbf_cnt--;
00243 
00244         /*
00245          * Send address in multidrop mode.
00246          */
00247         if (tx_aframe) {
00248             outr(USARTn_BASE + US_CR_OFF, US_SENDA);
00249         }
00250 
00251         /*
00252          * Start transmission of the next character.
00253          */
00254         outr(USARTn_BASE + US_THR_OFF, *cp);
00255 
00256         /*
00257          * Wrap around the buffer pointer if we reached its end.
00258          */
00259         if (++cp == rbf->rbf_last) {
00260             cp = rbf->rbf_start;
00261         }
00262         rbf->rbf_tail = cp;
00263         if (rbf->rbf_cnt == rbf->rbf_lwm) {
00264             NutEventPostFromIrq(&rbf->rbf_que);
00265         }
00266     }
00267 
00268     /*
00269      * Nothing left to transmit, disable interrupt.
00270      */
00271     else {
00272         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00273         rbf->rbf_cnt = 0;
00274         NutEventPostFromIrq(&rbf->rbf_que);
00275     }
00276 }
00277 
00278 
00279 /*
00280  * \brief USARTn receiver ready interrupt handler.
00281  *
00282  *
00283  * \param rbf Pointer to the receiver ring buffer.
00284  */
00285 
00286 static void At91UsartRxReady(RINGBUF *rbf) 
00287 {
00288     register size_t cnt;
00289     register u_char ch;
00290 
00291     /*
00292      * We read the received character as early as possible to avoid overflows
00293      * caused by interrupt latency.
00294      */
00295     ch = inb(USARTn_BASE + US_RHR_OFF);
00296 
00297     /* Collect receiver errors. */
00298     rx_errors |= inr(USARTn_BASE + US_CSR_OFF) & (US_OVRE | US_FRAME | US_PARE);
00299 
00300     /*
00301      * Handle software handshake. We have to do this before checking the
00302      * buffer, because flow control must work in write-only mode, where
00303      * there is no receive buffer.
00304      */
00305     if (flow_control) {
00306         /* XOFF character disables transmit interrupts. */
00307         if (ch == ASCII_XOFF) {
00308             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00309             flow_control |= XOFF_RCVD;
00310             return;
00311         }
00312         /* XON enables transmit interrupts. */
00313         else if (ch == ASCII_XON) {
00314             outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00315             flow_control &= ~XOFF_RCVD;
00316             return;
00317         }
00318     }
00319 
00320     /*
00321      * Check buffer overflow.
00322      */
00323     cnt = rbf->rbf_cnt;
00324     if (cnt >= rbf->rbf_siz) {
00325         rx_errors |= US_OVRE;
00326         return;
00327     }
00328 
00329     /* Wake up waiting threads if this is the first byte in the buffer. */
00330     if (cnt++ == 0){
00331         NutEventPostFromIrq(&rbf->rbf_que);
00332     }
00333 
00334     /*
00335      * Check the high watermark for software handshake. If the number of
00336      * buffered bytes is above this mark, then send XOFF.
00337      */
00338     else if (flow_control) {
00339         if(cnt >= rbf->rbf_hwm) {
00340             if((flow_control & XOFF_SENT) == 0) {
00341                 if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00342                     outb(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00343                     flow_control |= XOFF_SENT;
00344                     flow_control &= ~XOFF_PENDING;
00345                 } else {
00346                     flow_control |= XOFF_PENDING;
00347                 }
00348             }
00349         }
00350     }
00351 
00352 #ifdef UART_RTS_BIT
00353     /*
00354      * Check the high watermark for hardware handshake. If the number of
00355      * buffered bytes is above this mark, then disable RTS.
00356      */
00357     else if (rts_control && cnt >= rbf->rbf_hwm) {
00358         sbi(UART_RTS_PORT, UART_RTS_BIT);
00359     }
00360 #endif
00361 
00362     /*
00363      * Store the character and increment and the ring buffer pointer.
00364      */
00365     *rbf->rbf_head++ = ch;
00366     if (rbf->rbf_head == rbf->rbf_last) {
00367         rbf->rbf_head = rbf->rbf_start;
00368     }
00369 
00370     /* Update the ring buffer counter. */
00371     rbf->rbf_cnt = cnt;
00372 }
00373 
00379 static void At91UsartInterrupt(void *arg)
00380 {
00381     USARTDCB *dcb = (USARTDCB *)arg;
00382     ureg_t csr = inr(USARTn_BASE + US_CSR_OFF);
00383 
00384     if (csr & US_RXRDY) {
00385         At91UsartRxReady(&dcb->dcb_rx_rbf);
00386     }
00387     if (csr & US_TXRDY) {
00388         At91UsartTxReady(&dcb->dcb_tx_rbf);
00389     }
00390 
00391 #ifdef UART_HDX_BIT
00392     if (csr & US_TXEMPTY) {
00393         At91UsartTxEmpty(&dcb->dcb_tx_rbf);
00394     }
00395 #endif /*  UART_HDX_BIT */
00396 }
00397 
00404 static void At91UsartEnable(void)
00405 {
00406     NutEnterCritical();
00407 
00408     /* Enable UART receiver and transmitter. */
00409     outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
00410 
00411     /* Enable UART receiver and transmitter interrupts. */
00412     outr(USARTn_BASE + US_IER_OFF, US_RXRDY | US_TXRDY);
00413     NutIrqEnable(&SIG_UART);
00414 
00415 #ifdef UART_HDX_BIT
00416     if (hdx_control) {
00417         /* Enable transmit complete interrupt. */
00418         sbi(UCSRnB, TXCIE);
00419     }
00420 #endif
00421 
00422     NutExitCritical();
00423 }
00424 
00428 static void At91UsartDisable(void)
00429 {
00430     /*
00431      * Disable USART interrupts.
00432      */
00433     NutEnterCritical();
00434     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
00435     NutExitCritical();
00436 
00437     /*
00438      * Allow incoming or outgoing character to finish.
00439      */
00440     NutDelay(10);
00441 
00442     /*
00443      * Disable USART transmit and receive.
00444      */
00445     outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXDIS);
00446 }
00447 
00456 static u_long At91UsartGetSpeed(void)
00457 {
00458     ureg_t cs = inr(USARTn_BASE + US_MR_OFF);
00459     u_long clk;
00460 
00461 #if defined(AT91_PLL_MAINCK)
00462     clk = At91GetMasterClock();
00463 #else
00464     clk = NutGetCpuClock();
00465 #endif
00466     if ((cs & US_CLKS) == US_CLKS_MCK8) {
00467         clk /= 8;
00468     }
00469     else if ((cs & US_CLKS) != US_CLKS_MCK) {
00470         clk = 0;
00471     }
00472     return clk / (16UL * (inr(USARTn_BASE + US_BRGR_OFF) & 0xFFFF));
00473 }
00474 
00485 static int At91UsartSetSpeed(u_long rate)
00486 {
00487     At91UsartDisable();
00488 #if defined(AT91_PLL_MAINCK)
00489     outr(USARTn_BASE + US_BRGR_OFF, (At91GetMasterClock() / (8 * (rate)) + 1) / 2);
00490 #else
00491     outr(USARTn_BASE + US_BRGR_OFF, (NutGetCpuClock() / (8 * (rate)) + 1) / 2);
00492 #endif
00493     At91UsartEnable();
00494 
00495     return 0;
00496 }
00497 
00506 static u_char At91UsartGetDataBits(void)
00507 {
00508     ureg_t val = inr(USARTn_BASE + US_MR_OFF);
00509 
00510     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00511         val = 9;
00512     }
00513     else {
00514         val &= US_CHRL;
00515         if (val == US_CHRL_5) {
00516             val = 5;
00517         }
00518         else if (val == US_CHRL_6) {
00519             val = 6;
00520         }
00521         else if (val == US_CHRL_7) {
00522             val = 7;
00523         }
00524         else {
00525             val = 8;
00526         }
00527     }
00528     return (u_char)val;
00529 }
00530 
00539 static int At91UsartSetDataBits(u_char bits)
00540 {
00541     ureg_t val = inr(USARTn_BASE + US_MR_OFF);
00542 
00543     if (bits == 9) {
00544         val &= ~US_PAR;
00545         val |= US_PAR_MULTIDROP;
00546     }
00547     else {
00548         val &= ~US_CHRL;
00549         if (bits == 5) {
00550             val |= US_CHRL_5;
00551         }
00552         else if (bits == 6) {
00553             val |= US_CHRL_6;
00554         }
00555         else if (bits == 7) {
00556             val |= US_CHRL_7;
00557         }
00558         else if (bits == 8) {
00559             val |= US_CHRL_8;
00560         }
00561     }
00562 
00563     At91UsartDisable();
00564     outr(USARTn_BASE + US_MR_OFF, val);
00565     At91UsartEnable();
00566 
00567     /*
00568      * Verify the result.
00569      */
00570     if (At91UsartGetDataBits() != bits) {
00571         return -1;
00572     }
00573     return 0;
00574 }
00575 
00584 static u_char At91UsartGetParity(void)
00585 {
00586     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_PAR;
00587 
00588     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00589         val = 9;
00590     }
00591     else {
00592         if (val == US_PAR_ODD) {
00593             val = 1;
00594         }
00595         else if (val == US_PAR_EVEN) {
00596             val = 2;
00597         }
00598         else {
00599             val = 0;
00600         }
00601     }
00602     return (u_char)val;
00603 }
00604 
00615 static int At91UsartSetParity(u_char mode)
00616 {
00617     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_PAR;
00618 
00619     switch (mode) {
00620     case 0:
00621         val |= US_PAR_NO;
00622         break;
00623     case 1:
00624         val |= US_PAR_ODD;
00625         break;
00626     case 2:
00627         val |= US_PAR_EVEN;
00628         break;
00629     }
00630     At91UsartDisable();
00631     outr(USARTn_BASE + US_MR_OFF, val);
00632     At91UsartEnable();
00633 
00634     /*
00635      * Verify the result.
00636      */
00637     if (At91UsartGetParity() != mode) {
00638         return -1;
00639     }
00640     return 0;
00641 }
00642 
00651 static u_char At91UsartGetStopBits(void)
00652 {
00653     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & US_NBSTOP;
00654     if (val == US_NBSTOP_1) {
00655         val = 1;
00656     }
00657     else if (val == US_NBSTOP_2) {
00658         val = 2;
00659     }
00660     else {
00661         val = 3;
00662     }
00663     return (u_char)val;
00664 }
00665 
00674 static int At91UsartSetStopBits(u_char bits)
00675 {
00676     ureg_t val = inr(USARTn_BASE + US_MR_OFF) & ~US_NBSTOP;
00677 
00678     switch(bits) {
00679     case 1:
00680         val |= US_NBSTOP_1;
00681         break;
00682     case 2:
00683         val |= US_NBSTOP_2;
00684         break;
00685     case 3:
00686         val |= US_NBSTOP_1_5;
00687         break;
00688     }
00689     At91UsartDisable();
00690     outr(USARTn_BASE + US_MR_OFF, val);
00691     At91UsartEnable();
00692 
00693     /*
00694      * Verify the result.
00695      */
00696     if (At91UsartGetStopBits() != bits) {
00697         return -1;
00698     }
00699     return 0;
00700 }
00701 
00707 static u_long At91UsartGetStatus(void)
00708 {
00709     u_long rc = 0;
00710 
00711     /*
00712      * Set receiver error flags.
00713      */
00714     if ((rx_errors & US_FRAME) != 0) {
00715         rc |= UART_FRAMINGERROR;
00716     }
00717     if ((rx_errors & US_OVRE) != 0) {
00718         rc |= UART_OVERRUNERROR;
00719     }
00720     if ((rx_errors & US_PARE) != 0) {
00721         rc |= UART_PARITYERROR;
00722     }
00723 
00724     /*
00725      * Determine software handshake status. The flow control status may
00726      * change during interrupt, but this doesn't really hurt us.
00727      */
00728     if (flow_control) {
00729         if (flow_control & XOFF_SENT) {
00730             rc |= UART_RXDISABLED;
00731         }
00732         if (flow_control & XOFF_RCVD) {
00733             rc |= UART_TXDISABLED;
00734         }
00735     }
00736 #ifdef UART_RTS_BIT
00737     /*
00738      * Determine hardware handshake control status.
00739      */
00740     if (bit_is_set(UART_RTS_PORT, UART_RTS_BIT)) {
00741         rc |= UART_RTSDISABLED;
00742         if (rts_control) {
00743             rc |= UART_RXDISABLED;
00744         }
00745     } else {
00746         rc |= UART_RTSENABLED;
00747     }
00748 #endif
00749 
00750 #ifdef UART_CTS_BIT
00751     /*
00752      * Determine hardware handshake sense status.
00753      */
00754     if (bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {
00755         rc |= UART_CTSDISABLED;
00756         if (cts_sense) {
00757             rc |= UART_RXDISABLED;
00758         }
00759     } else {
00760         rc |= UART_CTSENABLED;
00761     }
00762 #endif
00763 
00764     /*
00765      * If transmitter and receiver haven't been detected disabled by any
00766      * of the checks above, then they are probably enabled.
00767      */
00768     if ((rc & UART_RXDISABLED) == 0) {
00769         rc |= UART_RXENABLED;
00770     }
00771     if ((rc & UART_TXDISABLED) == 0) {
00772         rc |= UART_TXENABLED;
00773     }
00774 
00775     /*
00776      * Process multidrop setting.
00777      */
00778     if (tx_aframe) {
00779         rc |= UART_TXADDRFRAME;
00780     } else {
00781         rc |= UART_TXNORMFRAME;
00782     }
00783     return rc;
00784 }
00785 
00793 static int At91UsartSetStatus(u_long flags)
00794 {
00795     /*
00796      * Process software handshake control.
00797      */
00798     if (flow_control) {
00799 
00800         /* Access to the flow control status must be atomic. */
00801         NutEnterCritical();
00802 
00803         /*
00804          * Enabling or disabling the receiver means to behave like
00805          * having sent a XON or XOFF character resp.
00806          */
00807         if (flags & UART_RXENABLED) {
00808             flow_control &= ~XOFF_SENT;
00809         } else if (flags & UART_RXDISABLED) {
00810             flow_control |= XOFF_SENT;
00811         }
00812 
00813         /*
00814          * Enabling or disabling the transmitter means to behave like
00815          * having received a XON or XOFF character resp.
00816          */
00817         if (flags & UART_TXENABLED) {
00818             flow_control &= ~XOFF_RCVD;
00819         } else if (flags & UART_TXDISABLED) {
00820             flow_control |= XOFF_RCVD;
00821         }
00822         NutExitCritical();
00823     }
00824 #ifdef UART_RTS_BIT
00825     /*
00826      * Process hardware handshake control.
00827      */
00828     if (rts_control) {
00829         if (flags & UART_RXDISABLED) {
00830             sbi(UART_RTS_PORT, UART_RTS_BIT);
00831         }
00832         if (flags & UART_RXENABLED) {
00833             cbi(UART_RTS_PORT, UART_RTS_BIT);
00834         }
00835     }
00836     if (flags & UART_RTSDISABLED) {
00837         sbi(UART_RTS_PORT, UART_RTS_BIT);
00838     }
00839     if (flags & UART_RTSENABLED) {
00840         cbi(UART_RTS_PORT, UART_RTS_BIT);
00841     }
00842 #endif
00843 
00844     /*
00845      * Process multidrop setting.
00846      */
00847     if (flags & UART_TXADDRFRAME) {
00848         tx_aframe = 1;
00849     }
00850     if (flags & UART_TXNORMFRAME) {
00851         tx_aframe = 0;
00852     }
00853 
00854     /*
00855      * Clear UART receive errors.
00856      */
00857     if (flags & UART_ERRORS) {
00858         outr(USARTn_BASE + US_CR_OFF, US_RSTSTA);
00859     }
00860 
00861     /*
00862      * Verify the result.
00863      */
00864     if ((At91UsartGetStatus() & ~UART_ERRORS) != flags) {
00865         return -1;
00866     }
00867     return 0;
00868 }
00869 
00879 static u_char At91UsartGetClockMode(void)
00880 {
00881     u_char rc = 0;
00882 
00883     return rc;
00884 }
00885 
00897 static int At91UsartSetClockMode(u_char mode)
00898 {
00899     /*
00900      * Verify the result.
00901      */
00902     if (At91UsartGetClockMode() != mode) {
00903         return -1;
00904     }
00905     return 0;
00906 }
00907 
00916 static u_long At91UsartGetFlowControl(void)
00917 {
00918     u_long rc = 0;
00919 
00920     if (flow_control) {
00921         rc |= USART_MF_XONXOFF;
00922     } else {
00923         rc &= ~USART_MF_XONXOFF;
00924     }
00925 
00926 #ifdef UART_RTS_BIT
00927     if (rts_control) {
00928         rc |= USART_MF_RTSCONTROL;
00929     } else {
00930         rc &= ~USART_MF_RTSCONTROL;
00931     }
00932 #endif
00933 
00934 #ifdef UART_CTS_BIT
00935     if (cts_sense) {
00936         rc |= USART_MF_CTSSENSE;
00937     } else {
00938         rc &= ~USART_MF_CTSSENSE;
00939     }
00940 #endif
00941 
00942 #ifdef UART_HDX_BIT
00943     if (hdx_control) {
00944         rc |= USART_MF_HALFDUPLEX;
00945     } else {
00946         rc &= ~USART_MF_HALFDUPLEX;
00947     }
00948 #endif
00949 
00950     return rc;
00951 }
00952 
00963 static int At91UsartSetFlowControl(u_long flags)
00964 {
00965     /*
00966      * Set software handshake mode.
00967      */
00968     if (flags & USART_MF_XONXOFF) {
00969         if(flow_control == 0) {
00970             NutEnterCritical();
00971             flow_control = 1 | XOFF_SENT;  /* force XON to be sent on next read */
00972             NutExitCritical();
00973         }
00974     } else {
00975         NutEnterCritical();
00976         flow_control = 0;
00977         NutExitCritical();
00978     }
00979 
00980 #ifdef UART_RTS_BIT
00981     /*
00982      * Set RTS control mode.
00983      */
00984     if (flags & USART_MF_RTSCONTROL) {
00985         sbi(UART_RTS_PORT, UART_RTS_BIT);
00986         sbi(UART_RTS_DDR, UART_RTS_BIT);
00987         rts_control = 1;
00988     } else if (rts_control) {
00989         rts_control = 0;
00990         cbi(UART_RTS_DDR, UART_RTS_BIT);
00991     }
00992 #endif
00993 
00994 #ifdef UART_CTS_BIT
00995     /*
00996      * Set CTS sense mode.
00997      */
00998     if (flags & USART_MF_CTSSENSE) {
00999         /* Register CTS sense interrupt. */
01000         if (NutRegisterIrqHandler(&UART_CTS_SIGNAL, At91UsartCts, 0)) {
01001             return -1;
01002         }
01003         sbi(UART_CTS_PORT, UART_CTS_BIT);
01004         cbi(UART_CTS_DDR, UART_CTS_BIT);
01005         cts_sense = 1;
01006     } else if (cts_sense) {
01007         cts_sense = 0;
01008         /* Deregister CTS sense interrupt. */
01009         NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0);
01010         cbi(UART_CTS_DDR, UART_CTS_BIT);
01011     }
01012 #endif
01013 
01014 #ifdef UART_HDX_BIT
01015     /*
01016      * Set half duplex mode.
01017      */
01018     if (flags & USART_MF_HALFDUPLEX) {
01019         /* Register transmit complete interrupt. */
01020         if (NutRegisterIrqHandler(&sig_UART_TRANS, At91UsartTxComplete, &dcb_usart.dcb_rx_rbf)) {
01021             return -1;
01022         }
01023         /* Initially enable the receiver. */
01024         UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);
01025         sbi(UART_HDX_DDR, UART_HDX_BIT);
01026         hdx_control = 1;
01027         /* Enable transmit complete interrupt. */
01028         sbi(UCSRnB, TXCIE);
01029     } else if (hdx_control) {
01030         hdx_control = 0;
01031         /* disable transmit complete interrupt */
01032         cbi(UCSRnB, TXCIE);
01033         /* Deregister transmit complete interrupt. */
01034         NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
01035         cbi(UART_HDX_DDR, UART_HDX_BIT);
01036     }
01037 #endif
01038 
01039     /*
01040      * Verify the result.
01041      */
01042     if (At91UsartGetFlowControl() != flags) {
01043         return -1;
01044     }
01045     return 0;
01046 }
01047 
01055 static void At91UsartTxStart(void)
01056 {
01057 #ifdef UART_HDX_BIT
01058     if (hdx_control) {
01059         /* Enable half duplex transmitter. */
01060         UART_HDX_TX(UART_HDX_PORT, UART_HDX_BIT);
01061     }
01062 #endif
01063     /* Enable transmit interrupts. */
01064     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
01065 }
01066 
01075 static void At91UsartRxStart(void)
01076 {
01077     /*
01078      * Do any required software flow control.
01079      */
01080     if (flow_control && (flow_control & XOFF_SENT) != 0) {
01081         NutEnterCritical();
01082         if ((inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY)) {
01083             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
01084             flow_control &= ~XON_PENDING;
01085         } else {
01086             flow_control |= XON_PENDING;
01087         }
01088         flow_control &= ~(XOFF_SENT | XOFF_PENDING);
01089         NutExitCritical();
01090     }
01091 #ifdef UART_RTS_BIT
01092     if (rts_control) {
01093         /* Enable RTS. */
01094         cbi(UART_RTS_PORT, UART_RTS_BIT);
01095     }
01096 #endif
01097 }
01098 
01099 /*
01100  * \brief Initialize the USART hardware driver.
01101  *
01102  * This function is called during device registration by the upper level
01103  * USART driver through the USARTDCB jump table.
01104  *
01105  * \return 0 on success, -1 otherwise.
01106  */
01107 static int At91UsartInit(void)
01108 {
01109     /*
01110      * Register receive and transmit interrupts.
01111      */
01112     if (NutRegisterIrqHandler(&SIG_UART, At91UsartInterrupt, &dcb_usart)) {
01113         return -1;
01114     }
01115 
01116 #if defined (MCU_AT91R40008)
01117     /* Enable UART clock. */
01118     outr(PS_PCER, _BV(US_ID));
01119     /* Disable GPIO on UART tx/rx pins. */
01120     outr(PIO_PDR, US_GPIO_PINS);
01121 #elif defined (MCU_AT91SAM7X256)
01122     outr(PMC_PCER, _BV(US_ID));
01123     outr(PIOA_PDR, US_GPIO_PINS);
01124 #endif
01125     /* Reset UART. */
01126     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01127     /* Disable all UART interrupts. */
01128     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01129     /* Clear UART counter registers. */
01130 #if defined (US_RCR_OFF)
01131     outr(USARTn_BASE + US_RCR_OFF, 0);
01132 #endif
01133 #if defined (US_TCR_OFF)
01134     outr(USARTn_BASE + US_TCR_OFF, 0);
01135 #endif
01136     /* Set UART baud rate generator register. */
01137 #if defined(AT91_PLL_MAINCK)
01138     outr(USARTn_BASE + US_BRGR_OFF, (At91GetMasterClock() / (8 * (115200)) + 1) / 2);
01139 #else
01140     outr(USARTn_BASE + US_BRGR_OFF, (NutGetCpuClock() / (8 * (115200)) + 1) / 2);
01141 #endif
01142     /* Set UART mode to 8 data bits, no parity and 1 stop bit. */
01143     outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1);
01144 
01145     return 0;
01146 }
01147 
01148 /*
01149  * \brief Deinitialize the USART hardware driver.
01150  *
01151  * This function is called during device deregistration by the upper
01152  * level USART driver through the USARTDCB jump table.
01153  *
01154  * \return 0 on success, -1 otherwise.
01155  */
01156 static int At91UsartDeinit(void)
01157 {
01158     /* Deregister receive and transmit interrupts. */
01159     NutRegisterIrqHandler(&SIG_UART, 0, 0);
01160 
01161     /* Reset UART. */
01162     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01163     /* Disable all UART interrupts. */
01164     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01165 #if defined (MCU_AT91R40008)
01166     /* Disable UART clock. */
01167     outr(PS_PCDR, _BV(US_ID));
01168     /* Enable GPIO on UART tx/rx pins. */
01169     outr(PIO_PER, US_GPIO_PINS);
01170 #elif defined (MCU_AT91SAM7X256)
01171     outr(PMC_PCDR, _BV(US_ID));
01172     outr(PIOA_PER, US_GPIO_PINS);
01173 #endif
01174 
01175     /*
01176      * Disabling flow control shouldn't be required here, because it's up
01177      * to the upper level to do this on the last close or during
01178      * deregistration.
01179      */
01180 #ifdef UART_HDX_BIT
01181     /* Deregister transmit complete interrupt. */
01182     if (hdx_control) {
01183         hdx_control = 0;
01184         NutRegisterIrqHandler(&sig_UART_TRANS, 0, 0);
01185     }
01186 #endif
01187 
01188 #ifdef UART_CTS_BIT
01189     if (cts_sense) {
01190         cts_sense = 0;
01191         cbi(UART_CTS_DDR, UART_CTS_BIT);
01192         /* Deregister CTS sense interrupt. */
01193         NutRegisterIrqHandler(&UART_CTS_SIGNAL, 0, 0);
01194     }
01195 #endif
01196 
01197 #ifdef UART_RTS_BIT
01198     if (rts_control) {
01199         rts_control = 0;
01200         cbi(UART_RTS_DDR, UART_RTS_BIT);
01201     }
01202 #endif
01203 
01204     return 0;
01205 }
01206 

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