Nut/OS  4.10.3
API Reference
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 3449 2011-05-31 19:08:15Z mifi $
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 #if US_ID == US1_ID
00131 #define UART_HDX_RX()   if (inr(NPL_RSCR) & NPL_RSUS1P) sbi(NPL_RSCR, NPL_RSRTS_BIT)
00132 #define UART_HDX_TX()   if (inr(NPL_RSCR) & NPL_RSUS1P) cbi(NPL_RSCR, NPL_RSRTS_BIT)
00133 #else
00134 #define UART_HDX_RX()   if ((inr(NPL_RSCR) & NPL_RSUS1P) == 0) sbi(NPL_RSCR, NPL_RSRTS_BIT)
00135 #define UART_HDX_TX()   if ((inr(NPL_RSCR) & NPL_RSUS1P) == 0) cbi(NPL_RSCR, NPL_RSRTS_BIT)
00136 #endif
00137 
00138 #endif /* UART_HDX_BIT */
00139 
00140 /*
00141 ** GPIO controlled RTS pin.
00142 */
00143 #if defined(UART_RTS_BIT) && defined(UART_RTS_PIO_ID)
00144 
00145 #undef UART_RTS_ON
00146 #undef UART_RTS_OFF
00147 #undef UART_RTS_PIN_ENABLE
00148 #undef GPIO_ID
00149 #define GPIO_ID UART_RTS_PIO_ID
00150 #include <cfg/arch/porttran.h>
00151 static INLINE void UART_RTS_PIN_ENABLE(void) { \
00152     GPIO_ENABLE(UART_RTS_BIT); \
00153     GPIO_OUTPUT(UART_RTS_BIT); \
00154 }
00155 #ifdef UART_RTS_FLIP_BIT
00156 static INLINE void UART_RTS_ON(void) { GPIO_SET_HI(UART_RTS_BIT); }
00157 static INLINE void UART_RTS_OFF(void) { GPIO_SET_LO(UART_RTS_BIT); }
00158 #else
00159 static INLINE void UART_RTS_ON(void) { GPIO_SET_LO(UART_RTS_BIT); }
00160 static INLINE void UART_RTS_OFF(void) { GPIO_SET_HI(UART_RTS_BIT); }
00161 #endif
00162 
00163 #elif defined(UART_USES_NPL)
00164 
00165 #undef UART_RTS_ON
00166 #undef UART_RTS_OFF
00167 #if US_ID == US1_ID
00168 #define UART_RTS_ON()   if (inr(NPL_RSCR) & NPL_RSUS1P) sbi(NPL_RSCR, NPL_RSRTS_BIT)
00169 #define UART_RTS_OFF()  if (inr(NPL_RSCR) & NPL_RSUS1P) cbi(NPL_RSCR, NPL_RSRTS_BIT)
00170 #else
00171 #define UART_RTS_ON()   if ((inr(NPL_RSCR) & NPL_RSUS1P) == 0) sbi(NPL_RSCR, NPL_RSRTS_BIT)
00172 #define UART_RTS_OFF()  if ((inr(NPL_RSCR) & NPL_RSUS1P) == 0) cbi(NPL_RSCR, NPL_RSRTS_BIT)
00173 #endif
00174 #endif
00175 
00176 /*
00177 ** GPIO monitored CTS pin.
00178 */
00179 #if defined(UART_CTS_BIT) && defined(UART_CTS_PIO_ID)
00180 
00181 #undef UART_CTS_IS_ON
00182 #undef UART_CTS_PIN_ENABLE
00183 #undef GPIO_ID
00184 #define GPIO_ID UART_CTS_PIO_ID
00185 #include <cfg/arch/porttran.h>
00186 #ifdef UART_CTS_FLIP_BIT
00187 static INLINE int UART_CTS_IS_ON(void) { return GPIO_GET(UART_CTS_BIT); }
00188 #else
00189 static INLINE int UART_CTS_IS_ON(void) { return !GPIO_GET(UART_CTS_BIT); }
00190 #endif
00191 static INLINE void UART_CTS_PIN_ENABLE(void) { \
00192     GPIO_ENABLE(UART_CTS_BIT); \
00193     GPIO_INPUT(UART_CTS_BIT); \
00194     GPIO_PULLUP_ON(UART_CTS_BIT); \
00195 }
00196 
00197 #elif defined(UART_USES_NPL)
00198 
00199 #undef UART_CTS_IS_ON
00200 static INLINE int UART_CTS_IS_ON(void) {
00201     outw(NPL_SCR, NPL_RSCTS);
00202     return bit_is_set(NPL_SLR, NPL_RSCTS_BIT);
00203 }
00204 
00205 #endif
00206 
00207 /*
00208 ** Determine if we use built-in hardware handshake.
00209 */
00210 #if !defined(USE_BUILT_IN_HARDWARE_HANDSHAKE)
00211 #if defined(UART_HARDWARE_HANDSHAKE) && \
00212     defined(US_MODE_HWHANDSHAKE) && \
00213     !defined(UART_RTS_BIT) && \
00214     !defined(UART_CTS_BIT) && \
00215     !defined(UART_USES_NPL)
00216 #define USE_BUILT_IN_HARDWARE_HANDSHAKE 1
00217 #else
00218 #define USE_BUILT_IN_HARDWARE_HANDSHAKE 0
00219 #endif
00220 #endif
00221 
00222 /*
00223 ** Determine if we use built-in half duplex mode.
00224 */
00225 #if !defined(USE_BUILT_IN_HALF_DUPLEX)
00226 #if defined(UART_HARDWARE_HANDSHAKE) && !defined(UART_HDX_BIT) && !defined(UART_USES_NPL)
00227 #define USE_BUILT_IN_HALF_DUPLEX    1
00228 #else
00229 #define USE_BUILT_IN_HALF_DUPLEX    0
00230 #endif
00231 #endif
00232 
00233 /* Some function renaming for IRQ handling on uarts
00234  * that do not have a separate IRQ instance but a
00235  * merged one with others like DBU on SYS-IRQ or
00236  * external uarts on GPIO-IRQs
00237  */
00238 #if (US_ID==SYSC_ID)
00239 #define NutUartIrqRegister  NutRegisterSysIrqHandler
00240 #define NutUartIrqEnable    NutSysIrqEnable
00241 #define NutUartIrqDisable   NutSysIrqDisable
00242 #else
00243 #define NutUartIrqRegister  NutRegisterIrqHandler
00244 #define NutUartIrqEnable    NutIrqEnable
00245 #define NutUartIrqDisable   NutIrqDisable
00246 #endif
00247 
00252 
00253 /* \brief ASCII code for software flow control, starts transmitter. */
00254 #define ASCII_XON   0x11
00255 /* \brief ASCII code for software flow control, stops transmitter. */
00256 #define ASCII_XOFF  0x13
00257 
00258 /* \brief XON transmit pending flag. */
00259 #define XON_PENDING     0x10
00260 /* \brief XOFF transmit pending flag. */
00261 #define XOFF_PENDING    0x20
00262 /* \brief XOFF sent flag. */
00263 #define XOFF_SENT       0x40
00264 /* \brief XOFF received flag. */
00265 #define XOFF_RCVD       0x80
00266 
00267 
00271 static unsigned int rx_errors;
00272 
00276 static uint_fast8_t flow_control;
00277 
00281 static uint_fast8_t tx_aframe;
00282 
00288 static uint_fast8_t hdx_control;
00289 
00296 static uint_fast8_t rts_control;
00297 
00304 static uint_fast8_t cts_sense;
00305 
00306 #if defined(UART_CTS_BIT) || defined(UART_USES_NPL)
00307 
00317 static void At91UsartCts(void *arg)
00318 {
00319     /* Disable CTS sense interrupt. */
00320 #if defined(UART_USES_NPL)
00321     NplIrqDisable(&sig_RSCTS);
00322     /* Enable transmit interrupt. */
00323     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00324 #else
00325     if (UART_CTS_IS_ON()) {
00326         GpioIrqDisable(&UART_CTS_SIGNAL, UART_CTS_BIT);
00327         /* Enable transmit interrupt. */
00328         outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00329     }
00330 #endif
00331 }
00332 #endif
00333 
00334 #if USE_BUILT_IN_HALF_DUPLEX == 0
00335 /*
00336  * \brief USARTn transmitter empty interrupt handler.
00337  *
00338  * Used with half duplex communication to switch from tranmit to receive
00339  * mode after the last character has been transmitted.
00340  *
00341  * \param arg Pointer to the transmitter ring buffer.
00342  */
00343 static void At91UsartTxEmpty(RINGBUF *rbf)
00344 {
00345     /*
00346      * Check if half duplex mode has been enabled and if all characters
00347      * had been sent out.
00348      */
00349     if (hdx_control && (rbf->rbf_cnt == 0)) {
00350         /*
00351          * Switch to receiver mode:
00352          * Enable USART receive, disable transmit.
00353          * Disable TX-Empty IRQ
00354          */
00355         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXDIS);
00356 #if defined(UART_HDX_BIT) || defined(UART_USES_NPL)
00357         UART_HDX_RX();
00358 #endif
00359     }
00360 }
00361 #endif
00362 
00363 /*
00364  * \brief USARTn transmitter ready interrupt handler.
00365  *
00366  * \param rbf Pointer to the transmitter ring buffer.
00367  */
00368 static void At91UsartTxReady(RINGBUF *rbf)
00369 {
00370     register uint8_t *cp = rbf->rbf_tail;
00371 
00372     /*
00373      * Process pending software flow controls first.
00374      */
00375     if (flow_control & (XON_PENDING | XOFF_PENDING)) {
00376         if (flow_control & XON_PENDING) {
00377             outr(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00378             flow_control |= XOFF_SENT;
00379         } else {
00380             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
00381             flow_control &= ~XOFF_SENT;
00382         }
00383         flow_control &= ~(XON_PENDING | XOFF_PENDING);
00384         return;
00385     }
00386 
00387     if (flow_control & XOFF_RCVD) {
00388         /*
00389          * If XOFF has been received, we disable the transmit interrupts
00390          * and return without sending anything.
00391          */
00392         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00393         return;
00394     }
00395 
00396     /*
00397      * Check if we have more bytes to transmit.
00398      */
00399     if (rbf->rbf_cnt) {
00400 #if defined(UART_CTS_BIT) || defined(UART_USES_NPL)
00401         /*
00402          * If CTS has been disabled, we disable the transmit interrupts,
00403          * enable CTS interrupts and return without sending anything.
00404          */
00405         if (cts_sense && !UART_CTS_IS_ON()) {
00406             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00407 #if defined(UART_CTS_BIT)
00408             GpioIrqEnable(&UART_CTS_SIGNAL, UART_CTS_BIT);
00409 #else
00410             NplIrqEnable(&sig_RSCTS);
00411 #endif
00412             return;
00413         }
00414 #endif
00415 
00416         /*
00417          * Send address in multidrop mode.
00418          */
00419         if (tx_aframe) {
00420             outr(USARTn_BASE + US_CR_OFF, US_SENDA);
00421         }
00422 
00423         /* Start transmission of the next character. */
00424         outr(USARTn_BASE + US_THR_OFF, *cp);
00425         /* Decrement the number of available bytes in the buffer. */
00426         rbf->rbf_cnt--;
00427         /* Wrap around the buffer pointer if we reached its end. */
00428         if (++cp == rbf->rbf_last) {
00429             cp = rbf->rbf_start;
00430         }
00431         rbf->rbf_tail = cp;
00432 
00433 #if USE_BUILT_IN_HALF_DUPLEX == 0
00434         /*
00435          * If software half duplex enabled, we need TX-Empty IRQ for
00436          * detection if last bit of last byte transmission is finished.
00437          */
00438         if( hdx_control && rbf->rbf_cnt == 0) {
00439             outr(USARTn_BASE + US_IER_OFF, US_TXEMPTY);
00440         }
00441 #endif
00442 
00443         /* Send an event if we reached the low watermark. */
00444         if (rbf->rbf_cnt == rbf->rbf_lwm) {
00445             NutEventPostFromIrq(&rbf->rbf_que);
00446         }
00447     }
00448 
00449     /*
00450      * Nothing left to transmit, disable interrupt.
00451      */
00452     else {
00453         /* Disable transmit interrupts. */
00454         outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00455         /* Send an event to inform the upper level. */
00456         NutEventPostFromIrq(&rbf->rbf_que);
00457     }
00458 }
00459 
00460 
00461 /*
00462  * \brief USARTn receiver ready interrupt handler.
00463  *
00464  *
00465  * \param rbf Pointer to the receiver ring buffer.
00466  */
00467 
00468 static void At91UsartRxReady(RINGBUF *rbf)
00469 {
00470     register size_t cnt;
00471     register uint8_t ch;
00472 
00473     /*
00474      * We read the received character as early as possible to avoid overflows
00475      * caused by interrupt latency.
00476      */
00477     ch = inb(USARTn_BASE + US_RHR_OFF);
00478 
00479     /* Collect receiver errors. */
00480     rx_errors |= inr(USARTn_BASE + US_CSR_OFF) & (US_OVRE | US_FRAME | US_PARE);
00481 
00482     /*
00483      * Handle software handshake. We have to do this before checking the
00484      * buffer, because flow control must work in write-only mode, where
00485      * there is no receive buffer.
00486      */
00487     if (flow_control) {
00488         /* XOFF character disables transmit interrupts. */
00489         if (ch == ASCII_XOFF) {
00490             outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
00491             flow_control |= XOFF_RCVD;
00492             return;
00493         }
00494         /* XON enables transmit interrupts. */
00495         else if (ch == ASCII_XON) {
00496             outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
00497             flow_control &= ~XOFF_RCVD;
00498             return;
00499         }
00500     }
00501 
00502     /*
00503      * Check buffer overflow.
00504      */
00505     cnt = rbf->rbf_cnt;
00506     if (cnt >= rbf->rbf_siz) {
00507         rx_errors |= US_OVRE;
00508         return;
00509     }
00510 
00511     /* Wake up waiting threads if this is the first byte in the buffer. */
00512     if (cnt++ == 0){
00513         NutEventPostFromIrq(&rbf->rbf_que);
00514     }
00515 
00516     /*
00517      * Check the high watermark for software handshake. If the number of
00518      * buffered bytes is equal or above this mark, then send XOFF.
00519      */
00520     else if (flow_control) {
00521         if(cnt >= rbf->rbf_hwm) {
00522             if((flow_control & XOFF_SENT) == 0) {
00523                 if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00524                     outb(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
00525                     flow_control |= XOFF_SENT;
00526                     flow_control &= ~XOFF_PENDING;
00527                 } else {
00528                     flow_control |= XOFF_PENDING;
00529                 }
00530             }
00531         }
00532     }
00533 
00534 #if defined(UART_RTS_BIT) || defined(UART_USES_NPL)
00535     /*
00536      * Check the high watermark for GPIO hardware handshake. If the
00537      * number of buffered bytes is equal or above this mark, then
00538      * disable RTS.
00539      */
00540     else if (rts_control && cnt >= rbf->rbf_hwm) {
00541         UART_RTS_OFF();
00542     }
00543 #endif
00544 
00545     /*
00546      * Store the character and increment and the ring buffer pointer.
00547      */
00548     *rbf->rbf_head++ = ch;
00549     if (rbf->rbf_head == rbf->rbf_last) {
00550         rbf->rbf_head = rbf->rbf_start;
00551     }
00552 
00553     /* Update the ring buffer counter. */
00554     rbf->rbf_cnt = cnt;
00555 }
00556 
00562 static void At91UsartInterrupt(void *arg)
00563 {
00564     USARTDCB *dcb = (USARTDCB *)arg;
00565     unsigned int csr = inr(USARTn_BASE + US_CSR_OFF);
00566 
00567     if (csr & US_RXRDY) {
00568         At91UsartRxReady(&dcb->dcb_rx_rbf);
00569     }
00570     if (csr & US_TXRDY) {
00571         At91UsartTxReady(&dcb->dcb_tx_rbf);
00572     }
00573 
00574 #if USE_BUILT_IN_HALF_DUPLEX == 0
00575     if (csr & US_TXEMPTY) {
00576         At91UsartTxEmpty(&dcb->dcb_tx_rbf);
00577     }
00578 #endif
00579 }
00580 
00587 static void At91UsartEnable(void)
00588 {
00589     /* Enable UART receiver and transmitter. */
00590     outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
00591     /* Globally enable UART interrupts. */
00592     NutUartIrqEnable(&SIG_UART);
00593 }
00594 
00617 static void At91UsartDisable(void)
00618 {
00619     /* Globally disable UART interrupts. */
00620     NutUartIrqDisable(&SIG_UART);
00621     /* Wait until all bits had been shifted out. */
00622     if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
00623         while((inr(USARTn_BASE + US_CSR_OFF) & US_TXEMPTY) == 0);
00624     }
00625     /* Disable USART transmit and receive. */
00626     outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXDIS);
00627 }
00628 
00637 static uint32_t At91UsartGetSpeed(void)
00638 {
00639     unsigned int cs;
00640     uint32_t clk;
00641 
00642     clk = NutClockGet(NUT_HWCLK_PERIPHERAL);
00643     cs = inr(USARTn_BASE + US_MR_OFF) & US_CLKS;
00644     if (cs == US_CLKS_MCK8) {
00645         clk /= 8;
00646     }
00647     else if (cs != US_CLKS_MCK) {
00648         clk = 0;
00649     }
00650     return clk / (16UL * (inr(USARTn_BASE + US_BRGR_OFF) & 0xFFFF));
00651 }
00652 
00663 static int At91UsartSetSpeed(uint32_t rate)
00664 {
00665     At91UsartDisable();
00666 #if !(USARTn_BASE == DBGU_BASE)
00667     outr(USARTn_BASE + US_BRGR_OFF, (NutClockGet(NUT_HWCLK_PERIPHERAL) / (8 * (rate)) + 1) / 2);
00668 #else
00669     #if defined(AT91_PLL_MAINCK)
00670         outr(DBGU_BRGR, (At91GetMasterClock() / (8 * rate) + 1) / 2);
00671     #else
00672         outr(DBGU_BRGR, (NutGetCpuClock() / (8 * rate) + 1) / 2);
00673     #endif
00674 #endif
00675     At91UsartEnable();
00676     return 0;
00677 }
00678 
00687 static uint8_t At91UsartGetDataBits(void)
00688 {
00689 #if !(USARTn_BASE == DBGU_BASE)
00690     unsigned int val = inr(USARTn_BASE + US_MR_OFF);
00691 
00692     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00693         val = 9;
00694     }
00695     else {
00696         val &= US_CHRL;
00697         if (val == US_CHRL_5) {
00698             val = 5;
00699         }
00700         else if (val == US_CHRL_6) {
00701             val = 6;
00702         }
00703         else if (val == US_CHRL_7) {
00704             val = 7;
00705         }
00706         else {
00707             val = 8;
00708         }
00709     }
00710     return (uint8_t)val;
00711 #else
00712     /* Not supported by DBGU, always 8 bits */
00713     return 8;
00714 #endif
00715 }
00716 
00725 static int At91UsartSetDataBits(uint8_t bits)
00726 {
00727 #if !(USARTn_BASE == DBGU_BASE)
00728     unsigned int val = inr(USARTn_BASE + US_MR_OFF);
00729 
00730     if (bits == 9) {
00731         val &= ~US_PAR;
00732         val |= US_PAR_MULTIDROP;
00733     }
00734     else {
00735         val &= ~US_CHRL;
00736         if (bits == 5) {
00737             val |= US_CHRL_5;
00738         }
00739         else if (bits == 6) {
00740             val |= US_CHRL_6;
00741         }
00742         else if (bits == 7) {
00743             val |= US_CHRL_7;
00744         }
00745         else if (bits == 8) {
00746             val |= US_CHRL_8;
00747         }
00748     }
00749 
00750     At91UsartDisable();
00751     outr(USARTn_BASE + US_MR_OFF, val);
00752     At91UsartEnable();
00753 
00754     /*
00755      * Verify the result.
00756      */
00757     if (At91UsartGetDataBits() != bits) {
00758         return -1;
00759     }
00760     return 0;
00761 #else
00762     /* Not supported by DBGU, always 8 bits */
00763     return -1;
00764 #endif
00765 }
00766 
00775 static uint8_t At91UsartGetParity(void)
00776 {
00777     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & US_PAR;
00778 
00779     if ((val & US_PAR) == US_PAR_MULTIDROP) {
00780         val = 9;
00781     }
00782     else {
00783         if (val == US_PAR_ODD) {
00784             val = 1;
00785         }
00786         else if (val == US_PAR_EVEN) {
00787             val = 2;
00788         }
00789         else {
00790             val = 0;
00791         }
00792     }
00793     return (uint8_t)val;
00794 }
00795 
00806 static int At91UsartSetParity(uint8_t mode)
00807 {
00808     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & ~US_PAR;
00809 
00810     switch (mode) {
00811     case 0:
00812         val |= US_PAR_NO;
00813         break;
00814     case 1:
00815         val |= US_PAR_ODD;
00816         break;
00817     case 2:
00818         val |= US_PAR_EVEN;
00819         break;
00820     }
00821     At91UsartDisable();
00822     outr(USARTn_BASE + US_MR_OFF, val);
00823     At91UsartEnable();
00824 
00825     /*
00826      * Verify the result.
00827      */
00828     if (At91UsartGetParity() != mode) {
00829         return -1;
00830     }
00831     return 0;
00832 }
00833 
00842 static uint8_t At91UsartGetStopBits(void)
00843 {
00844 #if !(USARTn_BASE == DBGU_BASE)
00845     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & US_NBSTOP;
00846     if (val == US_NBSTOP_1) {
00847         val = 1;
00848     }
00849     else if (val == US_NBSTOP_2) {
00850         val = 2;
00851     }
00852     else {
00853         val = 3;
00854     }
00855     return (uint8_t)val;
00856 #else
00857     /* Not supported by DBGU, always 1 */
00858     return 1;
00859 #endif
00860 }
00861 
00870 static int At91UsartSetStopBits(uint8_t bits)
00871 {
00872 #if !(USARTn_BASE == DBGU_BASE)
00873     unsigned int val = inr(USARTn_BASE + US_MR_OFF) & ~US_NBSTOP;
00874 
00875     switch(bits) {
00876     case 1:
00877         val |= US_NBSTOP_1;
00878         break;
00879     case 2:
00880         val |= US_NBSTOP_2;
00881         break;
00882     case 3:
00883         val |= US_NBSTOP_1_5;
00884         break;
00885     }
00886     At91UsartDisable();
00887     outr(USARTn_BASE + US_MR_OFF, val);
00888     At91UsartEnable();
00889 
00890     /*
00891      * Verify the result.
00892      */
00893     if (At91UsartGetStopBits() != bits) {
00894         return -1;
00895     }
00896 #endif
00897     return 0;
00898 }
00899 
00905 static uint32_t At91UsartGetStatus(void)
00906 {
00907     uint32_t rc = 0;
00908 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
00909     uint32_t csr = inr(USARTn_BASE + US_CSR_OFF);
00910 #endif
00911 
00912     /*
00913      * Set receiver error flags.
00914      */
00915     if ((rx_errors & US_FRAME) != 0) {
00916         rc |= UART_FRAMINGERROR;
00917     }
00918     if ((rx_errors & US_OVRE) != 0) {
00919         rc |= UART_OVERRUNERROR;
00920     }
00921     if ((rx_errors & US_PARE) != 0) {
00922         rc |= UART_PARITYERROR;
00923     }
00924 
00925     /*
00926      * Determine software handshake status. The flow control status may
00927      * change during interrupt, but this doesn't really hurt us.
00928      */
00929     if (flow_control) {
00930         if (flow_control & XOFF_SENT) {
00931             rc |= UART_RXDISABLED;
00932         }
00933         if (flow_control & XOFF_RCVD) {
00934             rc |= UART_TXDISABLED;
00935         }
00936     }
00937 
00938     /*
00939      * Determine hardware handshake control status.
00940      */
00941 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
00942     /* How to find out? */
00943 #elif defined(UART_RTS_BIT)
00944     /* No definition of the status register? */
00945 #elif defined(UART_USES_NPL)
00946     if (bit_is_set(NPL_RSCR, NPL_RSRTS_BIT)) {
00947         rc |= UART_RTSDISABLED;
00948         if (rts_control) {
00949             rc |= UART_RXDISABLED;
00950         }
00951     } else {
00952         rc |= UART_RTSENABLED;
00953     }
00954 #endif
00955 
00956     /*
00957      * Determine hardware handshake sense status.
00958      */
00959 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
00960     if (csr & US_CTS) {
00961         rc |= UART_CTSDISABLED;
00962         if (cts_sense) {
00963             rc |= UART_RXDISABLED;
00964         }
00965     } else {
00966         rc |= UART_CTSENABLED;
00967     }
00968 #else
00969     if (UART_CTS_IS_ON()) {
00970         rc |= UART_CTSENABLED;
00971     } else {
00972         rc |= UART_CTSDISABLED;
00973         if (cts_sense) {
00974             rc |= UART_RXDISABLED;
00975         }
00976     }
00977 #endif
00978 
00979     /*
00980      * Determine hardware modem sense status.
00981      */
00982 #if 0
00983     /* I'm confused. Awful flag mismatch? Why do we have uart.h and usart.h? */
00984     if (csr & US_RI) {
00985         rc |= UART_RIDISABLED;
00986     } else {
00987         rc |= UART_RIENABLED;
00988     }
00989     if (csr & US_DSR) {
00990         rc |= UART_DSRDISABLED;
00991     } else {
00992         rc |= UART_DSRENABLED;
00993     }
00994     if (csr & US_DCD) {
00995         rc |= UART_DCDDISABLED;
00996     } else {
00997         rc |= UART_DCDENABLED;
00998     }
00999 #endif
01000 
01001     /*
01002      * If transmitter and receiver haven't been detected disabled by any
01003      * of the checks above, then they are probably enabled.
01004      */
01005     if ((rc & UART_RXDISABLED) == 0) {
01006         rc |= UART_RXENABLED;
01007     }
01008     if ((rc & UART_TXDISABLED) == 0) {
01009         rc |= UART_TXENABLED;
01010     }
01011 
01012     /*
01013      * Process multidrop setting.
01014      */
01015     if (tx_aframe) {
01016         rc |= UART_TXADDRFRAME;
01017     } else {
01018         rc |= UART_TXNORMFRAME;
01019     }
01020     return rc;
01021 }
01022 
01030 static int At91UsartSetStatus(uint32_t flags)
01031 {
01032     /*
01033      * Process software handshake control.
01034      */
01035     if (flow_control) {
01036 
01037         /* Access to the flow control status must be atomic. */
01038         NutUartIrqDisable(&SIG_UART);
01039 
01040         /*
01041          * Enabling or disabling the receiver means to behave like
01042          * having sent a XON or XOFF character resp.
01043          */
01044         if (flags & UART_RXENABLED) {
01045             flow_control &= ~XOFF_SENT;
01046         } else if (flags & UART_RXDISABLED) {
01047             flow_control |= XOFF_SENT;
01048         }
01049 
01050         /*
01051          * Enabling or disabling the transmitter means to behave like
01052          * having received a XON or XOFF character resp.
01053          */
01054         if (flags & UART_TXENABLED) {
01055             flow_control &= ~XOFF_RCVD;
01056         } else if (flags & UART_TXDISABLED) {
01057             flow_control |= XOFF_RCVD;
01058         }
01059         NutUartIrqEnable(&SIG_UART);
01060     }
01061 
01062     /*
01063      * Process hardware handshake control.
01064      */
01065 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01066     /* Built-in hardware. */
01067     if (rts_control) {
01068         if (flags & UART_RXDISABLED) {
01069             outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
01070         }
01071         if (flags & UART_RXENABLED) {
01072             outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
01073         }
01074     }
01075     if (flags & UART_RTSDISABLED) {
01076         outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
01077     }
01078     if (flags & UART_RTSENABLED) {
01079         outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
01080     }
01081 #else
01082     /* Manually controlled via GPIO. */
01083     if (rts_control) {
01084         if (flags & UART_RXDISABLED) {
01085             UART_RTS_OFF();
01086         }
01087         if (flags & UART_RXENABLED) {
01088             UART_RTS_ON();
01089         }
01090     }
01091     if (flags & UART_RTSDISABLED) {
01092         UART_RTS_OFF();
01093     }
01094     if (flags & UART_RTSENABLED) {
01095         UART_RTS_ON();
01096     }
01097 #endif
01098 
01099 
01100     /*
01101      * Process hardware modem control.
01102      */
01103 #if USE_BUILT_IN_MODEM_CONTROL
01104     /* Built-in hardware. */
01105     if (flags & UART_DTRDISABLED) {
01106         outr(USARTn_BASE + US_CR_OFF, US_DTRDIS);
01107     }
01108     if (flags & UART_DTRENABLED) {
01109         outr(USARTn_BASE + US_CR_OFF, US_DTREN);
01110     }
01111 #endif
01112 
01113     /*
01114      * Process multidrop setting.
01115      */
01116     if (flags & UART_TXADDRFRAME) {
01117         tx_aframe = 1;
01118     }
01119     if (flags & UART_TXNORMFRAME) {
01120         tx_aframe = 0;
01121     }
01122 
01123     /*
01124      * Clear UART receive errors.
01125      */
01126     if (flags & UART_ERRORS) {
01127         outr(USARTn_BASE + US_CR_OFF, US_RSTSTA);
01128     }
01129 
01130     /*
01131      * Verify the result.
01132      */
01133     if ((At91UsartGetStatus() & ~UART_ERRORS) != flags) {
01134         return -1;
01135     }
01136     return 0;
01137 }
01138 
01150 static uint8_t At91UsartGetClockMode(void)
01151 {
01152     return 0;
01153 }
01154 
01168 static int At91UsartSetClockMode(uint8_t mode)
01169 {
01170     return -1;
01171 }
01172 
01181 static uint32_t At91UsartGetFlowControl(void)
01182 {
01183     uint32_t rc = 0;
01184 
01185     if (flow_control) {
01186         rc |= USART_MF_XONXOFF;
01187     } else {
01188         rc &= ~USART_MF_XONXOFF;
01189     }
01190 
01191 #if defined(UART_RTS_BIT) || defined(UART_USES_NPL) || defined(UART_HARDWARE_HANDSHAKE)
01192     if (rts_control) {
01193         rc |= USART_MF_RTSCONTROL;
01194     } else {
01195         rc &= ~USART_MF_RTSCONTROL;
01196     }
01197 #endif
01198 
01199 #if defined(UART_CTS_BIT) || defined(UART_USES_NPL) || defined(UART_HARDWARE_HANDSHAKE)
01200     if (cts_sense) {
01201         rc |= USART_MF_CTSSENSE;
01202     } else {
01203         rc &= ~USART_MF_CTSSENSE;
01204     }
01205 #endif
01206 
01207     if (hdx_control) {
01208         rc |= USART_MF_HALFDUPLEX;
01209     } else {
01210         rc &= ~USART_MF_HALFDUPLEX;
01211     }
01212     return rc;
01213 }
01214 
01225 static int At91UsartSetFlowControl(uint32_t flags)
01226 {
01227 #if USE_BUILT_IN_HARDWARE_HANDSHAKE || USE_BUILT_IN_HALF_DUPLEX
01228     uint32_t mr = inr(USARTn_BASE + US_MR_OFF) & ~US_MODE;
01229 #endif
01230 
01231     /*
01232      * Set software handshake mode.
01233      */
01234     NutUartIrqDisable(&SIG_UART);
01235     if (flags & USART_MF_XONXOFF) {
01236         if(flow_control == 0) {
01237             flow_control = 1 | XOFF_SENT;  /* force XON to be sent on next read */
01238         }
01239     } else {
01240         flow_control = 0;
01241     }
01242     NutUartIrqEnable(&SIG_UART);
01243 
01244     /*
01245      * Set RTS control mode.
01246      */
01247     UART_RTS_PIN_ENABLE();
01248     UART_RTS_ON();
01249     if (flags & USART_MF_RTSCONTROL) {
01250         rts_control = 1;
01251 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01252         outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_HWHANDSHAKE);
01253         cts_sense = 1;
01254 #endif
01255     } else if (rts_control) {
01256         rts_control = 0;
01257 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01258         outr(USARTn_BASE + US_MR_OFF, mr);
01259         cts_sense = 0;
01260 #endif
01261     }
01262 
01263     /*
01264      * Set CTS sense mode.
01265      */
01266     if (flags & USART_MF_CTSSENSE) {
01267         cts_sense = 1;
01268         UART_CTS_PIN_ENABLE();
01269 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01270         rts_control = 1;
01271         outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_HWHANDSHAKE);
01272 #endif
01273     } else if (cts_sense) {
01274         cts_sense = 0;
01275 #if USE_BUILT_IN_HARDWARE_HANDSHAKE
01276         rts_control = 0;
01277         outr(USARTn_BASE + US_MR_OFF, mr);
01278 #endif
01279     }
01280 
01281     /*
01282      * Set half duplex mode.
01283      */
01284     if (flags & USART_MF_HALFDUPLEX) {
01285         /* Mark half duplex mode enabled. */
01286         hdx_control = 1;
01287         /* Enable half duplex pin. */
01288         UART_HDX_PIN_ENABLE();
01289         UART_HDX_RX();
01290 #if USE_BUILT_IN_HALF_DUPLEX
01291         /* Enable built-in RS-485 mode. */
01292         outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_RS485);
01293 #else
01294         /* Enable USART receive, disable transmit. */
01295         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXDIS);
01296         /* Enable transmit complete interrupt. */
01297         outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
01298 #endif
01299     }
01300     else if (hdx_control) {
01301         hdx_control = 0;
01302 #if USE_BUILT_IN_HALF_DUPLEX
01303         /* Disable built-in RS-485 mode. */
01304         outr(USARTn_BASE + US_MR_OFF, inr(USARTn_BASE + US_MR_OFF) & ~US_MODE);
01305 #else
01306         /* Enable USART receive and transmit. */
01307         outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
01308         /* Disable transmit complete interrupt. */
01309         outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
01310 #endif
01311     }
01312     /* No need to call At91UsartGetFlowControl. The result is obvious,
01313     ** because we do not exclude unsupported modes yet. */
01314 
01315     return 0;
01316 }
01317 
01325 static void At91UsartTxStart(void)
01326 {
01327 #if USE_BUILT_IN_HALF_DUPLEX == 0
01328     if (hdx_control) {
01329 #if defined(UART_HDX_BIT) || defined(UART_USES_NPL)
01330         UART_HDX_TX();
01331 #endif
01332         /* Disable USART receive, enable transmit. */
01333         outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXEN);
01334     }
01335 #endif
01336     /* Enable transmit interrupts. */
01337     outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
01338 }
01339 
01348 static void At91UsartRxStart(void)
01349 {
01350     /*
01351      * Do any required software flow control.
01352      */
01353     if (flow_control && (flow_control & XOFF_SENT) != 0) {
01354         NutUartIrqDisable(&SIG_UART);
01355         if ((inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY)) {
01356             outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
01357             flow_control &= ~XON_PENDING;
01358         } else {
01359             flow_control |= XON_PENDING;
01360         }
01361         flow_control &= ~(XOFF_SENT | XOFF_PENDING);
01362         NutUartIrqEnable(&SIG_UART);
01363     }
01364 
01365     /* Enable RTS. */
01366     UART_RTS_ON();
01367     /* Enable receive interrupts. */
01368     outr(USARTn_BASE + US_IER_OFF, US_RXRDY);
01369 }
01370 
01371 /*
01372  * \brief Initialize the USART hardware driver.
01373  *
01374  * This function is called during device registration by the upper level
01375  * USART driver through the USARTDCB jump table.
01376  *
01377  * \return 0 on success, -1 otherwise.
01378  */
01379 static int At91UsartInit(void)
01380 {
01381     /*
01382      * Register receive and transmit interrupts.
01383      */
01384     if (NutUartIrqRegister(&SIG_UART, At91UsartInterrupt, &dcb_usart)) {
01385         return -1;
01386     }
01387 
01388     /*
01389      * Register CTS sense interrupts.
01390      */
01391 #if defined(UART_CTS_BIT)
01392 
01393     if (GpioRegisterIrqHandler(&sig_GPIO1, UART_CTS_BIT, At91UsartCts, NULL)) {
01394         return -1;
01395     }
01396 #if defined(PS_PCER)
01397     outr(PS_PCER, _BV(UART_CTS_PIO_ID));
01398 #elif defined(PMC_PCER)
01399     outr(PMC_PCER, _BV(UART_CTS_PIO_ID));
01400 #endif
01401 
01402 #elif defined(UART_USES_NPL)
01403 
01404     if (NplRegisterIrqHandler(&sig_RSCTS, At91UsartCts, NULL)) {
01405         return -1;
01406     }
01407 
01408 #endif
01409 
01410     /* Enable UART clock. */
01411 #if defined(US_ID)
01412 #if defined(PS_PCER)
01413     outr(PS_PCER, _BV(US_ID));
01414 #elif defined(PMC_PCER)
01415     outr(PMC_PCER, _BV(US_ID));
01416 #endif
01417 #endif
01418 
01419     /* Disable GPIO on UART tx/rx pins. */
01420     UART_RXTX_PINS_ENABLE();
01421 
01422     /* Reset UART. */
01423     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01424     /* Disable all UART interrupts. */
01425     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01426 
01427 #if defined(US_RCR_OFF) && defined(US_TCR_OFF)
01428     /* Clear UART PDC counter registers. */
01429     outr(USARTn_BASE + US_RCR_OFF, 0);
01430     outr(USARTn_BASE + US_TCR_OFF, 0);
01431 #endif
01432 
01433     /* Set UART baud rate generator register. */
01434     At91UsartSetSpeed( UART_INIT_BAUDRATE);
01435 
01436     /* Set UART mode to 8 data bits, no parity and 1 stop bit. */
01437     outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1);
01438 
01439     return 0;
01440 }
01441 
01442 /*
01443  * \brief Deinitialize the USART hardware driver.
01444  *
01445  * This function is called during device deregistration by the upper
01446  * level USART driver through the USARTDCB jump table.
01447  *
01448  * \return 0 on success, -1 otherwise.
01449  */
01450 static int At91UsartDeinit(void)
01451 {
01452     /* Deregister receive and transmit interrupts. */
01453     NutUartIrqRegister(&SIG_UART, 0, 0);
01454 
01455     /* Reset UART. */
01456     outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
01457     /* Disable all UART interrupts. */
01458     outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
01459 
01460     /* Disable UART clock. */
01461 #if defined (US_ID)
01462 #if defined(PS_PCDR)
01463     outr(PS_PCDR, _BV(US_ID));
01464 #elif defined(PMC_PCDR)
01465     outr(PMC_PCDR, _BV(US_ID));
01466 #endif
01467 #endif
01468 
01469     /*
01470      * Disabling flow control shouldn't be required here, because it's up
01471      * to the upper level to do this on the last close or during
01472      * deregistration.
01473      */
01474     hdx_control = 0;
01475     UART_HDX_RX();
01476     cts_sense = 0;
01477     rts_control = 0;
01478 
01479     return 0;
01480 }
01481