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 2685 2009-09-11 12:39:45Z 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_CTS_SIGNAL)) || 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 #else
00296     // TODO: Disable CTS interrupt.
00297 #endif
00298     /* Enable transmit interrupt. */
00299     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00300 }
00301 #endif
00302 
00303 #if USE_BUILT_IN_HALF_DUPLEX == 0
00304 /*
00305  * \brief USARTn transmitter empty interrupt handler.
00306  *
00307  * Used with half duplex communication to switch from tranmit to receive
00308  * mode after the last character has been transmitted.
00309  *
00310  * \param arg Pointer to the transmitter ring buffer.
00311  */
00312 static void At91UsartTxEmpty(RINGBUF *rbf)
00313 {
00314     /*
00315      * Check if half duplex mode has been enabled and if all characters
00316      * had been sent out.
00317      */
00318     if (hdx_control && (rbf->rbf_cnt == 0)) {
00319         /*
00320          * Switch to receiver mode:
00321          * Enable USART receive, disable transmit.
00322          * Disable TX-Empty IRQ
00323          */
00324         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXDIS);
00325 #if defined(UART_HDX_BIT) || defined(UART_USES_NPL)
00326         UART_HDX_RX();
00327 #endif
00328     }
00329 }
00330 #endif
00331 
00332 /*
00333  * \brief USARTn transmitter ready interrupt handler.
00334  *
00335  * \param rbf Pointer to the transmitter ring buffer.
00336  */
00337 static void At91UsartTxReady(RINGBUF *rbf) 
00338 {
00339     register uint8_t *cp = rbf->rbf_tail;
00340 
00341     /*
00342      * Process pending software flow controls first.
00343      */
00344     if (flow_control & (XON_PENDING | XOFF_PENDING)) {
00345         if (flow_control & XON_PENDING) {
00346             outr(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00347             flow_control |= XOFF_SENT;
00348         } else {
00349             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
00350             flow_control &= ~XOFF_SENT;
00351         }
00352         flow_control &= ~(XON_PENDING | XOFF_PENDING);
00353         return;
00354     }
00355 
00356     if (flow_control & XOFF_RCVD) {
00357         /*
00358          * If XOFF has been received, we disable the transmit interrupts
00359          * and return without sending anything.
00360          */
00361         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00362         return;
00363     }
00364 
00365     /*
00366      * Check if we have more bytes to transmit.
00367      */
00368     if (rbf->rbf_cnt) {
00369 #if defined(UART_CTS_BIT) || defined(UART_USES_NPL)
00370         /*
00371          * If CTS has been disabled, we disable the transmit interrupts,
00372          * enable CTS interrupts and return without sending anything.
00373          */
00374         if (cts_sense && !UART_CTS_IS_ON()) {
00375             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00376 #if defined(UART_CTS_BIT)
00377             // TODO: Disable CTS interrupt.
00378 #else
00379             NplIrqEnable(&sig_RSCTS);
00380 #endif
00381             return;
00382         }
00383 #endif
00384 
00385         /*
00386          * Send address in multidrop mode.
00387          */
00388         if (tx_aframe) {
00389             outr(USARTn_BASE + US_CR_OFF, US_SENDA);
00390         }
00391 
00392         /* Start transmission of the next character. */
00393         outr(USARTn_BASE + US_THR_OFF, *cp);
00394         /* Decrement the number of available bytes in the buffer. */
00395         rbf->rbf_cnt--;
00396         /* Wrap around the buffer pointer if we reached its end. */
00397         if (++cp == rbf->rbf_last) {
00398             cp = rbf->rbf_start;
00399         }
00400         rbf->rbf_tail = cp;
00401 
00402 #if USE_BUILT_IN_HALF_DUPLEX == 0
00403         /* 
00404          * If software half duplex enabled, we need TX-Empty IRQ for
00405          * detection if last bit of last byte transmission is finished.
00406          */
00407         if( hdx_control && rbf->rbf_cnt == 0) {
00408             outr(USARTn_BASE + US_IER_OFF, US_TXEMPTY);
00409         }
00410 #endif
00411 
00412         /* Send an event if we reached the low watermark. */
00413         if (rbf->rbf_cnt == rbf->rbf_lwm) {
00414             NutEventPostFromIrq(&rbf->rbf_que);
00415         }
00416     }
00417 
00418     /*
00419      * Nothing left to transmit, disable interrupt.
00420      */
00421     else {
00422         /* Disable transmit interrupts. */
00423         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00424         /* Send an event to inform the upper level. */
00425         NutEventPostFromIrq(&rbf->rbf_que);
00426     }
00427 }
00428 
00429 
00430 /*
00431  * \brief USARTn receiver ready interrupt handler.
00432  *
00433  *
00434  * \param rbf Pointer to the receiver ring buffer.
00435  */
00436 
00437 static void At91UsartRxReady(RINGBUF *rbf) 
00438 {
00439     register size_t cnt;
00440     register uint8_t ch;
00441 
00442     /*
00443      * We read the received character as early as possible to avoid overflows
00444      * caused by interrupt latency.
00445      */
00446     ch = inb(USARTn_BASE + US_RHR_OFF);
00447 
00448     /* Collect receiver errors. */
00449     rx_errors |= inr(USARTn_BASE + US_CSR_OFF) & (US_OVRE | US_FRAME | US_PARE);
00450 
00451     /*
00452      * Handle software handshake. We have to do this before checking the
00453      * buffer, because flow control must work in write-only mode, where
00454      * there is no receive buffer.
00455      */
00456     if (flow_control) {
00457         /* XOFF character disables transmit interrupts. */
00458         if (ch == ASCII_XOFF) {
00459             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00460             flow_control |= XOFF_RCVD;
00461             return;
00462         }
00463         /* XON enables transmit interrupts. */
00464         else if (ch == ASCII_XON) {
00465             outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00466             flow_control &= ~XOFF_RCVD;
00467             return;
00468         }
00469     }
00470 
00471     /*
00472      * Check buffer overflow.
00473      */
00474     cnt = rbf->rbf_cnt;
00475     if (cnt >= rbf->rbf_siz) {
00476         rx_errors |= US_OVRE;
00477         return;
00478     }
00479 
00480     /* Wake up waiting threads if this is the first byte in the buffer. */
00481     if (cnt++ == 0){
00482         NutEventPostFromIrq(&rbf->rbf_que);
00483     }
00484 
00485     /*
00486      * Check the high watermark for software handshake. If the number of
00487      * buffered bytes is equal or above this mark, then send XOFF.
00488      */
00489     else if (flow_control) {
00490         if(cnt >= rbf->rbf_hwm) {
00491             if((flow_control & XOFF_SENT) == 0) {
00492                 if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00493                     outb(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00494                     flow_control |= XOFF_SENT;
00495                     flow_control &= ~XOFF_PENDING;
00496                 } else {
00497                     flow_control |= XOFF_PENDING;
00498                 }
00499             }
00500         }
00501     }
00502 
00503 #if defined(UART_RTS_BIT) || defined(UART_USES_NPL)
00504     /*
00505      * Check the high watermark for GPIO hardware handshake. If the 
00506      * number of buffered bytes is equal or above this mark, then 
00507      * disable RTS.
00508      */
00509     else if (rts_control && cnt >= rbf->rbf_hwm) {
00510         UART_RTS_OFF();
00511     }
00512 #endif
00513 
00514     /*
00515      * Store the character and increment and the ring buffer pointer.
00516      */
00517     *rbf->rbf_head++ = ch;
00518     if (rbf->rbf_head == rbf->rbf_last) {
00519         rbf->rbf_head = rbf->rbf_start;
00520     }
00521 
00522     /* Update the ring buffer counter. */
00523     rbf->rbf_cnt = cnt;
00524 }
00525 
00531 static void At91UsartInterrupt(void *arg)
00532 {
00533     USARTDCB *dcb = (USARTDCB *)arg;
00534     unsigned int csr = inr(USARTn_BASE + US_CSR_OFF);
00535 
00536     if (csr & US_RXRDY) {
00537         At91UsartRxReady(&dcb->dcb_rx_rbf);
00538     }
00539     if (csr & US_TXRDY) {
00540         At91UsartTxReady(&dcb->dcb_tx_rbf);
00541     }
00542 
00543 #if USE_BUILT_IN_HALF_DUPLEX == 0
00544     if (csr & US_TXEMPTY) {
00545         At91UsartTxEmpty(&dcb->dcb_tx_rbf);
00546     }
00547 #endif
00548 }
00549 
00556 static void At91UsartEnable(void)
00557 {
00558     /* Enable UART receiver and transmitter. */
00559     outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
00560     /* Globally enable UART interrupts. */
00561     NutIrqEnable(&SIG_UART);
00562 }
00563 
00586 static void At91UsartDisable(void)
00587 {
00588     /* Globally disable UART interrupts. */
00589     NutIrqDisable(&SIG_UART);
00590     /* Wait until all bits had been shifted out. */
00591     if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00592         while((inr(USARTn_BASE + US_CSR_OFF) & US_TXEMPTY) == 0);
00593     }
00594     /* Disable USART transmit and receive. */
00595     outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXDIS);
00596 }
00597 
00606 static uint32_t At91UsartGetSpeed(void)
00607 {
00608     unsigned int cs;
00609     uint32_t clk;
00610 
00611     clk = NutClockGet(NUT_HWCLK_PERIPHERAL);
00612     cs = inr(USARTn_BASE + US_MR_OFF) & US_CLKS;
00613     if (cs == US_CLKS_MCK8) {
00614         clk /= 8;
00615     }
00616     else if (cs != US_CLKS_MCK) {
00617         clk = 0;
00618     }
00619     return clk / (16UL * (inr(USARTn_BASE + US_BRGR_OFF) & 0xFFFF));
00620 }
00621 
00632 static int At91UsartSetSpeed(uint32_t rate)
00633 {
00634     At91UsartDisable();
00635     outr(USARTn_BASE + US_BRGR_OFF, (NutClockGet(NUT_HWCLK_PERIPHERAL) / (8 * (rate)) + 1) / 2);
00636     At91UsartEnable();
00637 
00638     return 0;
00639 }
00640 
00649 static uint8_t At91UsartGetDataBits(void)
00650 {
00651     unsigned int val = inr(USARTn_BASE + US_MR_OFF);
00652 
00653     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00654         val = 9;
00655     }
00656     else {
00657         val &= US_CHRL;
00658         if (val == US_CHRL_5) {
00659             val = 5;
00660         }
00661         else if (val == US_CHRL_6) {
00662             val = 6;
00663         }
00664         else if (val == US_CHRL_7) {
00665             val = 7;
00666         }
00667         else {
00668             val = 8;
00669         }
00670     }
00671     return (uint8_t)val;
00672 }
00673 
00682 static int At91UsartSetDataBits(uint8_t bits)
00683 {
00684     unsigned int val = inr(USARTn_BASE + US_MR_OFF);
00685 
00686     if (bits == 9) {
00687         val &= ~US_PAR;
00688         val |= US_PAR_MULTIDROP;
00689     }
00690     else {
00691         val &= ~US_CHRL;
00692         if (bits == 5) {
00693             val |= US_CHRL_5;
00694         }
00695         else if (bits == 6) {
00696             val |= US_CHRL_6;
00697         }
00698         else if (bits == 7) {
00699             val |= US_CHRL_7;
00700         }
00701         else if (bits == 8) {
00702             val |= US_CHRL_8;
00703         }
00704     }
00705 
00706     At91UsartDisable();
00707     outr(USARTn_BASE + US_MR_OFF, val);
00708     At91UsartEnable();
00709 
00710     /*
00711      * Verify the result.
00712      */
00713     if (At91UsartGetDataBits() != bits) {
00714         return -1;
00715     }
00716     return 0;
00717 }
00718 
00727 static uint8_t At91UsartGetParity(void)
00728 {
00729     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & US_PAR;
00730 
00731     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00732         val = 9;
00733     }
00734     else {
00735         if (val == US_PAR_ODD) {
00736             val = 1;
00737         }
00738         else if (val == US_PAR_EVEN) {
00739             val = 2;
00740         }
00741         else {
00742             val = 0;
00743         }
00744     }
00745     return (uint8_t)val;
00746 }
00747 
00758 static int At91UsartSetParity(uint8_t mode)
00759 {
00760     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & ~US_PAR;
00761 
00762     switch (mode) {
00763     case 0:
00764         val |= US_PAR_NO;
00765         break;
00766     case 1:
00767         val |= US_PAR_ODD;
00768         break;
00769     case 2:
00770         val |= US_PAR_EVEN;
00771         break;
00772     }
00773     At91UsartDisable();
00774     outr(USARTn_BASE + US_MR_OFF, val);
00775     At91UsartEnable();
00776 
00777     /*
00778      * Verify the result.
00779      */
00780     if (At91UsartGetParity() != mode) {
00781         return -1;
00782     }
00783     return 0;
00784 }
00785 
00794 static uint8_t At91UsartGetStopBits(void)
00795 {
00796     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & US_NBSTOP;
00797     if (val == US_NBSTOP_1) {
00798         val = 1;
00799     }
00800     else if (val == US_NBSTOP_2) {
00801         val = 2;
00802     }
00803     else {
00804         val = 3;
00805     }
00806     return (uint8_t)val;
00807 }
00808 
00817 static int At91UsartSetStopBits(uint8_t bits)
00818 {
00819     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & ~US_NBSTOP;
00820 
00821     switch(bits) {
00822     case 1:
00823         val |= US_NBSTOP_1;
00824         break;
00825     case 2:
00826         val |= US_NBSTOP_2;
00827         break;
00828     case 3:
00829         val |= US_NBSTOP_1_5;
00830         break;
00831     }
00832     At91UsartDisable();
00833     outr(USARTn_BASE + US_MR_OFF, val);
00834     At91UsartEnable();
00835 
00836     /*
00837      * Verify the result.
00838      */
00839     if (At91UsartGetStopBits() != bits) {
00840         return -1;
00841     }
00842     return 0;
00843 }
00844 
00850 static uint32_t At91UsartGetStatus(void)
00851 {
00852     uint32_t rc = 0;
00853 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
00854     uint32_t csr = inr(USARTn_BASE + US_CSR_OFF);
00855 #endif
00856 
00857     /*
00858      * Set receiver error flags.
00859      */
00860     if ((rx_errors & US_FRAME) != 0) {
00861         rc |= UART_FRAMINGERROR;
00862     }
00863     if ((rx_errors & US_OVRE) != 0) {
00864         rc |= UART_OVERRUNERROR;
00865     }
00866     if ((rx_errors & US_PARE) != 0) {
00867         rc |= UART_PARITYERROR;
00868     }
00869 
00870     /*
00871      * Determine software handshake status. The flow control status may
00872      * change during interrupt, but this doesn't really hurt us.
00873      */
00874     if (flow_control) {
00875         if (flow_control & XOFF_SENT) {
00876             rc |= UART_RXDISABLED;
00877         }
00878         if (flow_control & XOFF_RCVD) {
00879             rc |= UART_TXDISABLED;
00880         }
00881     }
00882 
00883     /*
00884      * Determine hardware handshake control status.
00885      */
00886 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
00887     /* How to find out? */
00888 #elif defined(UART_RTS_BIT)
00889     /* No definition of the status register? */
00890 #elif defined(UART_USES_NPL)
00891     if (bit_is_set(NPL_RSCR, NPL_RSRTS_BIT)) {
00892         rc |= UART_RTSDISABLED;
00893         if (rts_control) {
00894             rc |= UART_RXDISABLED;
00895         }
00896     } else {
00897         rc |= UART_RTSENABLED;
00898     }
00899 #endif
00900 
00901     /*
00902      * Determine hardware handshake sense status.
00903      */
00904 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
00905     if (csr & US_CTS) {
00906         rc |= UART_CTSDISABLED;
00907         if (cts_sense) {
00908             rc |= UART_RXDISABLED;
00909         }
00910     } else {
00911         rc |= UART_CTSENABLED;
00912     }
00913 #else
00914     if (UART_CTS_IS_ON()) {
00915         rc |= UART_CTSENABLED;
00916     } else {
00917         rc |= UART_CTSDISABLED;
00918         if (cts_sense) {
00919             rc |= UART_RXDISABLED;
00920         }
00921     }
00922 #endif
00923 
00924     /*
00925      * Determine hardware modem sense status.
00926      */
00927 #if 0
00928     /* I'm confused. Awful flag mismatch? Why do we have uart.h and usart.h? */
00929     if (csr & US_RI) {
00930         rc |= UART_RIDISABLED;
00931     } else {
00932         rc |= UART_RIENABLED;
00933     }
00934     if (csr & US_DSR) {
00935         rc |= UART_DSRDISABLED;
00936     } else {
00937         rc |= UART_DSRENABLED;
00938     }
00939     if (csr & US_DCD) {
00940         rc |= UART_DCDDISABLED;
00941     } else {
00942         rc |= UART_DCDENABLED;
00943     }
00944 #endif
00945 
00946     /*
00947      * If transmitter and receiver haven't been detected disabled by any
00948      * of the checks above, then they are probably enabled.
00949      */
00950     if ((rc & UART_RXDISABLED) == 0) {
00951         rc |= UART_RXENABLED;
00952     }
00953     if ((rc & UART_TXDISABLED) == 0) {
00954         rc |= UART_TXENABLED;
00955     }
00956 
00957     /*
00958      * Process multidrop setting.
00959      */
00960     if (tx_aframe) {
00961         rc |= UART_TXADDRFRAME;
00962     } else {
00963         rc |= UART_TXNORMFRAME;
00964     }
00965     return rc;
00966 }
00967 
00975 static int At91UsartSetStatus(uint32_t flags)
00976 {
00977     /*
00978      * Process software handshake control.
00979      */
00980     if (flow_control) {
00981 
00982         /* Access to the flow control status must be atomic. */
00983         NutIrqDisable(&SIG_UART);
00984 
00985         /*
00986          * Enabling or disabling the receiver means to behave like
00987          * having sent a XON or XOFF character resp.
00988          */
00989         if (flags & UART_RXENABLED) {
00990             flow_control &= ~XOFF_SENT;
00991         } else if (flags & UART_RXDISABLED) {
00992             flow_control |= XOFF_SENT;
00993         }
00994 
00995         /*
00996          * Enabling or disabling the transmitter means to behave like
00997          * having received a XON or XOFF character resp.
00998          */
00999         if (flags & UART_TXENABLED) {
01000             flow_control &= ~XOFF_RCVD;
01001         } else if (flags & UART_TXDISABLED) {
01002             flow_control |= XOFF_RCVD;
01003         }
01004         NutIrqEnable(&SIG_UART);
01005     }
01006 
01007     /*
01008      * Process hardware handshake control.
01009      */
01010 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01011     /* Built-in hardware. */
01012     if (rts_control) {
01013         if (flags & UART_RXDISABLED) {
01014             outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
01015         }
01016         if (flags & UART_RXENABLED) {
01017             outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
01018         }
01019     }
01020     if (flags & UART_RTSDISABLED) {
01021         outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
01022     }
01023     if (flags & UART_RTSENABLED) {
01024         outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
01025     }
01026 #else
01027     /* Manually controlled via GPIO. */
01028     if (rts_control) {
01029         if (flags & UART_RXDISABLED) {
01030             UART_RTS_OFF();
01031         }
01032         if (flags & UART_RXENABLED) {
01033             UART_RTS_ON();
01034         }
01035     }
01036     if (flags & UART_RTSDISABLED) {
01037         UART_RTS_OFF();
01038     }
01039     if (flags & UART_RTSENABLED) {
01040         UART_RTS_ON();
01041     }
01042 #endif
01043 
01044 
01045     /*
01046      * Process hardware modem control.
01047      */
01048 #if USE_BUILT_IN_MODEM_CONTROL
01049     /* Built-in hardware. */
01050     if (flags & UART_DTRDISABLED) {
01051         outr(USARTn_BASE + US_CR_OFF, US_DTRDIS);
01052     }
01053     if (flags & UART_DTRENABLED) {
01054         outr(USARTn_BASE + US_CR_OFF, US_DTREN);
01055     }
01056 #endif
01057 
01058     /*
01059      * Process multidrop setting.
01060      */
01061     if (flags & UART_TXADDRFRAME) {
01062         tx_aframe = 1;
01063     }
01064     if (flags & UART_TXNORMFRAME) {
01065         tx_aframe = 0;
01066     }
01067 
01068     /*
01069      * Clear UART receive errors.
01070      */
01071     if (flags & UART_ERRORS) {
01072         outr(USARTn_BASE + US_CR_OFF, US_RSTSTA);
01073     }
01074 
01075     /*
01076      * Verify the result.
01077      */
01078     if ((At91UsartGetStatus() & ~UART_ERRORS) != flags) {
01079         return -1;
01080     }
01081     return 0;
01082 }
01083 
01095 static uint8_t At91UsartGetClockMode(void)
01096 {
01097     return 0;
01098 }
01099 
01113 static int At91UsartSetClockMode(uint8_t mode)
01114 {
01115     return -1;
01116 }
01117 
01126 static uint32_t At91UsartGetFlowControl(void)
01127 {
01128     uint32_t rc = 0;
01129 
01130     if (flow_control) {
01131         rc |= USART_MF_XONXOFF;
01132     } else {
01133         rc &= ~USART_MF_XONXOFF;
01134     }
01135 
01136 #if defined(UART_RTS_BIT) || defined(UART_USES_NPL) || defined(UART_HARDWARE_HANDSHAKE)
01137     if (rts_control) {
01138         rc |= USART_MF_RTSCONTROL;
01139     } else {
01140         rc &= ~USART_MF_RTSCONTROL;
01141     }
01142 #endif
01143 
01144 #if defined(UART_CTS_BIT) || defined(UART_USES_NPL) || defined(UART_HARDWARE_HANDSHAKE)
01145     if (cts_sense) {
01146         rc |= USART_MF_CTSSENSE;
01147     } else {
01148         rc &= ~USART_MF_CTSSENSE;
01149     }
01150 #endif
01151 
01152     if (hdx_control) {
01153         rc |= USART_MF_HALFDUPLEX;
01154     } else {
01155         rc &= ~USART_MF_HALFDUPLEX;
01156     }
01157     return rc;
01158 }
01159 
01170 static int At91UsartSetFlowControl(uint32_t flags)
01171 {
01172 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01173     uint32_t mr = inr(USARTn_BASE + US_MR_OFF) & ~US_MODE;
01174 #endif
01175 
01176     /*
01177      * Set software handshake mode.
01178      */
01179     NutIrqDisable(&SIG_UART);
01180     if (flags & USART_MF_XONXOFF) {
01181         if(flow_control == 0) {
01182             flow_control = 1 | XOFF_SENT;  /* force XON to be sent on next read */
01183         }
01184     } else {
01185         flow_control = 0;
01186     }
01187     NutIrqEnable(&SIG_UART);
01188 
01189     /*
01190      * Set RTS control mode.
01191      */
01192     if (flags & USART_MF_RTSCONTROL) {
01193         rts_control = 1;
01194         UART_RTS_PIN_ENABLE();
01195         UART_RTS_OFF();
01196 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01197         outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_HWHANDSHAKE);
01198         cts_sense = 1;
01199 #endif
01200     } else if (rts_control) {
01201         rts_control = 0;
01202         UART_RTS_ON();
01203 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01204         outr(USARTn_BASE + US_MR_OFF, mr);
01205         cts_sense = 0;
01206 #endif
01207     }
01208 
01209     /*
01210      * Set CTS sense mode.
01211      */
01212     if (flags & USART_MF_CTSSENSE) {
01213         cts_sense = 1;
01214         UART_CTS_PIN_ENABLE();
01215 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01216         rts_control = 1;
01217         outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_HWHANDSHAKE);
01218 #endif
01219     } else if (cts_sense) {
01220         cts_sense = 0;
01221 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01222         rts_control = 0;
01223         outr(USARTn_BASE + US_MR_OFF, mr);
01224 #endif
01225     }
01226 
01227     /*
01228      * Set half duplex mode.
01229      */
01230     if (flags & USART_MF_HALFDUPLEX) {
01231         /* Mark half duplex mode enabled. */
01232         hdx_control = 1;
01233         /* Enable half duplex pin. */
01234         UART_HDX_PIN_ENABLE();
01235         UART_HDX_RX();
01236 #if USE_BUILT_IN_HALF_DUPLEX
01237         /* Enable built-in RS-485 mode. */
01238         outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_RS485);
01239 #else
01240         /* Enable USART receive, disable transmit. */
01241         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXDIS);
01242         /* Enable transmit complete interrupt. */
01243         outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
01244 #endif
01245     }
01246     else if (hdx_control) {
01247         hdx_control = 0;
01248 #if USE_BUILT_IN_HALF_DUPLEX
01249         /* Disable built-in RS-485 mode. */
01250         outr(USARTn_BASE + US_MR_OFF, inr(USARTn_BASE + US_MR_OFF) & ~US_MODE);
01251 #else
01252         /* Enable USART receive and transmit. */
01253         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
01254         /* Disable transmit complete interrupt. */
01255         outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
01256 #endif
01257     }
01258     /* No need to call At91UsartGetFlowControl. The result is obvious,
01259     ** because we do not exclude unsupported modes yet. */
01260     return 0;
01261 }
01262 
01270 static void At91UsartTxStart(void)
01271 {
01272 #if USE_BUILT_IN_HALF_DUPLEX == 0
01273     if (hdx_control) {
01274 #if defined(UART_HDX_BIT) || defined(UART_USES_NPL)
01275         UART_HDX_TX();
01276 #endif
01277         /* Disable USART receive, enable transmit. */
01278         outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXEN);
01279     }
01280 #endif
01281     /* Enable transmit interrupts. */
01282     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
01283 }
01284 
01293 static void At91UsartRxStart(void)
01294 {
01295     /*
01296      * Do any required software flow control.
01297      */
01298     if (flow_control && (flow_control & XOFF_SENT) != 0) {
01299         NutIrqDisable(&SIG_UART);
01300         if ((inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY)) {
01301             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
01302             flow_control &= ~XON_PENDING;
01303         } else {
01304             flow_control |= XON_PENDING;
01305         }
01306         flow_control &= ~(XOFF_SENT | XOFF_PENDING);
01307         NutIrqEnable(&SIG_UART);
01308     }
01309 
01310     /* Enable RTS. */
01311     if (rts_control) {
01312         UART_RTS_ON();
01313     }
01314 }
01315 
01316 /*
01317  * \brief Initialize the USART hardware driver.
01318  *
01319  * This function is called during device registration by the upper level
01320  * USART driver through the USARTDCB jump table.
01321  *
01322  * \return 0 on success, -1 otherwise.
01323  */
01324 static int At91UsartInit(void)
01325 {
01326     /*
01327      * Register receive and transmit interrupts.
01328      */
01329     if (NutRegisterIrqHandler(&SIG_UART, At91UsartInterrupt, &dcb_usart)) {
01330         return -1;
01331     }
01332 
01333     /*
01334      * Register CTS sense interrupts.
01335      */
01336 #if defined(UART_CTS_BIT) && defined(UART_CTS_SIGNAL)
01337     if (NutRegisterIrqHandler(&UART_CTS_SIGNAL, At91UsartCts, NULL)) {
01338         return -1;
01339     }
01340 #elif defined(UART_USES_NPL)
01341     if (NplRegisterIrqHandler(&sig_RSCTS, At91UsartCts, NULL)) {
01342         return -1;
01343     }
01344 #endif
01345 
01346     /* Enable UART clock. */
01347 #if defined(US_ID)
01348 #if defined(PS_PCER)
01349     outr(PS_PCER, _BV(US_ID));
01350 #elif defined(PMC_PCER)
01351     outr(PMC_PCER, _BV(US_ID));
01352 #endif
01353 #endif
01354 
01355     /* Disable GPIO on UART tx/rx pins. */
01356     UART_RXTX_PINS_ENABLE();
01357 
01358     /* Reset UART. */
01359     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01360     /* Disable all UART interrupts. */
01361     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01362 
01363 #if defined(US_RCR_OFF) && defined(US_TCR_OFF)
01364     /* Clear UART PDC counter registers. */
01365     outr(USARTn_BASE + US_RCR_OFF, 0);
01366     outr(USARTn_BASE + US_TCR_OFF, 0);
01367 #endif
01368 
01369     /* Set UART baud rate generator register. */
01370     outr(USARTn_BASE + US_BRGR_OFF, (NutArchClockGet(NUT_HWCLK_PERIPHERAL) / (8 * (UART_INIT_BAUDRATE)) + 1) / 2);
01371 
01372     /* Set UART mode to 8 data bits, no parity and 1 stop bit. */
01373     outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1);
01374 
01375     return 0;
01376 }
01377 
01378 /*
01379  * \brief Deinitialize the USART hardware driver.
01380  *
01381  * This function is called during device deregistration by the upper
01382  * level USART driver through the USARTDCB jump table.
01383  *
01384  * \return 0 on success, -1 otherwise.
01385  */
01386 static int At91UsartDeinit(void)
01387 {
01388     /* Deregister receive and transmit interrupts. */
01389     NutRegisterIrqHandler(&SIG_UART, 0, 0);
01390 
01391     /* Reset UART. */
01392     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01393     /* Disable all UART interrupts. */
01394     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01395 
01396     /* Disable UART clock. */
01397 #if defined (US_ID)
01398 #if defined(PS_PCDR)
01399     outr(PS_PCDR, _BV(US_ID));
01400 #elif defined(PMC_PCDR)
01401     outr(PMC_PCDR, _BV(US_ID));
01402 #endif
01403 #endif
01404 
01405     /*
01406      * Disabling flow control shouldn't be required here, because it's up
01407      * to the upper level to do this on the last close or during
01408      * deregistration.
01409      */
01410     hdx_control = 0;
01411     UART_HDX_RX();
01412     cts_sense = 0;
01413     rts_control = 0;
01414 
01415     return 0;
01416 }
01417 

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