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 2706 2009-09-20 21:33:50Z Astralix $
00038  *
00039  * Revision 1.01  2009/09/20 ulrichprinz
00040  * Added support for using DBGU as limited standard USART.
00041  */
00042 
00043 #include <cfg/clock.h>
00044 
00045 #ifdef UART_USES_NPL
00046 #include <dev/npl.h>
00047 #endif
00048 
00049 #include <sys/atom.h>
00050 #include <sys/event.h>
00051 #include <sys/timer.h>
00052 
00053 #include <dev/irqreg.h>
00054 
00055 #include <dev/usartat91.h>
00056 
00057 /*
00058 ** Initial USART settings.
00059 */
00060 #ifndef UART_INIT_BAUDRATE
00061 #define UART_INIT_BAUDRATE  115200
00062 #endif
00063 
00064 /*
00065 ** Add empty placeholders for undefined pin configurations.
00066 */
00067 #ifndef UART_RXTX_PINS_ENABLE
00068 #define UART_RXTX_PINS_ENABLE()
00069 #endif
00070 
00071 #ifndef UART_HDX_PIN_ENABLE
00072 #define UART_HDX_PIN_ENABLE()
00073 #endif
00074 #ifndef UART_HDX_RX
00075 #define UART_HDX_RX()
00076 #endif
00077 #ifndef UART_HDX_TX
00078 #define UART_HDX_TX()
00079 #endif
00080 
00081 #ifndef UART_RTS_PIN_ENABLE
00082 #define UART_RTS_PIN_ENABLE()
00083 #endif
00084 #ifndef UART_RTS_ON
00085 #define UART_RTS_ON()
00086 #endif
00087 #ifndef UART_RTS_OFF
00088 #define UART_RTS_OFF()
00089 #endif
00090 
00091 #ifndef UART_CTS_PIN_ENABLE
00092 #define UART_CTS_PIN_ENABLE()
00093 #endif
00094 #ifndef UART_CTS_IS_ON
00095 #define UART_CTS_IS_ON()    (1)
00096 #endif
00097 
00098 #ifndef UART_MODEM_PINS_ENABLE
00099 #define UART_MODEM_PINS_ENABLE()
00100 #endif
00101 
00102 
00103 /*
00104 ** GPIO controlled half duplex pin.
00105 */
00106 #if defined(UART_HDX_BIT) && defined(UART_HDX_PIO_ID)
00107 
00108 #undef UART_HDX_RX
00109 #undef UART_HDX_TX
00110 #undef UART_HDX_PIN_ENABLE
00111 #undef GPIO_ID
00112 #define GPIO_ID UART_HDX_PIO_ID
00113 #include <cfg/arch/porttran.h>
00114 static INLINE void UART_HDX_PIN_ENABLE(void) {
00115     GPIO_ENABLE(UART_HDX_BIT);
00116     GPIO_OUTPUT(UART_HDX_BIT);
00117 }
00118 #ifdef UART_HDX_FLIP_BIT
00119 static INLINE void UART_HDX_RX(void) { GPIO_SET_HI(UART_HDX_BIT); }
00120 static INLINE void UART_HDX_TX(void) { GPIO_SET_LO(UART_HDX_BIT); }
00121 #else
00122 static INLINE void UART_HDX_RX(void) { GPIO_SET_LO(UART_HDX_BIT); }
00123 static INLINE void UART_HDX_TX(void) { GPIO_SET_HI(UART_HDX_BIT); }
00124 #endif
00125 
00126 #elif defined(UART_USES_NPL)
00127 
00128 #undef UART_HDX_RX
00129 #undef UART_HDX_TX
00130 #define UART_HDX_RX()   cbi(NPL_RSCR, NPL_RSRTS_BIT)
00131 #define UART_HDX_TX()   sbi(NPL_RSCR, NPL_RSRTS_BIT)
00132 
00133 #endif /* UART_HDX_BIT */
00134 
00135 /*
00136 ** GPIO controlled RTS pin.
00137 */
00138 #if defined(UART_RTS_BIT) && defined(UART_RTS_PIO_ID)
00139 
00140 #undef UART_RTS_ON
00141 #undef UART_RTS_OFF
00142 #undef UART_RTS_PIN_ENABLE
00143 #undef GPIO_ID
00144 #define GPIO_ID UART_RTS_PIO_ID
00145 #include <cfg/arch/porttran.h>
00146 static INLINE void UART_RTS_PIN_ENABLE(void) { \
00147     GPIO_ENABLE(UART_RTS_BIT); \
00148     GPIO_OUTPUT(UART_RTS_BIT); \
00149 }
00150 #ifdef UART_RTS_FLIP_BIT
00151 static INLINE void UART_RTS_ON(void) { GPIO_SET_HI(UART_RTS_BIT); }
00152 static INLINE void UART_RTS_OFF(void) { GPIO_SET_LO(UART_RTS_BIT); }
00153 #else
00154 static INLINE void UART_RTS_ON(void) { GPIO_SET_LO(UART_RTS_BIT); }
00155 static INLINE void UART_RTS_OFF(void) { GPIO_SET_HI(UART_RTS_BIT); }
00156 #endif
00157 
00158 #elif defined(UART_USES_NPL)
00159 
00160 #undef UART_RTS_ON
00161 #undef UART_RTS_OFF
00162 #define UART_RTS_ON()   cbi(NPL_RSCR, NPL_RSRTS_BIT)
00163 #define UART_RTS_OFF()  sbi(NPL_RSCR, NPL_RSRTS_BIT)
00164 
00165 #endif
00166 
00167 /*
00168 ** GPIO monitored CTS pin.
00169 */
00170 #if defined(UART_CTS_BIT) && defined(UART_CTS_PIO_ID)
00171 
00172 #undef UART_CTS_IS_ON
00173 #undef UART_CTS_PIN_ENABLE
00174 #undef GPIO_ID
00175 #define GPIO_ID UART_CTS_PIO_ID
00176 #include <cfg/arch/porttran.h>
00177 #ifdef UART_CTS_FLIP_BIT
00178 static INLINE int UART_CTS_IS_ON(void) { return GPIO_GET(UART_CTS_BIT); }
00179 #else
00180 static INLINE int UART_CTS_IS_ON(void) { return !GPIO_GET(UART_CTS_BIT); }
00181 #endif
00182 static INLINE void UART_CTS_PIN_ENABLE(void) { \
00183     GPIO_ENABLE(UART_CTS_BIT); \
00184     GPIO_INPUT(UART_CTS_BIT); \
00185     GPIO_PULLUP_ON(UART_CTS_BIT); \
00186 }
00187 
00188 #elif defined(UART_USES_NPL)
00189 
00190 #undef UART_CTS_IS_ON
00191 static INLINE int UART_CTS_IS_ON(void) {
00192     outw(NPL_SCR, NPL_RSCTS);
00193     return bit_is_set(NPL_SLR, NPL_RSCTS_BIT);
00194 }
00195 
00196 #endif
00197 
00198 /*
00199 ** Determine if we use built-in hardware handshake.
00200 */
00201 #if !defined(USE_BUILT_IN_HARDWARE_HANDSHAKE)
00202 #if defined(UART_HARDWARE_HANDSHAKE) && \
00203     defined(US_MODE_HWHANDSHAKE) && \
00204     !defined(UART_RTS_BIT) && \
00205     !defined(UART_CTS_BIT) && \
00206     !defined(UART_USES_NPL)
00207 #define USE_BUILT_IN_HARDWARE_HANDSHAKE 1
00208 #else
00209 #define USE_BUILT_IN_HARDWARE_HANDSHAKE 0
00210 #endif
00211 #endif
00212 
00213 /*
00214 ** Determine if we use built-in half duplex mode.
00215 */
00216 #if !defined(USE_BUILT_IN_HALF_DUPLEX)
00217 #if defined(UART_HARDWARE_HANDSHAKE) && !defined(UART_HDX_BIT) && !defined(UART_USES_NPL)
00218 #define USE_BUILT_IN_HALF_DUPLEX    1
00219 #else
00220 #define USE_BUILT_IN_HALF_DUPLEX    0
00221 #endif
00222 #endif
00223 
00224 /* Some function renaming for IRQ handling on uarts
00225  * that do not have a separate IRQ instance but a
00226  * merged one with others like DBU on SYS-IRQ or
00227  * external uarts on GPIO-IRQs
00228  */
00229 #if (US_ID==SYSC_ID)
00230 #define NutUartIrqRegister  NutRegisterSysIrqHandler
00231 #define NutUartIrqEnable    NutSysIrqEnable
00232 #define NutUartIrqDisable   NutSysIrqDisable
00233 #else
00234 #define NutUartIrqRegister  NutRegisterIrqHandler
00235 #define NutUartIrqEnable    NutIrqEnable
00236 #define NutUartIrqDisable   NutIrqDisable
00237 #endif
00238 
00243 
00244 /* \brief ASCII code for software flow control, starts transmitter. */
00245 #define ASCII_XON   0x11
00246 /* \brief ASCII code for software flow control, stops transmitter. */
00247 #define ASCII_XOFF  0x13
00248 
00249 /* \brief XON transmit pending flag. */
00250 #define XON_PENDING     0x10
00251 /* \brief XOFF transmit pending flag. */
00252 #define XOFF_PENDING    0x20
00253 /* \brief XOFF sent flag. */
00254 #define XOFF_SENT       0x40
00255 /* \brief XOFF received flag. */
00256 #define XOFF_RCVD       0x80
00257 
00258 
00262 static unsigned int rx_errors;
00263 
00267 static uint_fast8_t flow_control;
00268 
00272 static uint_fast8_t tx_aframe;
00273 
00279 static uint_fast8_t hdx_control;
00280 
00287 static uint_fast8_t rts_control;
00288 
00295 static uint_fast8_t cts_sense;
00296 
00297 #if defined(UART_CTS_BIT) || defined(UART_USES_NPL)
00298 
00308 static void At91UsartCts(void *arg)
00309 {
00310     /* Disable CTS sense interrupt. */
00311 #if defined(UART_USES_NPL)
00312     NplIrqDisable(&sig_RSCTS);
00313     /* Enable transmit interrupt. */
00314     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00315 #else
00316     if (UART_CTS_IS_ON()) {
00317         GpioIrqDisable(&UART_CTS_SIGNAL, UART_CTS_BIT);
00318         /* Enable transmit interrupt. */
00319         outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00320     }
00321 #endif
00322 }
00323 #endif
00324 
00325 #if USE_BUILT_IN_HALF_DUPLEX == 0
00326 /*
00327  * \brief USARTn transmitter empty interrupt handler.
00328  *
00329  * Used with half duplex communication to switch from tranmit to receive
00330  * mode after the last character has been transmitted.
00331  *
00332  * \param arg Pointer to the transmitter ring buffer.
00333  */
00334 static void At91UsartTxEmpty(RINGBUF *rbf)
00335 {
00336     /*
00337      * Check if half duplex mode has been enabled and if all characters
00338      * had been sent out.
00339      */
00340     if (hdx_control && (rbf->rbf_cnt == 0)) {
00341         /*
00342          * Switch to receiver mode:
00343          * Enable USART receive, disable transmit.
00344          * Disable TX-Empty IRQ
00345          */
00346         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXDIS);
00347 #if defined(UART_HDX_BIT) || defined(UART_USES_NPL)
00348         UART_HDX_RX();
00349 #endif
00350     }
00351 }
00352 #endif
00353 
00354 /*
00355  * \brief USARTn transmitter ready interrupt handler.
00356  *
00357  * \param rbf Pointer to the transmitter ring buffer.
00358  */
00359 static void At91UsartTxReady(RINGBUF *rbf)
00360 {
00361     register uint8_t *cp = rbf->rbf_tail;
00362 
00363     /*
00364      * Process pending software flow controls first.
00365      */
00366     if (flow_control & (XON_PENDING | XOFF_PENDING)) {
00367         if (flow_control & XON_PENDING) {
00368             outr(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00369             flow_control |= XOFF_SENT;
00370         } else {
00371             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
00372             flow_control &= ~XOFF_SENT;
00373         }
00374         flow_control &= ~(XON_PENDING | XOFF_PENDING);
00375         return;
00376     }
00377 
00378     if (flow_control & XOFF_RCVD) {
00379         /*
00380          * If XOFF has been received, we disable the transmit interrupts
00381          * and return without sending anything.
00382          */
00383         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00384         return;
00385     }
00386 
00387     /*
00388      * Check if we have more bytes to transmit.
00389      */
00390     if (rbf->rbf_cnt) {
00391 #if defined(UART_CTS_BIT) || defined(UART_USES_NPL)
00392         /*
00393          * If CTS has been disabled, we disable the transmit interrupts,
00394          * enable CTS interrupts and return without sending anything.
00395          */
00396         if (cts_sense && !UART_CTS_IS_ON()) {
00397             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00398 #if defined(UART_CTS_BIT)
00399             GpioIrqEnable(&UART_CTS_SIGNAL, UART_CTS_BIT);
00400 #else
00401             NplIrqEnable(&sig_RSCTS);
00402 #endif
00403             return;
00404         }
00405 #endif
00406 
00407         /*
00408          * Send address in multidrop mode.
00409          */
00410         if (tx_aframe) {
00411             outr(USARTn_BASE + US_CR_OFF, US_SENDA);
00412         }
00413 
00414         /* Start transmission of the next character. */
00415         outr(USARTn_BASE + US_THR_OFF, *cp);
00416         /* Decrement the number of available bytes in the buffer. */
00417         rbf->rbf_cnt--;
00418         /* Wrap around the buffer pointer if we reached its end. */
00419         if (++cp == rbf->rbf_last) {
00420             cp = rbf->rbf_start;
00421         }
00422         rbf->rbf_tail = cp;
00423 
00424 #if USE_BUILT_IN_HALF_DUPLEX == 0
00425         /*
00426          * If software half duplex enabled, we need TX-Empty IRQ for
00427          * detection if last bit of last byte transmission is finished.
00428          */
00429         if( hdx_control && rbf->rbf_cnt == 0) {
00430             outr(USARTn_BASE + US_IER_OFF, US_TXEMPTY);
00431         }
00432 #endif
00433 
00434         /* Send an event if we reached the low watermark. */
00435         if (rbf->rbf_cnt == rbf->rbf_lwm) {
00436             NutEventPostFromIrq(&rbf->rbf_que);
00437         }
00438     }
00439 
00440     /*
00441      * Nothing left to transmit, disable interrupt.
00442      */
00443     else {
00444         /* Disable transmit interrupts. */
00445         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00446         /* Send an event to inform the upper level. */
00447         NutEventPostFromIrq(&rbf->rbf_que);
00448     }
00449 }
00450 
00451 
00452 /*
00453  * \brief USARTn receiver ready interrupt handler.
00454  *
00455  *
00456  * \param rbf Pointer to the receiver ring buffer.
00457  */
00458 
00459 static void At91UsartRxReady(RINGBUF *rbf)
00460 {
00461     register size_t cnt;
00462     register uint8_t ch;
00463 
00464     /*
00465      * We read the received character as early as possible to avoid overflows
00466      * caused by interrupt latency.
00467      */
00468     ch = inb(USARTn_BASE + US_RHR_OFF);
00469 
00470     /* Collect receiver errors. */
00471     rx_errors |= inr(USARTn_BASE + US_CSR_OFF) & (US_OVRE | US_FRAME | US_PARE);
00472 
00473     /*
00474      * Handle software handshake. We have to do this before checking the
00475      * buffer, because flow control must work in write-only mode, where
00476      * there is no receive buffer.
00477      */
00478     if (flow_control) {
00479         /* XOFF character disables transmit interrupts. */
00480         if (ch == ASCII_XOFF) {
00481             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00482             flow_control |= XOFF_RCVD;
00483             return;
00484         }
00485         /* XON enables transmit interrupts. */
00486         else if (ch == ASCII_XON) {
00487             outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00488             flow_control &= ~XOFF_RCVD;
00489             return;
00490         }
00491     }
00492 
00493     /*
00494      * Check buffer overflow.
00495      */
00496     cnt = rbf->rbf_cnt;
00497     if (cnt >= rbf->rbf_siz) {
00498         rx_errors |= US_OVRE;
00499         return;
00500     }
00501 
00502     /* Wake up waiting threads if this is the first byte in the buffer. */
00503     if (cnt++ == 0){
00504         NutEventPostFromIrq(&rbf->rbf_que);
00505     }
00506 
00507     /*
00508      * Check the high watermark for software handshake. If the number of
00509      * buffered bytes is equal or above this mark, then send XOFF.
00510      */
00511     else if (flow_control) {
00512         if(cnt >= rbf->rbf_hwm) {
00513             if((flow_control & XOFF_SENT) == 0) {
00514                 if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00515                     outb(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00516                     flow_control |= XOFF_SENT;
00517                     flow_control &= ~XOFF_PENDING;
00518                 } else {
00519                     flow_control |= XOFF_PENDING;
00520                 }
00521             }
00522         }
00523     }
00524 
00525 #if defined(UART_RTS_BIT) || defined(UART_USES_NPL)
00526     /*
00527      * Check the high watermark for GPIO hardware handshake. If the
00528      * number of buffered bytes is equal or above this mark, then
00529      * disable RTS.
00530      */
00531     else if (rts_control && cnt >= rbf->rbf_hwm) {
00532         UART_RTS_OFF();
00533     }
00534 #endif
00535 
00536     /*
00537      * Store the character and increment and the ring buffer pointer.
00538      */
00539     *rbf->rbf_head++ = ch;
00540     if (rbf->rbf_head == rbf->rbf_last) {
00541         rbf->rbf_head = rbf->rbf_start;
00542     }
00543 
00544     /* Update the ring buffer counter. */
00545     rbf->rbf_cnt = cnt;
00546 }
00547 
00553 static void At91UsartInterrupt(void *arg)
00554 {
00555     USARTDCB *dcb = (USARTDCB *)arg;
00556     unsigned int csr = inr(USARTn_BASE + US_CSR_OFF);
00557 
00558     if (csr & US_RXRDY) {
00559         At91UsartRxReady(&dcb->dcb_rx_rbf);
00560     }
00561     if (csr & US_TXRDY) {
00562         At91UsartTxReady(&dcb->dcb_tx_rbf);
00563     }
00564 
00565 #if USE_BUILT_IN_HALF_DUPLEX == 0
00566     if (csr & US_TXEMPTY) {
00567         At91UsartTxEmpty(&dcb->dcb_tx_rbf);
00568     }
00569 #endif
00570 }
00571 
00578 static void At91UsartEnable(void)
00579 {
00580     /* Enable UART receiver and transmitter. */
00581     outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
00582     /* Globally enable UART interrupts. */
00583     NutUartIrqEnable(&SIG_UART);
00584 }
00585 
00608 static void At91UsartDisable(void)
00609 {
00610     /* Globally disable UART interrupts. */
00611     NutUartIrqDisable(&SIG_UART);
00612     /* Wait until all bits had been shifted out. */
00613     if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00614         while((inr(USARTn_BASE + US_CSR_OFF) & US_TXEMPTY) == 0);
00615     }
00616     /* Disable USART transmit and receive. */
00617     outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXDIS);
00618 }
00619 
00628 static uint32_t At91UsartGetSpeed(void)
00629 {
00630     unsigned int cs;
00631     uint32_t clk;
00632 
00633     clk = NutClockGet(NUT_HWCLK_PERIPHERAL);
00634     cs = inr(USARTn_BASE + US_MR_OFF) & US_CLKS;
00635     if (cs == US_CLKS_MCK8) {
00636         clk /= 8;
00637     }
00638     else if (cs != US_CLKS_MCK) {
00639         clk = 0;
00640     }
00641     return clk / (16UL * (inr(USARTn_BASE + US_BRGR_OFF) & 0xFFFF));
00642 }
00643 
00654 static int At91UsartSetSpeed(uint32_t rate)
00655 {
00656     At91UsartDisable();
00657 #if !(USARTn_BASE == DBGU_BASE)
00658     outr(USARTn_BASE + US_BRGR_OFF, (NutClockGet(NUT_HWCLK_PERIPHERAL) / (8 * (rate)) + 1) / 2);
00659 #else
00660     #if defined(AT91_PLL_MAINCK)
00661         outr(DBGU_BRGR, (At91GetMasterClock() / (8 * rate) + 1) / 2);
00662     #else
00663         outr(DBGU_BRGR, (NutGetCpuClock() / (8 * rate) + 1) / 2);
00664     #endif
00665 #endif
00666     At91UsartEnable();
00667     return 0;
00668 }
00669 
00678 static uint8_t At91UsartGetDataBits(void)
00679 {
00680 #if !(USARTn_BASE == DBGU_BASE)
00681     unsigned int val = inr(USARTn_BASE + US_MR_OFF);
00682 
00683     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00684         val = 9;
00685     }
00686     else {
00687         val &= US_CHRL;
00688         if (val == US_CHRL_5) {
00689             val = 5;
00690         }
00691         else if (val == US_CHRL_6) {
00692             val = 6;
00693         }
00694         else if (val == US_CHRL_7) {
00695             val = 7;
00696         }
00697         else {
00698             val = 8;
00699         }
00700     }
00701     return (uint8_t)val;
00702 #else
00703     /* Not supported by DBGU, always 8 bits */
00704     return 8;
00705 #endif
00706 }
00707 
00716 static int At91UsartSetDataBits(uint8_t bits)
00717 {
00718 #if !(USARTn_BASE == DBGU_BASE)
00719     unsigned int val = inr(USARTn_BASE + US_MR_OFF);
00720 
00721     if (bits == 9) {
00722         val &= ~US_PAR;
00723         val |= US_PAR_MULTIDROP;
00724     }
00725     else {
00726         val &= ~US_CHRL;
00727         if (bits == 5) {
00728             val |= US_CHRL_5;
00729         }
00730         else if (bits == 6) {
00731             val |= US_CHRL_6;
00732         }
00733         else if (bits == 7) {
00734             val |= US_CHRL_7;
00735         }
00736         else if (bits == 8) {
00737             val |= US_CHRL_8;
00738         }
00739     }
00740 
00741     At91UsartDisable();
00742     outr(USARTn_BASE + US_MR_OFF, val);
00743     At91UsartEnable();
00744 
00745     /*
00746      * Verify the result.
00747      */
00748     if (At91UsartGetDataBits() != bits) {
00749         return -1;
00750     }
00751     return 0;
00752 #else
00753     /* Not supported by DBGU, always 8 bits */
00754     return -1;
00755 #endif
00756 }
00757 
00766 static uint8_t At91UsartGetParity(void)
00767 {
00768     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & US_PAR;
00769 
00770     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00771         val = 9;
00772     }
00773     else {
00774         if (val == US_PAR_ODD) {
00775             val = 1;
00776         }
00777         else if (val == US_PAR_EVEN) {
00778             val = 2;
00779         }
00780         else {
00781             val = 0;
00782         }
00783     }
00784     return (uint8_t)val;
00785 }
00786 
00797 static int At91UsartSetParity(uint8_t mode)
00798 {
00799     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & ~US_PAR;
00800 
00801     switch (mode) {
00802     case 0:
00803         val |= US_PAR_NO;
00804         break;
00805     case 1:
00806         val |= US_PAR_ODD;
00807         break;
00808     case 2:
00809         val |= US_PAR_EVEN;
00810         break;
00811     }
00812     At91UsartDisable();
00813     outr(USARTn_BASE + US_MR_OFF, val);
00814     At91UsartEnable();
00815 
00816     /*
00817      * Verify the result.
00818      */
00819     if (At91UsartGetParity() != mode) {
00820         return -1;
00821     }
00822     return 0;
00823 }
00824 
00833 static uint8_t At91UsartGetStopBits(void)
00834 {
00835 #if !(USARTn_BASE == DBGU_BASE)
00836     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & US_NBSTOP;
00837     if (val == US_NBSTOP_1) {
00838         val = 1;
00839     }
00840     else if (val == US_NBSTOP_2) {
00841         val = 2;
00842     }
00843     else {
00844         val = 3;
00845     }
00846     return (uint8_t)val;
00847 #else
00848     /* Not supported by DBGU, always 1 */
00849     return 1;
00850 #endif
00851 }
00852 
00861 static int At91UsartSetStopBits(uint8_t bits)
00862 {
00863 #if !(USARTn_BASE == DBGU_BASE)
00864     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & ~US_NBSTOP;
00865 
00866     switch(bits) {
00867     case 1:
00868         val |= US_NBSTOP_1;
00869         break;
00870     case 2:
00871         val |= US_NBSTOP_2;
00872         break;
00873     case 3:
00874         val |= US_NBSTOP_1_5;
00875         break;
00876     }
00877     At91UsartDisable();
00878     outr(USARTn_BASE + US_MR_OFF, val);
00879     At91UsartEnable();
00880 
00881     /*
00882      * Verify the result.
00883      */
00884     if (At91UsartGetStopBits() != bits) {
00885         return -1;
00886     }
00887 #endif
00888     return 0;
00889 }
00890 
00896 static uint32_t At91UsartGetStatus(void)
00897 {
00898     uint32_t rc = 0;
00899 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
00900     uint32_t csr = inr(USARTn_BASE + US_CSR_OFF);
00901 #endif
00902 
00903     /*
00904      * Set receiver error flags.
00905      */
00906     if ((rx_errors & US_FRAME) != 0) {
00907         rc |= UART_FRAMINGERROR;
00908     }
00909     if ((rx_errors & US_OVRE) != 0) {
00910         rc |= UART_OVERRUNERROR;
00911     }
00912     if ((rx_errors & US_PARE) != 0) {
00913         rc |= UART_PARITYERROR;
00914     }
00915 
00916     /*
00917      * Determine software handshake status. The flow control status may
00918      * change during interrupt, but this doesn't really hurt us.
00919      */
00920     if (flow_control) {
00921         if (flow_control & XOFF_SENT) {
00922             rc |= UART_RXDISABLED;
00923         }
00924         if (flow_control & XOFF_RCVD) {
00925             rc |= UART_TXDISABLED;
00926         }
00927     }
00928 
00929     /*
00930      * Determine hardware handshake control status.
00931      */
00932 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
00933     /* How to find out? */
00934 #elif defined(UART_RTS_BIT)
00935     /* No definition of the status register? */
00936 #elif defined(UART_USES_NPL)
00937     if (bit_is_set(NPL_RSCR, NPL_RSRTS_BIT)) {
00938         rc |= UART_RTSDISABLED;
00939         if (rts_control) {
00940             rc |= UART_RXDISABLED;
00941         }
00942     } else {
00943         rc |= UART_RTSENABLED;
00944     }
00945 #endif
00946 
00947     /*
00948      * Determine hardware handshake sense status.
00949      */
00950 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
00951     if (csr & US_CTS) {
00952         rc |= UART_CTSDISABLED;
00953         if (cts_sense) {
00954             rc |= UART_RXDISABLED;
00955         }
00956     } else {
00957         rc |= UART_CTSENABLED;
00958     }
00959 #else
00960     if (UART_CTS_IS_ON()) {
00961         rc |= UART_CTSENABLED;
00962     } else {
00963         rc |= UART_CTSDISABLED;
00964         if (cts_sense) {
00965             rc |= UART_RXDISABLED;
00966         }
00967     }
00968 #endif
00969 
00970     /*
00971      * Determine hardware modem sense status.
00972      */
00973 #if 0
00974     /* I'm confused. Awful flag mismatch? Why do we have uart.h and usart.h? */
00975     if (csr & US_RI) {
00976         rc |= UART_RIDISABLED;
00977     } else {
00978         rc |= UART_RIENABLED;
00979     }
00980     if (csr & US_DSR) {
00981         rc |= UART_DSRDISABLED;
00982     } else {
00983         rc |= UART_DSRENABLED;
00984     }
00985     if (csr & US_DCD) {
00986         rc |= UART_DCDDISABLED;
00987     } else {
00988         rc |= UART_DCDENABLED;
00989     }
00990 #endif
00991 
00992     /*
00993      * If transmitter and receiver haven't been detected disabled by any
00994      * of the checks above, then they are probably enabled.
00995      */
00996     if ((rc & UART_RXDISABLED) == 0) {
00997         rc |= UART_RXENABLED;
00998     }
00999     if ((rc & UART_TXDISABLED) == 0) {
01000         rc |= UART_TXENABLED;
01001     }
01002 
01003     /*
01004      * Process multidrop setting.
01005      */
01006     if (tx_aframe) {
01007         rc |= UART_TXADDRFRAME;
01008     } else {
01009         rc |= UART_TXNORMFRAME;
01010     }
01011     return rc;
01012 }
01013 
01021 static int At91UsartSetStatus(uint32_t flags)
01022 {
01023     /*
01024      * Process software handshake control.
01025      */
01026     if (flow_control) {
01027 
01028         /* Access to the flow control status must be atomic. */
01029         NutUartIrqDisable(&SIG_UART);
01030 
01031         /*
01032          * Enabling or disabling the receiver means to behave like
01033          * having sent a XON or XOFF character resp.
01034          */
01035         if (flags & UART_RXENABLED) {
01036             flow_control &= ~XOFF_SENT;
01037         } else if (flags & UART_RXDISABLED) {
01038             flow_control |= XOFF_SENT;
01039         }
01040 
01041         /*
01042          * Enabling or disabling the transmitter means to behave like
01043          * having received a XON or XOFF character resp.
01044          */
01045         if (flags & UART_TXENABLED) {
01046             flow_control &= ~XOFF_RCVD;
01047         } else if (flags & UART_TXDISABLED) {
01048             flow_control |= XOFF_RCVD;
01049         }
01050         NutUartIrqEnable(&SIG_UART);
01051     }
01052 
01053     /*
01054      * Process hardware handshake control.
01055      */
01056 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01057     /* Built-in hardware. */
01058     if (rts_control) {
01059         if (flags & UART_RXDISABLED) {
01060             outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
01061         }
01062         if (flags & UART_RXENABLED) {
01063             outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
01064         }
01065     }
01066     if (flags & UART_RTSDISABLED) {
01067         outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
01068     }
01069     if (flags & UART_RTSENABLED) {
01070         outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
01071     }
01072 #else
01073     /* Manually controlled via GPIO. */
01074     if (rts_control) {
01075         if (flags & UART_RXDISABLED) {
01076             UART_RTS_OFF();
01077         }
01078         if (flags & UART_RXENABLED) {
01079             UART_RTS_ON();
01080         }
01081     }
01082     if (flags & UART_RTSDISABLED) {
01083         UART_RTS_OFF();
01084     }
01085     if (flags & UART_RTSENABLED) {
01086         UART_RTS_ON();
01087     }
01088 #endif
01089 
01090 
01091     /*
01092      * Process hardware modem control.
01093      */
01094 #if USE_BUILT_IN_MODEM_CONTROL
01095     /* Built-in hardware. */
01096     if (flags & UART_DTRDISABLED) {
01097         outr(USARTn_BASE + US_CR_OFF, US_DTRDIS);
01098     }
01099     if (flags & UART_DTRENABLED) {
01100         outr(USARTn_BASE + US_CR_OFF, US_DTREN);
01101     }
01102 #endif
01103 
01104     /*
01105      * Process multidrop setting.
01106      */
01107     if (flags & UART_TXADDRFRAME) {
01108         tx_aframe = 1;
01109     }
01110     if (flags & UART_TXNORMFRAME) {
01111         tx_aframe = 0;
01112     }
01113 
01114     /*
01115      * Clear UART receive errors.
01116      */
01117     if (flags & UART_ERRORS) {
01118         outr(USARTn_BASE + US_CR_OFF, US_RSTSTA);
01119     }
01120 
01121     /*
01122      * Verify the result.
01123      */
01124     if ((At91UsartGetStatus() & ~UART_ERRORS) != flags) {
01125         return -1;
01126     }
01127     return 0;
01128 }
01129 
01141 static uint8_t At91UsartGetClockMode(void)
01142 {
01143     return 0;
01144 }
01145 
01159 static int At91UsartSetClockMode(uint8_t mode)
01160 {
01161     return -1;
01162 }
01163 
01172 static uint32_t At91UsartGetFlowControl(void)
01173 {
01174     uint32_t rc = 0;
01175 
01176     if (flow_control) {
01177         rc |= USART_MF_XONXOFF;
01178     } else {
01179         rc &= ~USART_MF_XONXOFF;
01180     }
01181 
01182 #if defined(UART_RTS_BIT) || defined(UART_USES_NPL) || defined(UART_HARDWARE_HANDSHAKE)
01183     if (rts_control) {
01184         rc |= USART_MF_RTSCONTROL;
01185     } else {
01186         rc &= ~USART_MF_RTSCONTROL;
01187     }
01188 #endif
01189 
01190 #if defined(UART_CTS_BIT) || defined(UART_USES_NPL) || defined(UART_HARDWARE_HANDSHAKE)
01191     if (cts_sense) {
01192         rc |= USART_MF_CTSSENSE;
01193     } else {
01194         rc &= ~USART_MF_CTSSENSE;
01195     }
01196 #endif
01197 
01198     if (hdx_control) {
01199         rc |= USART_MF_HALFDUPLEX;
01200     } else {
01201         rc &= ~USART_MF_HALFDUPLEX;
01202     }
01203     return rc;
01204 }
01205 
01216 static int At91UsartSetFlowControl(uint32_t flags)
01217 {
01218 #if USE_BUILT_IN_HARDWARE_HANDSHAKE || USE_BUILT_IN_HALF_DUPLEX
01219     uint32_t mr = inr(USARTn_BASE + US_MR_OFF) & ~US_MODE;
01220 #endif
01221 
01222     /*
01223      * Set software handshake mode.
01224      */
01225     NutUartIrqDisable(&SIG_UART);
01226     if (flags & USART_MF_XONXOFF) {
01227         if(flow_control == 0) {
01228             flow_control = 1 | XOFF_SENT;  /* force XON to be sent on next read */
01229         }
01230     } else {
01231         flow_control = 0;
01232     }
01233     NutUartIrqEnable(&SIG_UART);
01234 
01235     /*
01236      * Set RTS control mode.
01237      */
01238     if (flags & USART_MF_RTSCONTROL) {
01239         rts_control = 1;
01240         UART_RTS_PIN_ENABLE();
01241         UART_RTS_OFF();
01242 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01243         outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_HWHANDSHAKE);
01244         cts_sense = 1;
01245 #endif
01246     } else if (rts_control) {
01247         rts_control = 0;
01248         UART_RTS_ON();
01249 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01250         outr(USARTn_BASE + US_MR_OFF, mr);
01251         cts_sense = 0;
01252 #endif
01253     }
01254 
01255     /*
01256      * Set CTS sense mode.
01257      */
01258     if (flags & USART_MF_CTSSENSE) {
01259         cts_sense = 1;
01260         UART_CTS_PIN_ENABLE();
01261 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01262         rts_control = 1;
01263         outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_HWHANDSHAKE);
01264 #endif
01265     } else if (cts_sense) {
01266         cts_sense = 0;
01267 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01268         rts_control = 0;
01269         outr(USARTn_BASE + US_MR_OFF, mr);
01270 #endif
01271     }
01272 
01273     /*
01274      * Set half duplex mode.
01275      */
01276     if (flags & USART_MF_HALFDUPLEX) {
01277         /* Mark half duplex mode enabled. */
01278         hdx_control = 1;
01279         /* Enable half duplex pin. */
01280         UART_HDX_PIN_ENABLE();
01281         UART_HDX_RX();
01282 #if USE_BUILT_IN_HALF_DUPLEX
01283         /* Enable built-in RS-485 mode. */
01284         outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_RS485);
01285 #else
01286         /* Enable USART receive, disable transmit. */
01287         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXDIS);
01288         /* Enable transmit complete interrupt. */
01289         outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
01290 #endif
01291     }
01292     else if (hdx_control) {
01293         hdx_control = 0;
01294 #if USE_BUILT_IN_HALF_DUPLEX
01295         /* Disable built-in RS-485 mode. */
01296         outr(USARTn_BASE + US_MR_OFF, inr(USARTn_BASE + US_MR_OFF) & ~US_MODE);
01297 #else
01298         /* Enable USART receive and transmit. */
01299         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
01300         /* Disable transmit complete interrupt. */
01301         outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
01302 #endif
01303     }
01304     /* No need to call At91UsartGetFlowControl. The result is obvious,
01305     ** because we do not exclude unsupported modes yet. */
01306 
01307     return 0;
01308 }
01309 
01317 static void At91UsartTxStart(void)
01318 {
01319 #if USE_BUILT_IN_HALF_DUPLEX == 0
01320     if (hdx_control) {
01321 #if defined(UART_HDX_BIT) || defined(UART_USES_NPL)
01322         UART_HDX_TX();
01323 #endif
01324         /* Disable USART receive, enable transmit. */
01325         outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXEN);
01326     }
01327 #endif
01328     /* Enable transmit interrupts. */
01329     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
01330 }
01331 
01340 static void At91UsartRxStart(void)
01341 {
01342     /*
01343      * Do any required software flow control.
01344      */
01345     if (flow_control && (flow_control & XOFF_SENT) != 0) {
01346         NutUartIrqDisable(&SIG_UART);
01347         if ((inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY)) {
01348             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
01349             flow_control &= ~XON_PENDING;
01350         } else {
01351             flow_control |= XON_PENDING;
01352         }
01353         flow_control &= ~(XOFF_SENT | XOFF_PENDING);
01354         NutUartIrqEnable(&SIG_UART);
01355     }
01356 
01357     /* Enable RTS. */
01358     if (rts_control) {
01359         UART_RTS_ON();
01360     }
01361     /* Enable receive interrupts. */
01362     outr(USARTn_BASE + US_IER_OFF, US_RXRDY);
01363 }
01364 
01365 /*
01366  * \brief Initialize the USART hardware driver.
01367  *
01368  * This function is called during device registration by the upper level
01369  * USART driver through the USARTDCB jump table.
01370  *
01371  * \return 0 on success, -1 otherwise.
01372  */
01373 static int At91UsartInit(void)
01374 {
01375     /*
01376      * Register receive and transmit interrupts.
01377      */
01378     if (NutUartIrqRegister(&SIG_UART, At91UsartInterrupt, &dcb_usart)) {
01379         return -1;
01380     }
01381 
01382     /*
01383      * Register CTS sense interrupts.
01384      */
01385 #if defined(UART_CTS_BIT)
01386 
01387     if (GpioRegisterIrqHandler(&sig_GPIO1, UART_CTS_BIT, At91UsartCts, NULL)) {
01388         return -1;
01389     }
01390 #if defined(PS_PCER)
01391     outr(PS_PCER, _BV(UART_CTS_PIO_ID));
01392 #elif defined(PMC_PCER)
01393     outr(PMC_PCER, _BV(UART_CTS_PIO_ID));
01394 #endif
01395 
01396 #elif defined(UART_USES_NPL)
01397 
01398     if (NplRegisterIrqHandler(&sig_RSCTS, At91UsartCts, NULL)) {
01399         return -1;
01400     }
01401 
01402 #endif
01403 
01404     /* Enable UART clock. */
01405 #if defined(US_ID)
01406 #if defined(PS_PCER)
01407     outr(PS_PCER, _BV(US_ID));
01408 #elif defined(PMC_PCER)
01409     outr(PMC_PCER, _BV(US_ID));
01410 #endif
01411 #endif
01412 
01413     /* Disable GPIO on UART tx/rx pins. */
01414     UART_RXTX_PINS_ENABLE();
01415 
01416     /* Reset UART. */
01417     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01418     /* Disable all UART interrupts. */
01419     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01420 
01421 #if defined(US_RCR_OFF) && defined(US_TCR_OFF)
01422     /* Clear UART PDC counter registers. */
01423     outr(USARTn_BASE + US_RCR_OFF, 0);
01424     outr(USARTn_BASE + US_TCR_OFF, 0);
01425 #endif
01426 
01427     /* Set UART baud rate generator register. */
01428     At91UsartSetSpeed( UART_INIT_BAUDRATE);
01429 
01430     /* Set UART mode to 8 data bits, no parity and 1 stop bit. */
01431     outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1);
01432 
01433     return 0;
01434 }
01435 
01436 /*
01437  * \brief Deinitialize the USART hardware driver.
01438  *
01439  * This function is called during device deregistration by the upper
01440  * level USART driver through the USARTDCB jump table.
01441  *
01442  * \return 0 on success, -1 otherwise.
01443  */
01444 static int At91UsartDeinit(void)
01445 {
01446     /* Deregister receive and transmit interrupts. */
01447     NutUartIrqRegister(&SIG_UART, 0, 0);
01448 
01449     /* Reset UART. */
01450     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01451     /* Disable all UART interrupts. */
01452     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01453 
01454     /* Disable UART clock. */
01455 #if defined (US_ID)
01456 #if defined(PS_PCDR)
01457     outr(PS_PCDR, _BV(US_ID));
01458 #elif defined(PMC_PCDR)
01459     outr(PMC_PCDR, _BV(US_ID));
01460 #endif
01461 #endif
01462 
01463     /*
01464      * Disabling flow control shouldn't be required here, because it's up
01465      * to the upper level to do this on the last close or during
01466      * deregistration.
01467      */
01468     hdx_control = 0;
01469     UART_HDX_RX();
01470     cts_sense = 0;
01471     rts_control = 0;
01472 
01473     return 0;
01474 }
01475 

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