| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485 |
- /*
- * Copyright 2001-2006 by egnite Software GmbH
- * Copyright 2009 by egnite GmbH
- *
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the copyright holders nor the names of
- * contributors may be used to endorse or promote products derived
- * from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
- * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
- * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
- * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * For additional information see http://www.ethernut.de/
- */
- /*
- * $Id: usartat91.c 5472 2013-12-06 00:16:28Z olereinhardt $
- *
- * Revision 1.01 2009/09/20 ulrichprinz
- * Added support for using DBGU as limited standard USART.
- */
- #include <cfg/clock.h>
- #ifdef UART_USES_NPL
- #include <dev/npl.h>
- #endif
- #include <sys/atom.h>
- #include <sys/event.h>
- #include <sys/timer.h>
- #include <dev/irqreg.h>
- #include <dev/usartat91.h>
- /*
- ** Initial USART settings.
- */
- #ifndef UART_INIT_BAUDRATE
- #define UART_INIT_BAUDRATE 115200
- #endif
- /*
- ** Add empty placeholders for undefined pin configurations.
- */
- #ifndef UART_RXTX_PINS_ENABLE
- #define UART_RXTX_PINS_ENABLE()
- #endif
- #ifndef UART_HDX_PIN_ENABLE
- #define UART_HDX_PIN_ENABLE()
- #endif
- #ifndef UART_HDX_RX
- #define UART_HDX_RX()
- #endif
- #ifndef UART_HDX_TX
- #define UART_HDX_TX()
- #endif
- #ifndef UART_RTS_PIN_ENABLE
- #define UART_RTS_PIN_ENABLE()
- #endif
- #ifndef UART_RTS_ON
- #define UART_RTS_ON()
- #endif
- #ifndef UART_RTS_OFF
- #define UART_RTS_OFF()
- #endif
- #ifndef UART_CTS_PIN_ENABLE
- #define UART_CTS_PIN_ENABLE()
- #endif
- #ifndef UART_CTS_IS_ON
- #define UART_CTS_IS_ON() (1)
- #endif
- #ifndef UART_MODEM_PINS_ENABLE
- #define UART_MODEM_PINS_ENABLE()
- #endif
- /*
- ** GPIO controlled half duplex pin.
- */
- #if defined(UART_HDX_BIT) && defined(UART_HDX_PIO_ID)
- #undef UART_HDX_RX
- #undef UART_HDX_TX
- #undef UART_HDX_PIN_ENABLE
- #undef GPIO_ID
- #define GPIO_ID UART_HDX_PIO_ID
- #include <cfg/arch/porttran.h>
- static INLINE void UART_HDX_PIN_ENABLE(void) {
- GPIO_ENABLE(UART_HDX_BIT);
- GPIO_OUTPUT(UART_HDX_BIT);
- }
- #ifdef UART_HDX_FLIP_BIT
- static INLINE void UART_HDX_RX(void) { GPIO_SET_HI(UART_HDX_BIT); }
- static INLINE void UART_HDX_TX(void) { GPIO_SET_LO(UART_HDX_BIT); }
- #else
- static INLINE void UART_HDX_RX(void) { GPIO_SET_LO(UART_HDX_BIT); }
- static INLINE void UART_HDX_TX(void) { GPIO_SET_HI(UART_HDX_BIT); }
- #endif
- #elif defined(UART_USES_NPL)
- #undef UART_HDX_RX
- #undef UART_HDX_TX
- #if US_ID == US1_ID
- #define UART_HDX_RX() if (inr(NPL_RSCR) & NPL_RSUS1P) sbi(NPL_RSCR, NPL_RSRTS_BIT)
- #define UART_HDX_TX() if (inr(NPL_RSCR) & NPL_RSUS1P) cbi(NPL_RSCR, NPL_RSRTS_BIT)
- #else
- #define UART_HDX_RX() if ((inr(NPL_RSCR) & NPL_RSUS1P) == 0) sbi(NPL_RSCR, NPL_RSRTS_BIT)
- #define UART_HDX_TX() if ((inr(NPL_RSCR) & NPL_RSUS1P) == 0) cbi(NPL_RSCR, NPL_RSRTS_BIT)
- #endif
- #endif /* UART_HDX_BIT */
- /*
- ** GPIO controlled RTS pin.
- */
- #if defined(UART_RTS_BIT) && defined(UART_RTS_PIO_ID)
- #undef UART_RTS_ON
- #undef UART_RTS_OFF
- #undef UART_RTS_PIN_ENABLE
- #undef GPIO_ID
- #define GPIO_ID UART_RTS_PIO_ID
- #include <cfg/arch/porttran.h>
- static INLINE void UART_RTS_PIN_ENABLE(void) { \
- GPIO_ENABLE(UART_RTS_BIT); \
- GPIO_OUTPUT(UART_RTS_BIT); \
- }
- #ifdef UART_RTS_FLIP_BIT
- static INLINE void UART_RTS_ON(void) { GPIO_SET_HI(UART_RTS_BIT); }
- static INLINE void UART_RTS_OFF(void) { GPIO_SET_LO(UART_RTS_BIT); }
- #else
- static INLINE void UART_RTS_ON(void) { GPIO_SET_LO(UART_RTS_BIT); }
- static INLINE void UART_RTS_OFF(void) { GPIO_SET_HI(UART_RTS_BIT); }
- #endif
- #elif defined(UART_USES_NPL)
- #undef UART_RTS_ON
- #undef UART_RTS_OFF
- #if US_ID == US1_ID
- #define UART_RTS_ON() if (inr(NPL_RSCR) & NPL_RSUS1P) sbi(NPL_RSCR, NPL_RSRTS_BIT)
- #define UART_RTS_OFF() if (inr(NPL_RSCR) & NPL_RSUS1P) cbi(NPL_RSCR, NPL_RSRTS_BIT)
- #else
- #define UART_RTS_ON() if ((inr(NPL_RSCR) & NPL_RSUS1P) == 0) sbi(NPL_RSCR, NPL_RSRTS_BIT)
- #define UART_RTS_OFF() if ((inr(NPL_RSCR) & NPL_RSUS1P) == 0) cbi(NPL_RSCR, NPL_RSRTS_BIT)
- #endif
- #endif
- /*
- ** GPIO monitored CTS pin.
- */
- #if defined(UART_CTS_BIT) && defined(UART_CTS_PIO_ID)
- #undef UART_CTS_IS_ON
- #undef UART_CTS_PIN_ENABLE
- #undef GPIO_ID
- #define GPIO_ID UART_CTS_PIO_ID
- #include <cfg/arch/porttran.h>
- #ifdef UART_CTS_FLIP_BIT
- static INLINE int UART_CTS_IS_ON(void) { return GPIO_GET(UART_CTS_BIT); }
- #else
- static INLINE int UART_CTS_IS_ON(void) { return !GPIO_GET(UART_CTS_BIT); }
- #endif
- static INLINE void UART_CTS_PIN_ENABLE(void) { \
- GPIO_ENABLE(UART_CTS_BIT); \
- GPIO_INPUT(UART_CTS_BIT); \
- GPIO_PULLUP_ON(UART_CTS_BIT); \
- }
- #elif defined(UART_USES_NPL)
- #undef UART_CTS_IS_ON
- static INLINE int UART_CTS_IS_ON(void) {
- outw(NPL_SCR, NPL_RSCTS);
- return bit_is_set(NPL_SLR, NPL_RSCTS_BIT);
- }
- #endif
- /*
- ** Determine if we use built-in hardware handshake.
- */
- #if !defined(USE_BUILT_IN_HARDWARE_HANDSHAKE)
- #if defined(UART_HARDWARE_HANDSHAKE) && \
- defined(US_MODE_HWHANDSHAKE) && \
- !defined(UART_RTS_BIT) && \
- !defined(UART_CTS_BIT) && \
- !defined(UART_USES_NPL)
- #define USE_BUILT_IN_HARDWARE_HANDSHAKE 1
- #else
- #define USE_BUILT_IN_HARDWARE_HANDSHAKE 0
- #endif
- #endif
- /*
- ** Determine if we use built-in half duplex mode.
- */
- #if !defined(USE_BUILT_IN_HALF_DUPLEX)
- #if defined(UART_HARDWARE_HANDSHAKE) && !defined(UART_HDX_BIT) && !defined(UART_USES_NPL)
- #define USE_BUILT_IN_HALF_DUPLEX 1
- #else
- #define USE_BUILT_IN_HALF_DUPLEX 0
- #endif
- #endif
- /* Some function renaming for IRQ handling on uarts
- * that do not have a separate IRQ instance but a
- * merged one with others like DBU on SYS-IRQ or
- * external uarts on GPIO-IRQs
- */
- #if (US_ID==SYSC_ID)
- #define NutUartIrqRegister NutRegisterSysIrqHandler
- #define NutUartIrqEnable NutSysIrqEnable
- #define NutUartIrqDisable NutSysIrqDisable
- #else
- #define NutUartIrqRegister NutRegisterIrqHandler
- #define NutUartIrqEnable NutIrqEnable
- #define NutUartIrqDisable NutIrqDisable
- #endif
- /*!
- * \addtogroup xgNutArchArmAt91Us
- */
- /*@{*/
- /* \brief ASCII code for software flow control, starts transmitter. */
- #define ASCII_XON 0x11
- /* \brief ASCII code for software flow control, stops transmitter. */
- #define ASCII_XOFF 0x13
- /* \brief XON transmit pending flag. */
- #define XON_PENDING 0x10
- /* \brief XOFF transmit pending flag. */
- #define XOFF_PENDING 0x20
- /* \brief XOFF sent flag. */
- #define XOFF_SENT 0x40
- /* \brief XOFF received flag. */
- #define XOFF_RCVD 0x80
- /*!
- * \brief Receiver error flags.
- */
- static unsigned int rx_errors;
- /*!
- * \brief Enables software flow control if not equal zero.
- */
- static uint_fast8_t flow_control;
- /*!
- * \brief Transmit address frame, if not zero.
- */
- static uint_fast8_t tx_aframe;
- /*!
- * \brief Half duplex control flag.
- *
- * Set to 1 if half duplex is enabled. Contains zero otherwise.
- */
- static uint_fast8_t hdx_control;
- /*!
- * \brief Enables RTS control if not equal zero.
- *
- * This variable exists only if the hardware configuration defines a
- * port bit to control the RTS signal.
- */
- static uint_fast8_t rts_control;
- /*!
- * \brief Enables CTS sense if not equal zero.
- *
- * This variable exists only if the hardware configuration defines a
- * port bit to sense the CTS signal.
- */
- static uint_fast8_t cts_sense;
- #if defined(UART_CTS_BIT) || defined(UART_USES_NPL)
- /*!
- * \brief USARTn CTS sense interrupt handler.
- *
- * This interrupt routine is called when the CTS line level is low.
- * Typical line drivers negate the signal, thus driving our port
- * low when CTS is active.
- *
- * This routine exists only if the hardware configuration defines a
- * port bit to sense the CTS signal.
- */
- static void At91UsartCts(void *arg)
- {
- /* Disable CTS sense interrupt. */
- #if defined(UART_USES_NPL)
- NplIrqDisable(&sig_RSCTS);
- /* Enable transmit interrupt. */
- outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
- #else
- if (UART_CTS_IS_ON()) {
- GpioIrqDisable(&UART_CTS_SIGNAL, UART_CTS_BIT);
- /* Enable transmit interrupt. */
- outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
- }
- #endif
- }
- #endif
- #if USE_BUILT_IN_HALF_DUPLEX == 0
- /*
- * \brief USARTn transmitter empty interrupt handler.
- *
- * Used with half duplex communication to switch from tranmit to receive
- * mode after the last character has been transmitted.
- *
- * \param arg Pointer to the transmitter ring buffer.
- */
- static void At91UsartTxEmpty(RINGBUF *rbf)
- {
- /*
- * Check if half duplex mode has been enabled and if all characters
- * had been sent out.
- */
- if (hdx_control && (rbf->rbf_cnt == 0)) {
- /*
- * Switch to receiver mode:
- * Enable USART receive, disable transmit.
- * Disable TX-Empty IRQ
- */
- outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXDIS);
- #if defined(UART_HDX_BIT) || defined(UART_USES_NPL)
- UART_HDX_RX();
- #endif
- }
- }
- #endif
- /*
- * \brief USARTn transmitter ready interrupt handler.
- *
- * \param rbf Pointer to the transmitter ring buffer.
- */
- static void At91UsartTxReady(RINGBUF *rbf)
- {
- register uint8_t *cp = rbf->rbf_tail;
- /*
- * Process pending software flow controls first.
- */
- if (flow_control & (XON_PENDING | XOFF_PENDING)) {
- if (flow_control & XON_PENDING) {
- outr(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
- flow_control |= XOFF_SENT;
- } else {
- outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
- flow_control &= ~XOFF_SENT;
- }
- flow_control &= ~(XON_PENDING | XOFF_PENDING);
- return;
- }
- if (flow_control & XOFF_RCVD) {
- /*
- * If XOFF has been received, we disable the transmit interrupts
- * and return without sending anything.
- */
- outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
- return;
- }
- /*
- * Check if we have more bytes to transmit.
- */
- if (rbf->rbf_cnt) {
- #if defined(UART_CTS_BIT) || defined(UART_USES_NPL)
- /*
- * If CTS has been disabled, we disable the transmit interrupts,
- * enable CTS interrupts and return without sending anything.
- */
- if (cts_sense && !UART_CTS_IS_ON()) {
- outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
- #if defined(UART_CTS_BIT)
- GpioIrqEnable(&UART_CTS_SIGNAL, UART_CTS_BIT);
- #else
- NplIrqEnable(&sig_RSCTS);
- #endif
- return;
- }
- #endif
- /*
- * Send address in multidrop mode.
- */
- if (tx_aframe) {
- outr(USARTn_BASE + US_CR_OFF, US_SENDA);
- }
- /* Start transmission of the next character. */
- outr(USARTn_BASE + US_THR_OFF, *cp);
- /* Decrement the number of available bytes in the buffer. */
- rbf->rbf_cnt--;
- /* Wrap around the buffer pointer if we reached its end. */
- if (++cp == rbf->rbf_last) {
- cp = rbf->rbf_start;
- }
- rbf->rbf_tail = cp;
- #if USE_BUILT_IN_HALF_DUPLEX == 0
- /*
- * If software half duplex enabled, we need TX-Empty IRQ for
- * detection if last bit of last byte transmission is finished.
- */
- if( hdx_control && rbf->rbf_cnt == 0) {
- outr(USARTn_BASE + US_IER_OFF, US_TXEMPTY);
- }
- #endif
- /* Send an event if we reached the low watermark. */
- if (rbf->rbf_cnt == rbf->rbf_lwm) {
- NutEventPostFromIrq(&rbf->rbf_que);
- NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_WRITE);
- }
- }
- /*
- * Nothing left to transmit, disable interrupt.
- */
- else {
- /* Disable transmit interrupts. */
- outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
- /* Send an event to inform the upper level. */
- NutEventPostFromIrq(&rbf->rbf_que);
- NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_WRITE);
- }
- }
- /*
- * \brief USARTn receiver ready interrupt handler.
- *
- *
- * \param rbf Pointer to the receiver ring buffer.
- */
- static void At91UsartRxReady(RINGBUF *rbf)
- {
- register size_t cnt;
- register uint8_t ch;
- /*
- * We read the received character as early as possible to avoid overflows
- * caused by interrupt latency.
- */
- ch = inb(USARTn_BASE + US_RHR_OFF);
- /* Collect receiver errors. */
- rx_errors |= inr(USARTn_BASE + US_CSR_OFF) & (US_OVRE | US_FRAME | US_PARE);
- /*
- * Handle software handshake. We have to do this before checking the
- * buffer, because flow control must work in write-only mode, where
- * there is no receive buffer.
- */
- if (flow_control) {
- /* XOFF character disables transmit interrupts. */
- if (ch == ASCII_XOFF) {
- outr(USARTn_BASE + US_IDR_OFF, US_TXRDY);
- flow_control |= XOFF_RCVD;
- return;
- }
- /* XON enables transmit interrupts. */
- else if (ch == ASCII_XON) {
- outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
- flow_control &= ~XOFF_RCVD;
- return;
- }
- }
- /*
- * Check buffer overflow.
- */
- cnt = rbf->rbf_cnt;
- if (cnt >= rbf->rbf_siz) {
- rx_errors |= US_OVRE;
- return;
- }
- /* Wake up waiting threads if this is the first byte in the buffer. */
- if (cnt++ == 0){
- NutEventPostFromIrq(&rbf->rbf_que);
- NutSelectWakeupFromIrq(rbf->wq_list, WQ_FLAG_READ);
- }
- /*
- * Check the high watermark for software handshake. If the number of
- * buffered bytes is equal or above this mark, then send XOFF.
- */
- else if (flow_control) {
- if(cnt >= rbf->rbf_hwm) {
- if((flow_control & XOFF_SENT) == 0) {
- if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
- outb(USARTn_BASE + US_THR_OFF, ASCII_XOFF);
- flow_control |= XOFF_SENT;
- flow_control &= ~XOFF_PENDING;
- } else {
- flow_control |= XOFF_PENDING;
- }
- }
- }
- }
- #if defined(UART_RTS_BIT) || defined(UART_USES_NPL)
- /*
- * Check the high watermark for GPIO hardware handshake. If the
- * number of buffered bytes is equal or above this mark, then
- * disable RTS.
- */
- else if (rts_control && cnt >= rbf->rbf_hwm) {
- UART_RTS_OFF();
- }
- #endif
- /*
- * Store the character and increment and the ring buffer pointer.
- */
- *rbf->rbf_head++ = ch;
- if (rbf->rbf_head == rbf->rbf_last) {
- rbf->rbf_head = rbf->rbf_start;
- }
- /* Update the ring buffer counter. */
- rbf->rbf_cnt = cnt;
- }
- /*!
- * \brief USART interrupt handler.
- *
- * \param arg Pointer to the device specific control block.
- */
- static void At91UsartInterrupt(void *arg)
- {
- USARTDCB *dcb = (USARTDCB *)arg;
- unsigned int csr = inr(USARTn_BASE + US_CSR_OFF);
- if (csr & US_RXRDY) {
- At91UsartRxReady(&dcb->dcb_rx_rbf);
- }
- if (csr & US_TXRDY) {
- At91UsartTxReady(&dcb->dcb_tx_rbf);
- }
- #if USE_BUILT_IN_HALF_DUPLEX == 0
- if (csr & US_TXEMPTY) {
- At91UsartTxEmpty(&dcb->dcb_tx_rbf);
- }
- #endif
- }
- /*!
- * \brief Carefully enable USART hardware functions.
- *
- * Always enabale transmitter and receiver, even on read-only or
- * write-only mode. So we can support software flow control.
- */
- static void At91UsartEnable(void)
- {
- /* Enable UART receiver and transmitter. */
- outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
- /* Globally enable UART interrupts. */
- NutUartIrqEnable(&SIG_UART);
- }
- /*!
- * \brief Carefully disable USART hardware functions.
- *
- * This routine is called before changing cruical settings like
- * baudrate, frame format etc.
- *
- * The previous version uses a 10ms delay to make sure, that any
- * incoming or outgoing character is processed. However, this time
- * depends on the baudrate.
- *
- * In fact we do not need to take care of incoming characters,
- * when changing such settings.
- *
- * For outgoing characters however, settings may be changed on
- * the fly and we should wait, until the last character transmitted
- * with the old settings has left the shift register. While TXRDY
- * is set when the holding register is empty, TXEMPTY is set when the
- * shift register is empty. The bad news is, that both are zero, if
- * the transmitter is disabled. We are not able to determine this
- * state. So we check TXRDY first and, if set, wait for any character
- * currently in the shift register.
- */
- static void At91UsartDisable(void)
- {
- /* Globally disable UART interrupts. */
- NutUartIrqDisable(&SIG_UART);
- /* Wait until all bits had been shifted out. */
- if (inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY) {
- while((inr(USARTn_BASE + US_CSR_OFF) & US_TXEMPTY) == 0);
- }
- /* Disable USART transmit and receive. */
- outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXDIS);
- }
- /*!
- * \brief Query the USART hardware for the selected speed.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return The currently selected baudrate.
- */
- static uint32_t At91UsartGetSpeed(void)
- {
- unsigned int cs;
- uint32_t clk;
- clk = NutClockGet(NUT_HWCLK_PERIPHERAL);
- cs = inr(USARTn_BASE + US_MR_OFF) & US_CLKS;
- if (cs == US_CLKS_MCK8) {
- clk /= 8;
- }
- else if (cs != US_CLKS_MCK) {
- clk = 0;
- }
- return clk / (16UL * (inr(USARTn_BASE + US_BRGR_OFF) & 0xFFFF));
- }
- /*!
- * \brief Set the USART hardware bit rate.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \param rate Number of bits per second.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int At91UsartSetSpeed(uint32_t rate)
- {
- At91UsartDisable();
- #if !(USARTn_BASE == DBGU_BASE)
- outr(USARTn_BASE + US_BRGR_OFF, (NutClockGet(NUT_HWCLK_PERIPHERAL) / (8 * (rate)) + 1) / 2);
- #else
- #if defined(AT91_PLL_MAINCK)
- outr(DBGU_BRGR, (At91GetMasterClock() / (8 * rate) + 1) / 2);
- #else
- outr(DBGU_BRGR, (NutGetCpuClock() / (8 * rate) + 1) / 2);
- #endif
- #endif
- At91UsartEnable();
- return 0;
- }
- /*!
- * \brief Query the USART hardware for the number of data bits.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return The number of data bits set.
- */
- static uint8_t At91UsartGetDataBits(void)
- {
- #if !(USARTn_BASE == DBGU_BASE)
- unsigned int val = inr(USARTn_BASE + US_MR_OFF);
- if ((val & US_PAR) == US_PAR_MULTIDROP) {
- val = 9;
- }
- else {
- val &= US_CHRL;
- if (val == US_CHRL_5) {
- val = 5;
- }
- else if (val == US_CHRL_6) {
- val = 6;
- }
- else if (val == US_CHRL_7) {
- val = 7;
- }
- else {
- val = 8;
- }
- }
- return (uint8_t)val;
- #else
- /* Not supported by DBGU, always 8 bits */
- return 8;
- #endif
- }
- /*!
- * \brief Set the USART hardware to the number of data bits.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int At91UsartSetDataBits(uint8_t bits)
- {
- #if !(USARTn_BASE == DBGU_BASE)
- unsigned int val = inr(USARTn_BASE + US_MR_OFF);
- if (bits == 9) {
- val &= ~US_PAR;
- val |= US_PAR_MULTIDROP;
- }
- else {
- val &= ~US_CHRL;
- if (bits == 5) {
- val |= US_CHRL_5;
- }
- else if (bits == 6) {
- val |= US_CHRL_6;
- }
- else if (bits == 7) {
- val |= US_CHRL_7;
- }
- else if (bits == 8) {
- val |= US_CHRL_8;
- }
- }
- At91UsartDisable();
- outr(USARTn_BASE + US_MR_OFF, val);
- At91UsartEnable();
- /*
- * Verify the result.
- */
- if (At91UsartGetDataBits() != bits) {
- return -1;
- }
- return 0;
- #else
- /* Not supported by DBGU, always 8 bits */
- return -1;
- #endif
- }
- /*!
- * \brief Query the USART hardware for the parity mode.
- *
- * This routine is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return Parity mode, either 0 (disabled), 1 (odd), 2 (even) or 9 (multidrop).
- */
- static uint8_t At91UsartGetParity(void)
- {
- unsigned int val = inr(USARTn_BASE + US_MR_OFF) & US_PAR;
- if ((val & US_PAR) == US_PAR_MULTIDROP) {
- val = 9;
- }
- else {
- if (val == US_PAR_ODD) {
- val = 1;
- }
- else if (val == US_PAR_EVEN) {
- val = 2;
- }
- else {
- val = 0;
- }
- }
- return (uint8_t)val;
- }
- /*!
- * \brief Set the USART hardware to the specified parity mode.
- *
- * This routine is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \param mode 0 (disabled), 1 (odd) or 2 (even)
- *
- * \return 0 on success, -1 otherwise.
- */
- static int At91UsartSetParity(uint8_t mode)
- {
- unsigned int val = inr(USARTn_BASE + US_MR_OFF) & ~US_PAR;
- switch (mode) {
- case 0:
- val |= US_PAR_NO;
- break;
- case 1:
- val |= US_PAR_ODD;
- break;
- case 2:
- val |= US_PAR_EVEN;
- break;
- }
- At91UsartDisable();
- outr(USARTn_BASE + US_MR_OFF, val);
- At91UsartEnable();
- /*
- * Verify the result.
- */
- if (At91UsartGetParity() != mode) {
- return -1;
- }
- return 0;
- }
- /*!
- * \brief Query the USART hardware for the number of stop bits.
- *
- * This routine is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return The number of stop bits set, either 1, 2 or 3 (1.5 bits).
- */
- static uint8_t At91UsartGetStopBits(void)
- {
- #if !(USARTn_BASE == DBGU_BASE)
- unsigned int val = inr(USARTn_BASE + US_MR_OFF) & US_NBSTOP;
- if (val == US_NBSTOP_1) {
- val = 1;
- }
- else if (val == US_NBSTOP_2) {
- val = 2;
- }
- else {
- val = 3;
- }
- return (uint8_t)val;
- #else
- /* Not supported by DBGU, always 1 */
- return 1;
- #endif
- }
- /*!
- * \brief Set the USART hardware to the number of stop bits.
- *
- * This routine is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int At91UsartSetStopBits(uint8_t bits)
- {
- #if !(USARTn_BASE == DBGU_BASE)
- unsigned int val = inr(USARTn_BASE + US_MR_OFF) & ~US_NBSTOP;
- switch(bits) {
- case 1:
- val |= US_NBSTOP_1;
- break;
- case 2:
- val |= US_NBSTOP_2;
- break;
- case 3:
- val |= US_NBSTOP_1_5;
- break;
- }
- At91UsartDisable();
- outr(USARTn_BASE + US_MR_OFF, val);
- At91UsartEnable();
- /*
- * Verify the result.
- */
- if (At91UsartGetStopBits() != bits) {
- return -1;
- }
- #endif
- return 0;
- }
- /*!
- * \brief Query the USART hardware status.
- *
- * \return Status flags.
- */
- static uint32_t At91UsartGetStatus(void)
- {
- uint32_t rc = 0;
- #if USE_BUILT_IN_HARDWARE_HANDSHAKE
- uint32_t csr = inr(USARTn_BASE + US_CSR_OFF);
- #endif
- /*
- * Set receiver error flags.
- */
- if ((rx_errors & US_FRAME) != 0) {
- rc |= UART_FRAMINGERROR;
- }
- if ((rx_errors & US_OVRE) != 0) {
- rc |= UART_OVERRUNERROR;
- }
- if ((rx_errors & US_PARE) != 0) {
- rc |= UART_PARITYERROR;
- }
- /*
- * Determine software handshake status. The flow control status may
- * change during interrupt, but this doesn't really hurt us.
- */
- if (flow_control) {
- if (flow_control & XOFF_SENT) {
- rc |= UART_RXDISABLED;
- }
- if (flow_control & XOFF_RCVD) {
- rc |= UART_TXDISABLED;
- }
- }
- /*
- * Determine hardware handshake control status.
- */
- #if USE_BUILT_IN_HARDWARE_HANDSHAKE
- /* How to find out? */
- #elif defined(UART_RTS_BIT)
- /* No definition of the status register? */
- #elif defined(UART_USES_NPL)
- if (bit_is_set(NPL_RSCR, NPL_RSRTS_BIT)) {
- rc |= UART_RTSDISABLED;
- if (rts_control) {
- rc |= UART_RXDISABLED;
- }
- } else {
- rc |= UART_RTSENABLED;
- }
- #endif
- /*
- * Determine hardware handshake sense status.
- */
- #if USE_BUILT_IN_HARDWARE_HANDSHAKE
- if (csr & US_CTS) {
- rc |= UART_CTSDISABLED;
- if (cts_sense) {
- rc |= UART_RXDISABLED;
- }
- } else {
- rc |= UART_CTSENABLED;
- }
- #else
- if (UART_CTS_IS_ON()) {
- rc |= UART_CTSENABLED;
- } else {
- rc |= UART_CTSDISABLED;
- if (cts_sense) {
- rc |= UART_RXDISABLED;
- }
- }
- #endif
- /*
- * Determine hardware modem sense status.
- */
- #if 0
- /* I'm confused. Awful flag mismatch? Why do we have uart.h and usart.h? */
- if (csr & US_RI) {
- rc |= UART_RIDISABLED;
- } else {
- rc |= UART_RIENABLED;
- }
- if (csr & US_DSR) {
- rc |= UART_DSRDISABLED;
- } else {
- rc |= UART_DSRENABLED;
- }
- if (csr & US_DCD) {
- rc |= UART_DCDDISABLED;
- } else {
- rc |= UART_DCDENABLED;
- }
- #endif
- /*
- * If transmitter and receiver haven't been detected disabled by any
- * of the checks above, then they are probably enabled.
- */
- if ((rc & UART_RXDISABLED) == 0) {
- rc |= UART_RXENABLED;
- }
- if ((rc & UART_TXDISABLED) == 0) {
- rc |= UART_TXENABLED;
- }
- /*
- * Process multidrop setting.
- */
- if (tx_aframe) {
- rc |= UART_TXADDRFRAME;
- } else {
- rc |= UART_TXNORMFRAME;
- }
- return rc;
- }
- /*!
- * \brief Set the USART hardware status.
- *
- * \param flags Status flags.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int At91UsartSetStatus(uint32_t flags)
- {
- /*
- * Process software handshake control.
- */
- if (flow_control) {
- /* Access to the flow control status must be atomic. */
- NutUartIrqDisable(&SIG_UART);
- /*
- * Enabling or disabling the receiver means to behave like
- * having sent a XON or XOFF character resp.
- */
- if (flags & UART_RXENABLED) {
- flow_control &= ~XOFF_SENT;
- } else if (flags & UART_RXDISABLED) {
- flow_control |= XOFF_SENT;
- }
- /*
- * Enabling or disabling the transmitter means to behave like
- * having received a XON or XOFF character resp.
- */
- if (flags & UART_TXENABLED) {
- flow_control &= ~XOFF_RCVD;
- } else if (flags & UART_TXDISABLED) {
- flow_control |= XOFF_RCVD;
- }
- NutUartIrqEnable(&SIG_UART);
- }
- /*
- * Process hardware handshake control.
- */
- #if USE_BUILT_IN_HARDWARE_HANDSHAKE
- /* Built-in hardware. */
- if (rts_control) {
- if (flags & UART_RXDISABLED) {
- outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
- }
- if (flags & UART_RXENABLED) {
- outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
- }
- }
- if (flags & UART_RTSDISABLED) {
- outr(USARTn_BASE + US_CR_OFF, US_RTSDIS);
- }
- if (flags & UART_RTSENABLED) {
- outr(USARTn_BASE + US_CR_OFF, US_RTSEN);
- }
- #else
- /* Manually controlled via GPIO. */
- if (rts_control) {
- if (flags & UART_RXDISABLED) {
- UART_RTS_OFF();
- }
- if (flags & UART_RXENABLED) {
- UART_RTS_ON();
- }
- }
- if (flags & UART_RTSDISABLED) {
- UART_RTS_OFF();
- }
- if (flags & UART_RTSENABLED) {
- UART_RTS_ON();
- }
- #endif
- /*
- * Process hardware modem control.
- */
- #if USE_BUILT_IN_MODEM_CONTROL
- /* Built-in hardware. */
- if (flags & UART_DTRDISABLED) {
- outr(USARTn_BASE + US_CR_OFF, US_DTRDIS);
- }
- if (flags & UART_DTRENABLED) {
- outr(USARTn_BASE + US_CR_OFF, US_DTREN);
- }
- #endif
- /*
- * Process multidrop setting.
- */
- if (flags & UART_TXADDRFRAME) {
- tx_aframe = 1;
- }
- if (flags & UART_TXNORMFRAME) {
- tx_aframe = 0;
- }
- /*
- * Clear UART receive errors.
- */
- if (flags & UART_ERRORS) {
- outr(USARTn_BASE + US_CR_OFF, US_RSTSTA);
- }
- /*
- * Verify the result.
- */
- if ((At91UsartGetStatus() & ~UART_ERRORS) != flags) {
- return -1;
- }
- return 0;
- }
- /*!
- * \brief Query the USART hardware for synchronous mode.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * Not implemented for the AT91 USART. Always returns 0.
- *
- * \return Or-ed combination of \ref UART_SYNC, \ref UART_MASTER,
- * \ref UART_NCLOCK and \ref UART_HIGHSPEED.
- */
- static uint8_t At91UsartGetClockMode(void)
- {
- return 0;
- }
- /*!
- * \brief Set asynchronous or synchronous mode.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * Not implemented for the AT91 USART. Always returns -1.
- *
- * \param mode Must be an or-ed combination of USART_SYNC, USART_MASTER,
- * USART_NCLOCK and USART_HIGHSPEED.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int At91UsartSetClockMode(uint8_t mode)
- {
- return -1;
- }
- /*!
- * \brief Query flow control mode.
- *
- * This routine is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \return See UsartIOCtl().
- */
- static uint32_t At91UsartGetFlowControl(void)
- {
- uint32_t rc = 0;
- if (flow_control) {
- rc |= USART_MF_XONXOFF;
- } else {
- rc &= ~USART_MF_XONXOFF;
- }
- #if defined(UART_RTS_BIT) || defined(UART_USES_NPL) || defined(UART_HARDWARE_HANDSHAKE)
- if (rts_control) {
- rc |= USART_MF_RTSCONTROL;
- } else {
- rc &= ~USART_MF_RTSCONTROL;
- }
- #endif
- #if defined(UART_CTS_BIT) || defined(UART_USES_NPL) || defined(UART_HARDWARE_HANDSHAKE)
- if (cts_sense) {
- rc |= USART_MF_CTSSENSE;
- } else {
- rc &= ~USART_MF_CTSSENSE;
- }
- #endif
- if (hdx_control) {
- rc |= USART_MF_HALFDUPLEX;
- } else {
- rc &= ~USART_MF_HALFDUPLEX;
- }
- return rc;
- }
- /*!
- * \brief Set flow control mode.
- *
- * This function is called by ioctl function of the upper level USART
- * driver through the USARTDCB jump table.
- *
- * \param flags See UsartIOCtl().
- *
- * \return 0 on success, -1 otherwise.
- */
- static int At91UsartSetFlowControl(uint32_t flags)
- {
- #if USE_BUILT_IN_HARDWARE_HANDSHAKE || USE_BUILT_IN_HALF_DUPLEX
- uint32_t mr = inr(USARTn_BASE + US_MR_OFF) & ~US_MODE;
- #endif
- /*
- * Set software handshake mode.
- */
- NutUartIrqDisable(&SIG_UART);
- if (flags & USART_MF_XONXOFF) {
- if(flow_control == 0) {
- flow_control = 1 | XOFF_SENT; /* force XON to be sent on next read */
- }
- } else {
- flow_control = 0;
- }
- NutUartIrqEnable(&SIG_UART);
- /*
- * Set RTS control mode.
- */
- UART_RTS_PIN_ENABLE();
- UART_RTS_ON();
- if (flags & USART_MF_RTSCONTROL) {
- rts_control = 1;
- #if USE_BUILT_IN_HARDWARE_HANDSHAKE
- outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_HWHANDSHAKE);
- cts_sense = 1;
- #endif
- } else if (rts_control) {
- rts_control = 0;
- #if USE_BUILT_IN_HARDWARE_HANDSHAKE
- outr(USARTn_BASE + US_MR_OFF, mr);
- cts_sense = 0;
- #endif
- }
- /*
- * Set CTS sense mode.
- */
- if (flags & USART_MF_CTSSENSE) {
- cts_sense = 1;
- UART_CTS_PIN_ENABLE();
- #if USE_BUILT_IN_HARDWARE_HANDSHAKE
- rts_control = 1;
- outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_HWHANDSHAKE);
- #endif
- } else if (cts_sense) {
- cts_sense = 0;
- #if USE_BUILT_IN_HARDWARE_HANDSHAKE
- rts_control = 0;
- outr(USARTn_BASE + US_MR_OFF, mr);
- #endif
- }
- /*
- * Set half duplex mode.
- */
- if (flags & USART_MF_HALFDUPLEX) {
- /* Mark half duplex mode enabled. */
- hdx_control = 1;
- /* Enable half duplex pin. */
- UART_HDX_PIN_ENABLE();
- UART_HDX_RX();
- #if USE_BUILT_IN_HALF_DUPLEX
- /* Enable built-in RS-485 mode. */
- outr(USARTn_BASE + US_MR_OFF, mr | US_MODE_RS485);
- #else
- /* Enable USART receive, disable transmit. */
- outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXDIS);
- /* Enable transmit complete interrupt. */
- outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
- #endif
- }
- else if (hdx_control) {
- hdx_control = 0;
- #if USE_BUILT_IN_HALF_DUPLEX
- /* Disable built-in RS-485 mode. */
- outr(USARTn_BASE + US_MR_OFF, inr(USARTn_BASE + US_MR_OFF) & ~US_MODE);
- #else
- /* Enable USART receive and transmit. */
- outr(USARTn_BASE + US_CR_OFF, US_RXEN | US_TXEN);
- /* Disable transmit complete interrupt. */
- outr(USARTn_BASE + US_IDR_OFF, US_TXEMPTY);
- #endif
- }
- /* No need to call At91UsartGetFlowControl. The result is obvious,
- ** because we do not exclude unsupported modes yet. */
- return 0;
- }
- /*!
- * \brief Start the USART transmitter hardware.
- *
- * The upper level USART driver will call this function through the
- * USARTDCB jump table each time it added one or more bytes to the
- * transmit buffer.
- */
- static void At91UsartTxStart(void)
- {
- #if USE_BUILT_IN_HALF_DUPLEX == 0
- if (hdx_control) {
- #if defined(UART_HDX_BIT) || defined(UART_USES_NPL)
- UART_HDX_TX();
- #endif
- /* Disable USART receive, enable transmit. */
- outr(USARTn_BASE + US_CR_OFF, US_RXDIS | US_TXEN);
- }
- #endif
- /* Enable transmit interrupts. */
- outr(USARTn_BASE + US_IER_OFF, US_TXRDY);
- }
- /*!
- * \brief Start the USART receiver hardware.
- *
- * The upper level USART driver will call this function through the
- * USARTDCB jump table each time it removed enough bytes from the
- * receive buffer. Enough means, that the number of bytes left in
- * the buffer is below the low watermark.
- */
- static void At91UsartRxStart(void)
- {
- /*
- * Do any required software flow control.
- */
- if (flow_control && (flow_control & XOFF_SENT) != 0) {
- NutUartIrqDisable(&SIG_UART);
- if ((inr(USARTn_BASE + US_CSR_OFF) & US_TXRDY)) {
- outr(USARTn_BASE + US_THR_OFF, ASCII_XON);
- flow_control &= ~XON_PENDING;
- } else {
- flow_control |= XON_PENDING;
- }
- flow_control &= ~(XOFF_SENT | XOFF_PENDING);
- NutUartIrqEnable(&SIG_UART);
- }
- /* Enable RTS. */
- UART_RTS_ON();
- /* Enable receive interrupts. */
- outr(USARTn_BASE + US_IER_OFF, US_RXRDY);
- }
- /*
- * \brief Initialize the USART hardware driver.
- *
- * This function is called during device registration by the upper level
- * USART driver through the USARTDCB jump table.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int At91UsartInit(void)
- {
- /*
- * Register receive and transmit interrupts.
- */
- if (NutUartIrqRegister(&SIG_UART, At91UsartInterrupt, &dcb_usart)) {
- return -1;
- }
- /*
- * Register CTS sense interrupts.
- */
- #if defined(UART_CTS_BIT)
- if (GpioRegisterIrqHandler(&sig_GPIO1, UART_CTS_BIT, At91UsartCts, NULL)) {
- return -1;
- }
- #if defined(PS_PCER)
- outr(PS_PCER, _BV(UART_CTS_PIO_ID));
- #elif defined(PMC_PCER)
- outr(PMC_PCER, _BV(UART_CTS_PIO_ID));
- #endif
- #elif defined(UART_USES_NPL)
- if (NplRegisterIrqHandler(&sig_RSCTS, At91UsartCts, NULL)) {
- return -1;
- }
- #endif
- /* Enable UART clock. */
- #if defined(US_ID)
- #if defined(PS_PCER)
- outr(PS_PCER, _BV(US_ID));
- #elif defined(PMC_PCER)
- outr(PMC_PCER, _BV(US_ID));
- #endif
- #endif
- /* Disable GPIO on UART tx/rx pins. */
- UART_RXTX_PINS_ENABLE();
- /* Reset UART. */
- outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
- /* Disable all UART interrupts. */
- outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
- #if defined(US_RCR_OFF) && defined(US_TCR_OFF)
- /* Clear UART PDC counter registers. */
- outr(USARTn_BASE + US_RCR_OFF, 0);
- outr(USARTn_BASE + US_TCR_OFF, 0);
- #endif
- /* Set UART baud rate generator register. */
- At91UsartSetSpeed( UART_INIT_BAUDRATE);
- /* Set UART mode to 8 data bits, no parity and 1 stop bit. */
- outr(USARTn_BASE + US_MR_OFF, US_CHMODE_NORMAL | US_CHRL_8 | US_PAR_NO | US_NBSTOP_1);
- return 0;
- }
- /*
- * \brief Deinitialize the USART hardware driver.
- *
- * This function is called during device deregistration by the upper
- * level USART driver through the USARTDCB jump table.
- *
- * \return 0 on success, -1 otherwise.
- */
- static int At91UsartDeinit(void)
- {
- /* Deregister receive and transmit interrupts. */
- NutUartIrqRegister(&SIG_UART, 0, 0);
- /* Reset UART. */
- outr(USARTn_BASE + US_CR_OFF, US_RSTRX | US_RSTTX | US_RXDIS | US_TXDIS);
- /* Disable all UART interrupts. */
- outr(USARTn_BASE + US_IDR_OFF, 0xFFFFFFFF);
- /* Disable UART clock. */
- #if defined (US_ID)
- #if defined(PS_PCDR)
- outr(PS_PCDR, _BV(US_ID));
- #elif defined(PMC_PCDR)
- outr(PMC_PCDR, _BV(US_ID));
- #endif
- #endif
- /*
- * Disabling flow control shouldn't be required here, because it's up
- * to the upper level to do this on the last close or during
- * deregistration.
- */
- hdx_control = 0;
- UART_HDX_RX();
- cts_sense = 0;
- rts_control = 0;
- return 0;
- }
- /*@}*/
|