usartat91.c

Go to the documentation of this file.
00001 /*
00002  * Copyright 2001-2006 by egnite Software GmbH
00003  * Copyright 2009 by egnite GmbH
00004  *
00005  * All rights reserved.
00006  *
00007  * Redistribution and use in source and binary forms, with or without
00008  * modification, are permitted provided that the following conditions
00009  * are met:
00010  *
00011  * 1. Redistributions of source code must retain the above copyright
00012  *    notice, this list of conditions and the following disclaimer.
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in the
00015  *    documentation and/or other materials provided with the distribution.
00016  * 3. Neither the name of the copyright holders nor the names of
00017  *    contributors may be used to endorse or promote products derived
00018  *    from this software without specific prior written permission.
00019  *
00020  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00027  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00028  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00029  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00030  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00031  * SUCH DAMAGE.
00032  *
00033  * For additional information see http://www.ethernut.de/
00034  */
00035 
00036 /*
00037  * $Id: usartat91.c 2693 2009-09-14 11:41:37Z haraldkipp $
00038  */
00039 
00040 #include <cfg/clock.h>
00041 
00042 #ifdef UART_USES_NPL
00043 #include <dev/npl.h>
00044 #endif
00045 
00046 #include <sys/atom.h>
00047 #include <sys/event.h>
00048 #include <sys/timer.h>
00049 
00050 #include <dev/irqreg.h>
00051 
00052 #include <dev/usartat91.h>
00053 
00054 /*
00055 ** Initial USART settings.
00056 */
00057 #ifndef UART_INIT_BAUDRATE
00058 #define UART_INIT_BAUDRATE  115200
00059 #endif
00060 
00061 /*
00062 ** Add empty placeholders for undefined pin configurations.
00063 */
00064 #ifndef UART_RXTX_PINS_ENABLE
00065 #define UART_RXTX_PINS_ENABLE()
00066 #endif
00067 
00068 #ifndef UART_HDX_PIN_ENABLE
00069 #define UART_HDX_PIN_ENABLE()
00070 #endif
00071 #ifndef UART_HDX_RX
00072 #define UART_HDX_RX()
00073 #endif
00074 #ifndef UART_HDX_TX
00075 #define UART_HDX_TX()
00076 #endif
00077 
00078 #ifndef UART_RTS_PIN_ENABLE
00079 #define UART_RTS_PIN_ENABLE()
00080 #endif
00081 #ifndef UART_RTS_ON
00082 #define UART_RTS_ON()
00083 #endif
00084 #ifndef UART_RTS_OFF
00085 #define UART_RTS_OFF()
00086 #endif
00087 
00088 #ifndef UART_CTS_PIN_ENABLE
00089 #define UART_CTS_PIN_ENABLE()
00090 #endif
00091 #ifndef UART_CTS_IS_ON
00092 #define UART_CTS_IS_ON()    (1)
00093 #endif
00094 
00095 #ifndef UART_MODEM_PINS_ENABLE
00096 #define UART_MODEM_PINS_ENABLE()
00097 #endif
00098 
00099 
00100 /*
00101 ** GPIO controlled half duplex pin.
00102 */
00103 #if defined(UART_HDX_BIT) && defined(UART_HDX_PIO_ID)
00104 
00105 #undef UART_HDX_RX
00106 #undef UART_HDX_TX
00107 #undef UART_HDX_PIN_ENABLE
00108 #undef GPIO_ID
00109 #define GPIO_ID UART_HDX_PIO_ID
00110 #include <cfg/arch/porttran.h>
00111 static INLINE void UART_HDX_PIN_ENABLE(void) {
00112     GPIO_ENABLE(UART_HDX_BIT);
00113     GPIO_OUTPUT(UART_HDX_BIT);
00114 }
00115 #ifdef UART_HDX_FLIP_BIT
00116 static INLINE void UART_HDX_RX(void) { GPIO_SET_HI(UART_HDX_BIT); }
00117 static INLINE void UART_HDX_TX(void) { GPIO_SET_LO(UART_HDX_BIT); }
00118 #else
00119 static INLINE void UART_HDX_RX(void) { GPIO_SET_LO(UART_HDX_BIT); }
00120 static INLINE void UART_HDX_TX(void) { GPIO_SET_HI(UART_HDX_BIT); }
00121 #endif
00122 
00123 #elif defined(UART_USES_NPL)
00124 
00125 #undef UART_HDX_RX
00126 #undef UART_HDX_TX
00127 #define UART_HDX_RX()   cbi(NPL_RSCR, NPL_RSRTS_BIT)
00128 #define UART_HDX_TX()   sbi(NPL_RSCR, NPL_RSRTS_BIT)
00129 
00130 #endif /* UART_HDX_BIT */
00131 
00132 /*
00133 ** GPIO controlled RTS pin.
00134 */
00135 #if defined(UART_RTS_BIT) && defined(UART_RTS_PIO_ID)
00136 
00137 #undef UART_RTS_ON
00138 #undef UART_RTS_OFF
00139 #undef UART_RTS_PIN_ENABLE
00140 #undef GPIO_ID
00141 #define GPIO_ID UART_RTS_PIO_ID
00142 #include <cfg/arch/porttran.h>
00143 static INLINE void UART_RTS_PIN_ENABLE(void) { \
00144     GPIO_ENABLE(UART_RTS_BIT); \
00145     GPIO_OUTPUT(UART_RTS_BIT); \
00146 }
00147 #ifdef UART_RTS_FLIP_BIT
00148 static INLINE void UART_RTS_ON(void) { GPIO_SET_HI(UART_RTS_BIT); }
00149 static INLINE void UART_RTS_OFF(void) { GPIO_SET_LO(UART_RTS_BIT); }
00150 #else
00151 static INLINE void UART_RTS_ON(void) { GPIO_SET_LO(UART_RTS_BIT); }
00152 static INLINE void UART_RTS_OFF(void) { GPIO_SET_HI(UART_RTS_BIT); }
00153 #endif
00154 
00155 #elif defined(UART_USES_NPL)
00156 
00157 #undef UART_RTS_ON
00158 #undef UART_RTS_OFF
00159 #define UART_RTS_ON()   cbi(NPL_RSCR, NPL_RSRTS_BIT)
00160 #define UART_RTS_OFF()  sbi(NPL_RSCR, NPL_RSRTS_BIT)
00161 
00162 #endif
00163 
00164 /*
00165 ** GPIO monitored CTS pin.
00166 */
00167 #if defined(UART_CTS_BIT) && defined(UART_CTS_PIO_ID)
00168 
00169 #undef UART_CTS_IS_ON
00170 #undef UART_CTS_PIN_ENABLE
00171 #undef GPIO_ID
00172 #define GPIO_ID UART_CTS_PIO_ID
00173 #include <cfg/arch/porttran.h>
00174 #ifdef UART_CTS_FLIP_BIT
00175 static INLINE int UART_CTS_IS_ON(void) { return GPIO_GET(UART_CTS_BIT); }
00176 #else
00177 static INLINE int UART_CTS_IS_ON(void) { return !GPIO_GET(UART_CTS_BIT); }
00178 #endif
00179 static INLINE void UART_CTS_PIN_ENABLE(void) { \
00180     GPIO_ENABLE(UART_CTS_BIT); \
00181     GPIO_INPUT(UART_CTS_BIT); \
00182     GPIO_PULLUP_ON(UART_CTS_BIT); \
00183 }
00184 
00185 #elif defined(UART_USES_NPL)
00186 
00187 #undef UART_CTS_IS_ON
00188 static INLINE int UART_CTS_IS_ON(void) {
00189     outw(NPL_SCR, NPL_RSCTS);
00190     return bit_is_set(NPL_SLR, NPL_RSCTS_BIT);
00191 }
00192 
00193 #endif
00194 
00195 /*
00196 ** Determine if we use built-in hardware handshake.
00197 */
00198 #if !defined(USE_BUILT_IN_HARDWARE_HANDSHAKE)
00199 #if defined(UART_HARDWARE_HANDSHAKE) && \
00200     defined(US_MODE_HWHANDSHAKE) && \
00201     !defined(UART_RTS_BIT) && \
00202     !defined(UART_CTS_BIT) && \
00203     !defined(UART_USES_NPL)
00204 #define USE_BUILT_IN_HARDWARE_HANDSHAKE 1
00205 #else
00206 #define USE_BUILT_IN_HARDWARE_HANDSHAKE 0
00207 #endif
00208 #endif
00209 
00210 /*
00211 ** Determine if we use built-in half duplex mode.
00212 */
00213 #if !defined(USE_BUILT_IN_HALF_DUPLEX)
00214 #if defined(UART_HARDWARE_HANDSHAKE) && !defined(UART_HDX_BIT) && !defined(UART_USES_NPL)
00215 #define USE_BUILT_IN_HALF_DUPLEX    1
00216 #else
00217 #define USE_BUILT_IN_HALF_DUPLEX    0
00218 #endif
00219 #endif
00220 
00225 
00226 /* \brief ASCII code for software flow control, starts transmitter. */
00227 #define ASCII_XON   0x11
00228 /* \brief ASCII code for software flow control, stops transmitter. */
00229 #define ASCII_XOFF  0x13
00230 
00231 /* \brief XON transmit pending flag. */
00232 #define XON_PENDING     0x10
00233 /* \brief XOFF transmit pending flag. */
00234 #define XOFF_PENDING    0x20
00235 /* \brief XOFF sent flag. */
00236 #define XOFF_SENT       0x40
00237 /* \brief XOFF received flag. */
00238 #define XOFF_RCVD       0x80
00239 
00240 
00244 static unsigned int rx_errors;
00245 
00249 static uint_fast8_t flow_control;
00250 
00254 static uint_fast8_t tx_aframe;
00255 
00261 static uint_fast8_t hdx_control;
00262 
00269 static uint_fast8_t rts_control;
00270 
00277 static uint_fast8_t cts_sense;
00278 
00279 #if defined(UART_CTS_BIT) || defined(UART_USES_NPL)
00280 
00290 static void At91UsartCts(void *arg)
00291 {
00292     /* Disable CTS sense interrupt. */
00293 #if defined(UART_USES_NPL)
00294     NplIrqDisable(&sig_RSCTS);
00295     /* Enable transmit interrupt. */
00296     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00297 #else
00298     if (UART_CTS_IS_ON()) {
00299         GpioIrqDisable(&UART_CTS_SIGNAL, UART_CTS_BIT);
00300         /* Enable transmit interrupt. */
00301         outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00302     }
00303 #endif
00304 }
00305 #endif
00306 
00307 #if USE_BUILT_IN_HALF_DUPLEX == 0
00308 /*
00309  * \brief USARTn transmitter empty interrupt handler.
00310  *
00311  * Used with half duplex communication to switch from tranmit to receive
00312  * mode after the last character has been transmitted.
00313  *
00314  * \param arg Pointer to the transmitter ring buffer.
00315  */
00316 static void At91UsartTxEmpty(RINGBUF *rbf)
00317 {
00318     /*
00319      * Check if half duplex mode has been enabled and if all characters
00320      * had been sent out.
00321      */
00322     if (hdx_control && (rbf->rbf_cnt == 0)) {
00323         /*
00324          * Switch to receiver mode:
00325          * Enable USART receive, disable transmit.
00326          * Disable TX-Empty IRQ
00327          */
00328         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXDIS);
00329 #if defined(UART_HDX_BIT) || defined(UART_USES_NPL)
00330         UART_HDX_RX();
00331 #endif
00332     }
00333 }
00334 #endif
00335 
00336 /*
00337  * \brief USARTn transmitter ready interrupt handler.
00338  *
00339  * \param rbf Pointer to the transmitter ring buffer.
00340  */
00341 static void At91UsartTxReady(RINGBUF *rbf) 
00342 {
00343     register uint8_t *cp = rbf->rbf_tail;
00344 
00345     /*
00346      * Process pending software flow controls first.
00347      */
00348     if (flow_control & (XON_PENDING | XOFF_PENDING)) {
00349         if (flow_control & XON_PENDING) {
00350             outr(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00351             flow_control |= XOFF_SENT;
00352         } else {
00353             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
00354             flow_control &= ~XOFF_SENT;
00355         }
00356         flow_control &= ~(XON_PENDING | XOFF_PENDING);
00357         return;
00358     }
00359 
00360     if (flow_control & XOFF_RCVD) {
00361         /*
00362          * If XOFF has been received, we disable the transmit interrupts
00363          * and return without sending anything.
00364          */
00365         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00366         return;
00367     }
00368 
00369     /*
00370      * Check if we have more bytes to transmit.
00371      */
00372     if (rbf->rbf_cnt) {
00373 #if defined(UART_CTS_BIT) || defined(UART_USES_NPL)
00374         /*
00375          * If CTS has been disabled, we disable the transmit interrupts,
00376          * enable CTS interrupts and return without sending anything.
00377          */
00378         if (cts_sense && !UART_CTS_IS_ON()) {
00379             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00380 #if defined(UART_CTS_BIT)
00381             GpioIrqEnable(&UART_CTS_SIGNAL, UART_CTS_BIT);
00382 #else
00383             NplIrqEnable(&sig_RSCTS);
00384 #endif
00385             return;
00386         }
00387 #endif
00388 
00389         /*
00390          * Send address in multidrop mode.
00391          */
00392         if (tx_aframe) {
00393             outr(USARTn_BASE + US_CR_OFF, US_SENDA);
00394         }
00395 
00396         /* Start transmission of the next character. */
00397         outr(USARTn_BASE + US_THR_OFF, *cp);
00398         /* Decrement the number of available bytes in the buffer. */
00399         rbf->rbf_cnt--;
00400         /* Wrap around the buffer pointer if we reached its end. */
00401         if (++cp == rbf->rbf_last) {
00402             cp = rbf->rbf_start;
00403         }
00404         rbf->rbf_tail = cp;
00405 
00406 #if USE_BUILT_IN_HALF_DUPLEX == 0
00407         /* 
00408          * If software half duplex enabled, we need TX-Empty IRQ for
00409          * detection if last bit of last byte transmission is finished.
00410          */
00411         if( hdx_control && rbf->rbf_cnt == 0) {
00412             outr(USARTn_BASE + US_IER_OFF, US_TXEMPTY);
00413         }
00414 #endif
00415 
00416         /* Send an event if we reached the low watermark. */
00417         if (rbf->rbf_cnt == rbf->rbf_lwm) {
00418             NutEventPostFromIrq(&rbf->rbf_que);
00419         }
00420     }
00421 
00422     /*
00423      * Nothing left to transmit, disable interrupt.
00424      */
00425     else {
00426         /* Disable transmit interrupts. */
00427         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00428         /* Send an event to inform the upper level. */
00429         NutEventPostFromIrq(&rbf->rbf_que);
00430     }
00431 }
00432 
00433 
00434 /*
00435  * \brief USARTn receiver ready interrupt handler.
00436  *
00437  *
00438  * \param rbf Pointer to the receiver ring buffer.
00439  */
00440 
00441 static void At91UsartRxReady(RINGBUF *rbf) 
00442 {
00443     register size_t cnt;
00444     register uint8_t ch;
00445 
00446     /*
00447      * We read the received character as early as possible to avoid overflows
00448      * caused by interrupt latency.
00449      */
00450     ch = inb(USARTn_BASE + US_RHR_OFF);
00451 
00452     /* Collect receiver errors. */
00453     rx_errors |= inr(USARTn_BASE + US_CSR_OFF) & (US_OVRE | US_FRAME | US_PARE);
00454 
00455     /*
00456      * Handle software handshake. We have to do this before checking the
00457      * buffer, because flow control must work in write-only mode, where
00458      * there is no receive buffer.
00459      */
00460     if (flow_control) {
00461         /* XOFF character disables transmit interrupts. */
00462         if (ch == ASCII_XOFF) {
00463             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00464             flow_control |= XOFF_RCVD;
00465             return;
00466         }
00467         /* XON enables transmit interrupts. */
00468         else if (ch == ASCII_XON) {
00469             outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00470             flow_control &= ~XOFF_RCVD;
00471             return;
00472         }
00473     }
00474 
00475     /*
00476      * Check buffer overflow.
00477      */
00478     cnt = rbf->rbf_cnt;
00479     if (cnt >= rbf->rbf_siz) {
00480         rx_errors |= US_OVRE;
00481         return;
00482     }
00483 
00484     /* Wake up waiting threads if this is the first byte in the buffer. */
00485     if (cnt++ == 0){
00486         NutEventPostFromIrq(&rbf->rbf_que);
00487     }
00488 
00489     /*
00490      * Check the high watermark for software handshake. If the number of
00491      * buffered bytes is equal or above this mark, then send XOFF.
00492      */
00493     else if (flow_control) {
00494         if(cnt >= rbf->rbf_hwm) {
00495             if((flow_control & XOFF_SENT) == 0) {
00496                 if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00497                     outb(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00498                     flow_control |= XOFF_SENT;
00499                     flow_control &= ~XOFF_PENDING;
00500                 } else {
00501                     flow_control |= XOFF_PENDING;
00502                 }
00503             }
00504         }
00505     }
00506 
00507 #if defined(UART_RTS_BIT) || defined(UART_USES_NPL)
00508     /*
00509      * Check the high watermark for GPIO hardware handshake. If the 
00510      * number of buffered bytes is equal or above this mark, then 
00511      * disable RTS.
00512      */
00513     else if (rts_control && cnt >= rbf->rbf_hwm) {
00514         UART_RTS_OFF();
00515     }
00516 #endif
00517 
00518     /*
00519      * Store the character and increment and the ring buffer pointer.
00520      */
00521     *rbf->rbf_head++ = ch;
00522     if (rbf->rbf_head == rbf->rbf_last) {
00523         rbf->rbf_head = rbf->rbf_start;
00524     }
00525 
00526     /* Update the ring buffer counter. */
00527     rbf->rbf_cnt = cnt;
00528 }
00529 
00535 static void At91UsartInterrupt(void *arg)
00536 {
00537     USARTDCB *dcb = (USARTDCB *)arg;
00538     unsigned int csr = inr(USARTn_BASE + US_CSR_OFF);
00539 
00540     if (csr & US_RXRDY) {
00541         At91UsartRxReady(&dcb->dcb_rx_rbf);
00542     }
00543     if (csr & US_TXRDY) {
00544         At91UsartTxReady(&dcb->dcb_tx_rbf);
00545     }
00546 
00547 #if USE_BUILT_IN_HALF_DUPLEX == 0
00548     if (csr & US_TXEMPTY) {
00549         At91UsartTxEmpty(&dcb->dcb_tx_rbf);
00550     }
00551 #endif
00552 }
00553 
00560 static void At91UsartEnable(void)
00561 {
00562     /* Enable UART receiver and transmitter. */
00563     outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
00564     /* Globally enable UART interrupts. */
00565     NutIrqEnable(&SIG_UART);
00566 }
00567 
00590 static void At91UsartDisable(void)
00591 {
00592     /* Globally disable UART interrupts. */
00593     NutIrqDisable(&SIG_UART);
00594     /* Wait until all bits had been shifted out. */
00595     if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00596         while((inr(USARTn_BASE + US_CSR_OFF) & US_TXEMPTY) == 0);
00597     }
00598     /* Disable USART transmit and receive. */
00599     outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXDIS);
00600 }
00601 
00610 static uint32_t At91UsartGetSpeed(void)
00611 {
00612     unsigned int cs;
00613     uint32_t clk;
00614 
00615     clk = NutClockGet(NUT_HWCLK_PERIPHERAL);
00616     cs = inr(USARTn_BASE + US_MR_OFF) & US_CLKS;
00617     if (cs == US_CLKS_MCK8) {
00618         clk /= 8;
00619     }
00620     else if (cs != US_CLKS_MCK) {
00621         clk = 0;
00622     }
00623     return clk / (16UL * (inr(USARTn_BASE + US_BRGR_OFF) & 0xFFFF));
00624 }
00625 
00636 static int At91UsartSetSpeed(uint32_t rate)
00637 {
00638     At91UsartDisable();
00639     outr(USARTn_BASE + US_BRGR_OFF, (NutClockGet(NUT_HWCLK_PERIPHERAL) / (8 * (rate)) + 1) / 2);
00640     At91UsartEnable();
00641 
00642     return 0;
00643 }
00644 
00653 static uint8_t At91UsartGetDataBits(void)
00654 {
00655     unsigned int val = inr(USARTn_BASE + US_MR_OFF);
00656 
00657     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00658         val = 9;
00659     }
00660     else {
00661         val &= US_CHRL;
00662         if (val == US_CHRL_5) {
00663             val = 5;
00664         }
00665         else if (val == US_CHRL_6) {
00666             val = 6;
00667         }
00668         else if (val == US_CHRL_7) {
00669             val = 7;
00670         }
00671         else {
00672             val = 8;
00673         }
00674     }
00675     return (uint8_t)val;
00676 }
00677 
00686 static int At91UsartSetDataBits(uint8_t bits)
00687 {
00688     unsigned int val = inr(USARTn_BASE + US_MR_OFF);
00689 
00690     if (bits == 9) {
00691         val &= ~US_PAR;
00692         val |= US_PAR_MULTIDROP;
00693     }
00694     else {
00695         val &= ~US_CHRL;
00696         if (bits == 5) {
00697             val |= US_CHRL_5;
00698         }
00699         else if (bits == 6) {
00700             val |= US_CHRL_6;
00701         }
00702         else if (bits == 7) {
00703             val |= US_CHRL_7;
00704         }
00705         else if (bits == 8) {
00706             val |= US_CHRL_8;
00707         }
00708     }
00709 
00710     At91UsartDisable();
00711     outr(USARTn_BASE + US_MR_OFF, val);
00712     At91UsartEnable();
00713 
00714     /*
00715      * Verify the result.
00716      */
00717     if (At91UsartGetDataBits() != bits) {
00718         return -1;
00719     }
00720     return 0;
00721 }
00722 
00731 static uint8_t At91UsartGetParity(void)
00732 {
00733     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & US_PAR;
00734 
00735     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00736         val = 9;
00737     }
00738     else {
00739         if (val == US_PAR_ODD) {
00740             val = 1;
00741         }
00742         else if (val == US_PAR_EVEN) {
00743             val = 2;
00744         }
00745         else {
00746             val = 0;
00747         }
00748     }
00749     return (uint8_t)val;
00750 }
00751 
00762 static int At91UsartSetParity(uint8_t mode)
00763 {
00764     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & ~US_PAR;
00765 
00766     switch (mode) {
00767     case 0:
00768         val |= US_PAR_NO;
00769         break;
00770     case 1:
00771         val |= US_PAR_ODD;
00772         break;
00773     case 2:
00774         val |= US_PAR_EVEN;
00775         break;
00776     }
00777     At91UsartDisable();
00778     outr(USARTn_BASE + US_MR_OFF, val);
00779     At91UsartEnable();
00780 
00781     /*
00782      * Verify the result.
00783      */
00784     if (At91UsartGetParity() != mode) {
00785         return -1;
00786     }
00787     return 0;
00788 }
00789 
00798 static uint8_t At91UsartGetStopBits(void)
00799 {
00800     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & US_NBSTOP;
00801     if (val == US_NBSTOP_1) {
00802         val = 1;
00803     }
00804     else if (val == US_NBSTOP_2) {
00805         val = 2;
00806     }
00807     else {
00808         val = 3;
00809     }
00810     return (uint8_t)val;
00811 }
00812 
00821 static int At91UsartSetStopBits(uint8_t bits)
00822 {
00823     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & ~US_NBSTOP;
00824 
00825     switch(bits) {
00826     case 1:
00827         val |= US_NBSTOP_1;
00828         break;
00829     case 2:
00830         val |= US_NBSTOP_2;
00831         break;
00832     case 3:
00833         val |= US_NBSTOP_1_5;
00834         break;
00835     }
00836     At91UsartDisable();
00837     outr(USARTn_BASE + US_MR_OFF, val);
00838     At91UsartEnable();
00839 
00840     /*
00841      * Verify the result.
00842      */
00843     if (At91UsartGetStopBits() != bits) {
00844         return -1;
00845     }
00846     return 0;
00847 }
00848 
00854 static uint32_t At91UsartGetStatus(void)
00855 {
00856     uint32_t rc = 0;
00857 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
00858     uint32_t csr = inr(USARTn_BASE + US_CSR_OFF);
00859 #endif
00860 
00861     /*
00862      * Set receiver error flags.
00863      */
00864     if ((rx_errors & US_FRAME) != 0) {
00865         rc |= UART_FRAMINGERROR;
00866     }
00867     if ((rx_errors & US_OVRE) != 0) {
00868         rc |= UART_OVERRUNERROR;
00869     }
00870     if ((rx_errors & US_PARE) != 0) {
00871         rc |= UART_PARITYERROR;
00872     }
00873 
00874     /*
00875      * Determine software handshake status. The flow control status may
00876      * change during interrupt, but this doesn't really hurt us.
00877      */
00878     if (flow_control) {
00879         if (flow_control & XOFF_SENT) {
00880             rc |= UART_RXDISABLED;
00881         }
00882         if (flow_control & XOFF_RCVD) {
00883             rc |= UART_TXDISABLED;
00884         }
00885     }
00886 
00887     /*
00888      * Determine hardware handshake control status.
00889      */
00890 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
00891     /* How to find out? */
00892 #elif defined(UART_RTS_BIT)
00893     /* No definition of the status register? */
00894 #elif defined(UART_USES_NPL)
00895     if (bit_is_set(NPL_RSCR, NPL_RSRTS_BIT)) {
00896         rc |= UART_RTSDISABLED;
00897         if (rts_control) {
00898             rc |= UART_RXDISABLED;
00899         }
00900     } else {
00901         rc |= UART_RTSENABLED;
00902     }
00903 #endif
00904 
00905     /*
00906      * Determine hardware handshake sense status.
00907      */
00908 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
00909     if (csr & US_CTS) {
00910         rc |= UART_CTSDISABLED;
00911         if (cts_sense) {
00912             rc |= UART_RXDISABLED;
00913         }
00914     } else {
00915         rc |= UART_CTSENABLED;
00916     }
00917 #else
00918     if (UART_CTS_IS_ON()) {
00919         rc |= UART_CTSENABLED;
00920     } else {
00921         rc |= UART_CTSDISABLED;
00922         if (cts_sense) {
00923             rc |= UART_RXDISABLED;
00924         }
00925     }
00926 #endif
00927 
00928     /*
00929      * Determine hardware modem sense status.
00930      */
00931 #if 0
00932     /* I'm confused. Awful flag mismatch? Why do we have uart.h and usart.h? */
00933     if (csr & US_RI) {
00934         rc |= UART_RIDISABLED;
00935     } else {
00936         rc |= UART_RIENABLED;
00937     }
00938     if (csr & US_DSR) {
00939         rc |= UART_DSRDISABLED;
00940     } else {
00941         rc |= UART_DSRENABLED;
00942     }
00943     if (csr & US_DCD) {
00944         rc |= UART_DCDDISABLED;
00945     } else {
00946         rc |= UART_DCDENABLED;
00947     }
00948 #endif
00949 
00950     /*
00951      * If transmitter and receiver haven't been detected disabled by any
00952      * of the checks above, then they are probably enabled.
00953      */
00954     if ((rc & UART_RXDISABLED) == 0) {
00955         rc |= UART_RXENABLED;
00956     }
00957     if ((rc & UART_TXDISABLED) == 0) {
00958         rc |= UART_TXENABLED;
00959     }
00960 
00961     /*
00962      * Process multidrop setting.
00963      */
00964     if (tx_aframe) {
00965         rc |= UART_TXADDRFRAME;
00966     } else {
00967         rc |= UART_TXNORMFRAME;
00968     }
00969     return rc;
00970 }
00971 
00979 static int At91UsartSetStatus(uint32_t flags)
00980 {
00981     /*
00982      * Process software handshake control.
00983      */
00984     if (flow_control) {
00985 
00986         /* Access to the flow control status must be atomic. */
00987         NutIrqDisable(&SIG_UART);
00988 
00989         /*
00990          * Enabling or disabling the receiver means to behave like
00991          * having sent a XON or XOFF character resp.
00992          */
00993         if (flags & UART_RXENABLED) {
00994             flow_control &= ~XOFF_SENT;
00995         } else if (flags & UART_RXDISABLED) {
00996             flow_control |= XOFF_SENT;
00997         }
00998 
00999         /*
01000          * Enabling or disabling the transmitter means to behave like
01001          * having received a XON or XOFF character resp.
01002          */
01003         if (flags & UART_TXENABLED) {
01004             flow_control &= ~XOFF_RCVD;
01005         } else if (flags & UART_TXDISABLED) {
01006             flow_control |= XOFF_RCVD;
01007         }
01008         NutIrqEnable(&SIG_UART);
01009     }
01010 
01011     /*
01012      * Process hardware handshake control.
01013      */
01014 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01015     /* Built-in hardware. */
01016     if (rts_control) {
01017         if (flags & UART_RXDISABLED) {
01018             outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
01019         }
01020         if (flags & UART_RXENABLED) {
01021             outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
01022         }
01023     }
01024     if (flags & UART_RTSDISABLED) {
01025         outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
01026     }
01027     if (flags & UART_RTSENABLED) {
01028         outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
01029     }
01030 #else
01031     /* Manually controlled via GPIO. */
01032     if (rts_control) {
01033         if (flags & UART_RXDISABLED) {
01034             UART_RTS_OFF();
01035         }
01036         if (flags & UART_RXENABLED) {
01037             UART_RTS_ON();
01038         }
01039     }
01040     if (flags & UART_RTSDISABLED) {
01041         UART_RTS_OFF();
01042     }
01043     if (flags & UART_RTSENABLED) {
01044         UART_RTS_ON();
01045     }
01046 #endif
01047 
01048 
01049     /*
01050      * Process hardware modem control.
01051      */
01052 #if USE_BUILT_IN_MODEM_CONTROL
01053     /* Built-in hardware. */
01054     if (flags & UART_DTRDISABLED) {
01055         outr(USARTn_BASE + US_CR_OFF, US_DTRDIS);
01056     }
01057     if (flags & UART_DTRENABLED) {
01058         outr(USARTn_BASE + US_CR_OFF, US_DTREN);
01059     }
01060 #endif
01061 
01062     /*
01063      * Process multidrop setting.
01064      */
01065     if (flags & UART_TXADDRFRAME) {
01066         tx_aframe = 1;
01067     }
01068     if (flags & UART_TXNORMFRAME) {
01069         tx_aframe = 0;
01070     }
01071 
01072     /*
01073      * Clear UART receive errors.
01074      */
01075     if (flags & UART_ERRORS) {
01076         outr(USARTn_BASE + US_CR_OFF, US_RSTSTA);
01077     }
01078 
01079     /*
01080      * Verify the result.
01081      */
01082     if ((At91UsartGetStatus() & ~UART_ERRORS) != flags) {
01083         return -1;
01084     }
01085     return 0;
01086 }
01087 
01099 static uint8_t At91UsartGetClockMode(void)
01100 {
01101     return 0;
01102 }
01103 
01117 static int At91UsartSetClockMode(uint8_t mode)
01118 {
01119     return -1;
01120 }
01121 
01130 static uint32_t At91UsartGetFlowControl(void)
01131 {
01132     uint32_t rc = 0;
01133 
01134     if (flow_control) {
01135         rc |= USART_MF_XONXOFF;
01136     } else {
01137         rc &= ~USART_MF_XONXOFF;
01138     }
01139 
01140 #if defined(UART_RTS_BIT) || defined(UART_USES_NPL) || defined(UART_HARDWARE_HANDSHAKE)
01141     if (rts_control) {
01142         rc |= USART_MF_RTSCONTROL;
01143     } else {
01144         rc &= ~USART_MF_RTSCONTROL;
01145     }
01146 #endif
01147 
01148 #if defined(UART_CTS_BIT) || defined(UART_USES_NPL) || defined(UART_HARDWARE_HANDSHAKE)
01149     if (cts_sense) {
01150         rc |= USART_MF_CTSSENSE;
01151     } else {
01152         rc &= ~USART_MF_CTSSENSE;
01153     }
01154 #endif
01155 
01156     if (hdx_control) {
01157         rc |= USART_MF_HALFDUPLEX;
01158     } else {
01159         rc &= ~USART_MF_HALFDUPLEX;
01160     }
01161     return rc;
01162 }
01163 
01174 static int At91UsartSetFlowControl(uint32_t flags)
01175 {
01176 #if USE_BUILT_IN_HARDWARE_HANDSHAKE || USE_BUILT_IN_HALF_DUPLEX
01177     uint32_t mr = inr(USARTn_BASE + US_MR_OFF) & ~US_MODE;
01178 #endif
01179 
01180     /*
01181      * Set software handshake mode.
01182      */
01183     NutIrqDisable(&SIG_UART);
01184     if (flags & USART_MF_XONXOFF) {
01185         if(flow_control == 0) {
01186             flow_control = 1 | XOFF_SENT;  /* force XON to be sent on next read */
01187         }
01188     } else {
01189         flow_control = 0;
01190     }
01191     NutIrqEnable(&SIG_UART);
01192 
01193     /*
01194      * Set RTS control mode.
01195      */
01196     if (flags & USART_MF_RTSCONTROL) {
01197         rts_control = 1;
01198         UART_RTS_PIN_ENABLE();
01199         UART_RTS_OFF();
01200 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01201         outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_HWHANDSHAKE);
01202         cts_sense = 1;
01203 #endif
01204     } else if (rts_control) {
01205         rts_control = 0;
01206         UART_RTS_ON();
01207 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01208         outr(USARTn_BASE + US_MR_OFF, mr);
01209         cts_sense = 0;
01210 #endif
01211     }
01212 
01213     /*
01214      * Set CTS sense mode.
01215      */
01216     if (flags & USART_MF_CTSSENSE) {
01217         cts_sense = 1;
01218         UART_CTS_PIN_ENABLE();
01219 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01220         rts_control = 1;
01221         outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_HWHANDSHAKE);
01222 #endif
01223     } else if (cts_sense) {
01224         cts_sense = 0;
01225 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01226         rts_control = 0;
01227         outr(USARTn_BASE + US_MR_OFF, mr);
01228 #endif
01229     }
01230 
01231     /*
01232      * Set half duplex mode.
01233      */
01234     if (flags & USART_MF_HALFDUPLEX) {
01235         /* Mark half duplex mode enabled. */
01236         hdx_control = 1;
01237         /* Enable half duplex pin. */
01238         UART_HDX_PIN_ENABLE();
01239         UART_HDX_RX();
01240 #if USE_BUILT_IN_HALF_DUPLEX
01241         /* Enable built-in RS-485 mode. */
01242         outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_RS485);
01243 #else
01244         /* Enable USART receive, disable transmit. */
01245         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXDIS);
01246         /* Enable transmit complete interrupt. */
01247         outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
01248 #endif
01249     }
01250     else if (hdx_control) {
01251         hdx_control = 0;
01252 #if USE_BUILT_IN_HALF_DUPLEX
01253         /* Disable built-in RS-485 mode. */
01254         outr(USARTn_BASE + US_MR_OFF, inr(USARTn_BASE + US_MR_OFF) & ~US_MODE);
01255 #else
01256         /* Enable USART receive and transmit. */
01257         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
01258         /* Disable transmit complete interrupt. */
01259         outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
01260 #endif
01261     }
01262     /* No need to call At91UsartGetFlowControl. The result is obvious,
01263     ** because we do not exclude unsupported modes yet. */
01264 
01265     return 0;
01266 }
01267 
01275 static void At91UsartTxStart(void)
01276 {
01277 #if USE_BUILT_IN_HALF_DUPLEX == 0
01278     if (hdx_control) {
01279 #if defined(UART_HDX_BIT) || defined(UART_USES_NPL)
01280         UART_HDX_TX();
01281 #endif
01282         /* Disable USART receive, enable transmit. */
01283         outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXEN);
01284     }
01285 #endif
01286     /* Enable transmit interrupts. */
01287     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
01288 }
01289 
01298 static void At91UsartRxStart(void)
01299 {
01300     /*
01301      * Do any required software flow control.
01302      */
01303     if (flow_control && (flow_control & XOFF_SENT) != 0) {
01304         NutIrqDisable(&SIG_UART);
01305         if ((inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY)) {
01306             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
01307             flow_control &= ~XON_PENDING;
01308         } else {
01309             flow_control |= XON_PENDING;
01310         }
01311         flow_control &= ~(XOFF_SENT | XOFF_PENDING);
01312         NutIrqEnable(&SIG_UART);
01313     }
01314 
01315     /* Enable RTS. */
01316     if (rts_control) {
01317         UART_RTS_ON();
01318     }
01319     /* Enable receive interrupts. */
01320     outr(USARTn_BASE + US_IER_OFF, US_RXRDY);
01321 }
01322 
01323 /*
01324  * \brief Initialize the USART hardware driver.
01325  *
01326  * This function is called during device registration by the upper level
01327  * USART driver through the USARTDCB jump table.
01328  *
01329  * \return 0 on success, -1 otherwise.
01330  */
01331 static int At91UsartInit(void)
01332 {
01333     /*
01334      * Register receive and transmit interrupts.
01335      */
01336     if (NutRegisterIrqHandler(&SIG_UART, At91UsartInterrupt, &dcb_usart)) {
01337         return -1;
01338     }
01339 
01340     /*
01341      * Register CTS sense interrupts.
01342      */
01343 #if defined(UART_CTS_BIT)
01344 
01345     if (GpioRegisterIrqHandler(&sig_GPIO1, UART_CTS_BIT, At91UsartCts, NULL)) {
01346         return -1;
01347     }
01348 #if defined(PS_PCER)
01349     outr(PS_PCER, _BV(UART_CTS_PIO_ID));
01350 #elif defined(PMC_PCER)
01351     outr(PMC_PCER, _BV(UART_CTS_PIO_ID));
01352 #endif
01353 
01354 #elif defined(UART_USES_NPL)
01355 
01356     if (NplRegisterIrqHandler(&sig_RSCTS, At91UsartCts, NULL)) {
01357         return -1;
01358     }
01359 
01360 #endif
01361 
01362     /* Enable UART clock. */
01363 #if defined(US_ID)
01364 #if defined(PS_PCER)
01365     outr(PS_PCER, _BV(US_ID));
01366 #elif defined(PMC_PCER)
01367     outr(PMC_PCER, _BV(US_ID));
01368 #endif
01369 #endif
01370 
01371     /* Disable GPIO on UART tx/rx pins. */
01372     UART_RXTX_PINS_ENABLE();
01373 
01374     /* Reset UART. */
01375     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01376     /* Disable all UART interrupts. */
01377     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01378 
01379 #if defined(US_RCR_OFF) && defined(US_TCR_OFF)
01380     /* Clear UART PDC counter registers. */
01381     outr(USARTn_BASE + US_RCR_OFF, 0);
01382     outr(USARTn_BASE + US_TCR_OFF, 0);
01383 #endif
01384 
01385     /* Set UART baud rate generator register. */
01386     outr(USARTn_BASE + US_BRGR_OFF, (NutArchClockGet(NUT_HWCLK_PERIPHERAL) / (8 * (UART_INIT_BAUDRATE)) + 1) / 2);
01387 
01388     /* Set UART mode to 8 data bits, no parity and 1 stop bit. */
01389     outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1);
01390 
01391     return 0;
01392 }
01393 
01394 /*
01395  * \brief Deinitialize the USART hardware driver.
01396  *
01397  * This function is called during device deregistration by the upper
01398  * level USART driver through the USARTDCB jump table.
01399  *
01400  * \return 0 on success, -1 otherwise.
01401  */
01402 static int At91UsartDeinit(void)
01403 {
01404     /* Deregister receive and transmit interrupts. */
01405     NutRegisterIrqHandler(&SIG_UART, 0, 0);
01406 
01407     /* Reset UART. */
01408     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01409     /* Disable all UART interrupts. */
01410     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01411 
01412     /* Disable UART clock. */
01413 #if defined (US_ID)
01414 #if defined(PS_PCDR)
01415     outr(PS_PCDR, _BV(US_ID));
01416 #elif defined(PMC_PCDR)
01417     outr(PMC_PCDR, _BV(US_ID));
01418 #endif
01419 #endif
01420 
01421     /*
01422      * Disabling flow control shouldn't be required here, because it's up
01423      * to the upper level to do this on the last close or during
01424      * deregistration.
01425      */
01426     hdx_control = 0;
01427     UART_HDX_RX();
01428     cts_sense = 0;
01429     rts_control = 0;
01430 
01431     return 0;
01432 }
01433 

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