⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 usartavr.c

📁 含有完整TCP/IP PPP协议的嵌入式操作系统
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (C) 2001-2003 by egnite Software 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 EGNITE SOFTWARE GMBH 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 EGNITE * SOFTWARE GMBH 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/ * * The 9-bit communication had been contributed by Brett Abbott, * Digital Telemetry Limited. * * Dave Smart contributed the synchronous mode support. *//* * $Log: usartavr.c,v $ * Revision 1.2  2005/10/07 22:05:00  hwmaier * Using __AVR_ENHANCED__ macro instead of __AVR_ATmega128__ to support also AT90CAN128 MCU * * Revision 1.1  2005/07/26 18:02:40  haraldkipp * Moved from dev. * * Revision 1.10  2005/07/22 08:07:07  freckle * added experimental improvements to usart driver. see ChangeLog for details * * Revision 1.9  2005/02/21 12:38:00  phblum * Removed tabs and added semicolons after NUTTRACER macros * * Revision 1.8  2005/01/24 22:34:46  freckle * Added new tracer by Phlipp Blum <blum@tik.ee.ethz.ch> * * Revision 1.6  2005/01/21 16:49:46  freckle * Seperated calls to NutEventPostAsync between Threads and IRQs * * Revision 1.5  2004/11/12 08:25:51  drsung * Bugfix in AvrUsartTxEmpty. Thanks to Grzegorz Plonski and Matthias Ringwald. * * Revision 1.4  2004/05/26 09:04:17  drsung * Bugfix in AvrUsartTxStart. Now the correct port and pin are used for half duplex mode...again... * Thanks to Przemyslaw Rudy. * * Revision 1.3  2004/05/16 14:09:06  drsung * Applied bugfixes for half duplex mode an XON/XOFF handling. Thanks to Damian Slee. * * Revision 1.2  2004/04/07 12:58:52  haraldkipp * Bugfix for half duplex mode * * Revision 1.1  2003/12/15 19:25:33  haraldkipp * New USART driver added * */#include <sys/atom.h>#include <sys/event.h>#include <sys/timer.h>#include <dev/irqreg.h>#include <dev/usartavr.h>#ifdef NUTTRACER#include <sys/tracer.h>#endif/*! * \addtogroup xgUsartAvr *//*@{*//* \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 ureg_t rx_errors;/*! * \brief Enables software flow control if not equal zero. */static ureg_t flow_control;/*! * \brief Transmit address frame, if not zero. */static ureg_t tx_aframe;#ifdef UART_HDX_BIT	/* define in cfg/modem.h */	#ifdef UART_HDX_FLIP_BIT	/* same as RTS toggle by Windows NT driver */		#define UART_HDX_TX		cbi		#define UART_HDX_RX		sbi	#else						/* previous usage by Ethernut */		#define UART_HDX_TX		sbi		#define UART_HDX_RX		cbi	#endif#endif#ifdef UART_HDX_BIT/*! * \brief Enables half duplex control if not equal zero. * * This variable exists only if the hardware configuration defines a * port bit to switch between receive and transmit mode. */static ureg_t hdx_control;#endif#ifdef UART_RTS_BIT/*! * \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 ureg_t rts_control;#endif#ifdef UART_CTS_BIT/*! * \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 ureg_t cts_sense;#endif#ifdef UART_CTS_BIT/*! * \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 AvrUsartCts(void *arg){    /* Enable transmit interrupt. */    sbi(UCSRnB, UDRIE);    /* Disable CTS sense interrupt. */    cbi(EIMSK, UART_CTS_BIT);}#endif#ifdef UART_HDX_BIT/* * \brief USARTn transmit complete interrupt handler. * * Used with half duplex communication to switch from tranmit to receive * mode after the last character has been transmitted. * * This routine exists only if the hardware configuration defines a * port bit to switch between receive and transmit mode. * * \param arg Pointer to the transmitter ring buffer. */static void AvrUsartTxComplete(void *arg){    register RINGBUF *rbf = (RINGBUF *) arg;    /*     * 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. */        UART_HDX_RX(UART_HDX_PORT, UART_HDX_BIT);    }}#endif/* * \brief USARTn transmit data register empty interrupt handler. * * \param arg Pointer to the transmitter ring buffer. */#ifdef USE_USARTSIGNAL( SIG_UART_DATA ) {    register RINGBUF *rbf = &dcb_usart.dcb_tx_rbf;#elsestatic void AvrUsartTxEmpty(void *arg) {    register RINGBUF *rbf = (RINGBUF *) arg;#endif    register u_char *cp = rbf->rbf_tail;#ifdef NUTTRACER    TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_ENTER,TRACE_INT_UART_TXEMPTY);#endif#ifndef UART_NO_SW_FLOWCONTROL    /*     * Process pending software flow controls first.     */    if (flow_control & (XON_PENDING | XOFF_PENDING)) {        if (flow_control & XON_PENDING) {            outb(UDRn, ASCII_XOFF);            flow_control |= XOFF_SENT;        } else {            outb(UDRn, ASCII_XON);            flow_control &= ~XOFF_SENT;        }        flow_control &= ~(XON_PENDING | XOFF_PENDING);#ifdef NUTTRACER        TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_TXEMPTY);#endif        return;    }    if (flow_control & XOFF_RCVD) {        /*         * If XOFF has been received, we disable the transmit interrupts         * and return without sending anything.         */        cbi(UCSRnB, UDRIE);#ifdef NUTTRACER        TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_TXEMPTY);#endif        return;	}#endif /* UART_NO_SW_FLOWCONTROL */    if (rbf->rbf_cnt) {#ifdef UART_CTS_BIT        /*         * If CTS has been disabled, we disable the transmit interrupts         * and return without sending anything.         */        if (cts_sense && bit_is_set(UART_CTS_PIN, UART_CTS_BIT)) {            cbi(UCSRnB, UDRIE);            sbi(EIMSK, UART_CTS_BIT);#ifdef NUTTRACER            TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_TXEMPTY);#endif            return;        }#endif        rbf->rbf_cnt--;        /*         * The data sheet doesn't exactly tell us, if this bit is retained         * or cleared after the character has been sent out. So we do it         * the save way.         */        if (tx_aframe) {            sbi(UCSRnB, TXB8);        } else {            cbi(UCSRnB, TXB8);        }        /*         * Start transmission of the next character.         */        outb(UDRn, *cp);        /*         * Wrap around the buffer pointer if we reached its end.         */        if (++cp == rbf->rbf_last) {            cp = rbf->rbf_start;        }        rbf->rbf_tail = cp;        if (rbf->rbf_cnt == rbf->rbf_lwm) {            NutEventPostFromIrq(&rbf->rbf_que);        }    }    /*     * Nothing left to transmit, disable interrupt.     */    else {        cbi(UCSRnB, UDRIE);        rbf->rbf_cnt = 0;        NutEventPostFromIrq(&rbf->rbf_que);    }#ifdef NUTTRACER    TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_TXEMPTY);#endif}/* * \brief USARTn receive complete interrupt handler. * * * \param arg Pointer to the receiver ring buffer. */#ifdef USE_USARTSIGNAL( SIG_UART_RECV ){    register RINGBUF *rbf = &dcb_usart.dcb_rx_rbf;#elsestatic void AvrUsartRxComplete(void *arg) {    register RINGBUF *rbf = (RINGBUF *) arg;#endif    register size_t cnt;    register u_char ch;#ifdef NUTTRACER    TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_ENTER,TRACE_INT_UART_RXCOMPL);#endif#ifdef UART_READMULTIBYTE    register u_char postEvent = 0;    do {#endif        /*         * We read the received character as early as possible to avoid overflows         * caused by interrupt latency. However, reading the error flags must come         * first, because reading the ATmega128 data register clears the status.         */        rx_errors |= inb(UCSRnA);        ch = inb(UDRn);#ifndef UART_NO_SW_FLOWCONTROL        /*         * 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) {                cbi(UCSRnB, UDRIE);                flow_control |= XOFF_RCVD;#ifdef NUTTRACER                TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_RXCOMPL);#endif                return;            }            /* XON enables transmit interrupts. */            else if (ch == ASCII_XON) {                sbi(UCSRnB, UDRIE);                flow_control &= ~XOFF_RCVD;#ifdef NUTTRACER                TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_RXCOMPL);#endif                return;            }        }#endif        /*         * Check buffer overflow.         */        cnt = rbf->rbf_cnt;        if (cnt >= rbf->rbf_siz) {            rx_errors |= _BV(DOR);#ifdef NUTTRACER            TRACE_ADD_ITEM(TRACE_TAG_INTERRUPT_EXIT,TRACE_INT_UART_RXCOMPL);#endif            return;        }        /* Wake up waiting threads if this is the first byte in the buffer. */        if (cnt++ == 0){#ifdef UART_READMULTIBYTE            // we do this later, to get the other bytes in time..            postEvent = 1;#else            NutEventPostFromIrq(&rbf->rbf_que);#endif        }#ifndef UART_NO_SW_FLOWCONTROL        /*         * Check the high watermark for software handshake. If the number of         * buffered bytes is above this mark, then send XOFF.         */        else if (flow_control) {            if(cnt >= rbf->rbf_hwm) {                if((flow_control & XOFF_SENT) == 0) {                    if (inb(UCSRnA) & _BV(UDRE)) {                        outb(UDRn, ASCII_XOFF);                        flow_control |= XOFF_SENT;                        flow_control &= ~XOFF_PENDING;                    } else {                        flow_control |= XOFF_PENDING;                    }                }            }        }#endif#ifdef UART_RTS_BIT        /*         * Check the high watermark for hardware handshake. If the number of         * buffered bytes is above this mark, then disable RTS.         */        else if (rts_control && cnt >= rbf->rbf_hwm) {            sbi(UART_RTS_PORT, UART_RTS_BIT);        }#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -