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

📄 uartgba.c

📁 含有完整TCP/IP PPP协议的嵌入式操作系统
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2001-2005 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/ *//* * $Log: uartgba.c,v $ * Revision 1.3  2005/10/24 17:59:19  haraldkipp * Use correct header file, arm, not gba. * * Revision 1.2  2005/08/02 17:46:45  haraldkipp * Major API documentation update. * * Revision 1.1  2005/07/26 18:02:26  haraldkipp * Moved from dev. * * Revision 1.1  2005/04/05 18:01:43  haraldkipp * This code is buggy! Anyone willing to help? * */#include <sys/atom.h>#include <sys/event.h>#include <sys/timer.h>#include <dev/irqreg.h>#include <arch/arm.h>#include <dev/usart.h>#include <stdio.h>/*! * \addtogroup xgUartGba *//*@{*//* \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;static volatile ureg_t tx_stop = 1;static USARTDCB dcb_uart;/* * \brief USART0 transmit data register empty interrupt handler. * * \param arg Pointer to the transmitter ring buffer. */static void GbaUartTxEmpty(RINGBUF * rbf){    register u_char *cp = rbf->rbf_tail;    /*     * Process pending software flow controls first.     */    if (flow_control & (XON_PENDING | XOFF_PENDING)) {        if (flow_control & XON_PENDING) {            outw(REG_SIODATA8, ASCII_XOFF);            flow_control |= XOFF_SENT;        } else {            outw(REG_SIODATA8, 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.         */        tx_stop = 1;        outw(REG_SIOCNT, inw(REG_SIOCNT) & ~SIO_SEND_ENA);        return;    }    if (rbf->rbf_cnt) {        rbf->rbf_cnt--;        /*         * Start transmission of the next character.         */        outw(REG_SIODATA8, *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 {        tx_stop = 1;        outw(REG_SIOCNT, (inw(REG_SIOCNT) & ~SIO_SEND_ENA) | SIO_TX_FULL);        rbf->rbf_cnt = 0;        NutEventPostFromIrq(&rbf->rbf_que);    }}/* * \brief USART0 receive complete interrupt handler. * * * \param arg Pointer to the receiver ring buffer. */static void GbaUartRxFull(RINGBUF * rbf){    register size_t cnt;    register u_char ch;    /*     * 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.     */    //TODO rx_errors |= inb(UCSRnA);    ch = (u_char) inw(REG_SIODATA8);    /*     * 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) {            tx_stop = 1;            outw(REG_SIOCNT, inw(REG_SIOCNT) & ~SIO_SEND_ENA);            flow_control |= XOFF_RCVD;            return;        }        /* XON enables transmit interrupts. */        else if (ch == ASCII_XON) {            tx_stop = 0; //TODO            outw(REG_SIOCNT, inw(REG_SIOCNT) | SIO_SEND_ENA);            flow_control &= ~XOFF_RCVD;            return;        }    }    /*     * Check buffer overflow.     */    cnt = rbf->rbf_cnt;    if (cnt >= rbf->rbf_siz) {        //TODO rx_errors |= _BV(DOR);        return;    }    /* Wake up waiting threads if this is the first byte in the buffer. */    if (cnt++ == 0) {        NutEventPostFromIrq(&rbf->rbf_que);    }    /*     * 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 (inw(REG_SIOCNT) & SIO_TX_FULL) {                    flow_control |= XOFF_PENDING;                } else {                    outw(REG_SIODATA8, ASCII_XOFF);                    flow_control |= XOFF_SENT;                    flow_control &= ~XOFF_PENDING;                }            }        }    }    /*      * 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;}static void GbaUartIsr(void *arg){    /* Clear interrupt. */    outw(REG_IF, INT_SIO);    if ((inw(REG_SIOCNT) & SIO_RX_EMPTY) == 0) {        GbaUartRxFull(&((USARTDCB *) arg)->dcb_rx_rbf);    }    if ((inw(REG_SIOCNT) & SIO_TX_FULL) == 0) {        GbaUartTxEmpty(&((USARTDCB *) arg)->dcb_tx_rbf);    }}/*! * \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 GbaUartEnable(void){    NutEnterCritical();    //TODO outb(UCSRnB, _BV(RXCIE) | _BV(UDRIE) | _BV(RXEN) | _BV(TXEN));    NutExitCritical();}/*! * \brief Carefully disable USART hardware functions. */static void GbaUartDisable(void){    /*     * Disable USART interrupts.     */    //TODO NutEnterCritical();    //TODO cbi(UCSRnB, RXCIE);    //TODO cbi(UCSRnB, TXCIE);    //TODO cbi(UCSRnB, UDRIE);    //TODO NutExitCritical();    /*     * Allow incoming or outgoing character to finish.     */    //TODO NutDelay(10);    /*     * Disable USART transmit and receive.     */    //TODO cbi(UCSRnB, RXEN);    //TODO cbi(UCSRnB, TXEN);}/*! * \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 u_long GbaUartGetSpeed(void){    u_short sv = inw(REG_SIOCNT);    if ((sv & SIO_BAUD_115200) == SIO_BAUD_115200) {        return 115200UL;    }    if ((sv & SIO_BAUD_57600) == SIO_BAUD_57600) {        return 57600UL;    }    if ((sv & SIO_BAUD_38400) == SIO_BAUD_38400) {        return 38400L;    }    return 9600UL;}/*! * \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 GbaUartSetSpeed(u_long rate){    u_short sv;    GbaUartDisable();    sv = inw(REG_SIOCNT) & ~SIO_BAUD_115200;    if (rate == 115200) {        sv |= SIO_BAUD_115200;    } else {        if (rate == 57600) {            sv |= SIO_BAUD_57600;        } else if (rate == 38400) {            sv |= SIO_BAUD_38400;        }    }    outw(REG_SIOCNT, sv);    GbaUartEnable();    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 u_char GbaUartGetDataBits(void){    return 8;}/*! * \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 GbaUartSetDataBits(u_char bits){    GbaUartDisable();    GbaUartEnable();    /*     * Verify the result.     */    if (GbaUartGetDataBits() != bits) {        return -1;    }    return 0;}/*! * \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) or 2 (even). */static u_char GbaUartGetParity(void){    return 0;}/*! * \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 GbaUartSetParity(u_char mode){    GbaUartDisable();

⌨️ 快捷键说明

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