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

📄 serial.c

📁 移植到WLIT项目的redboot源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
//==========================================================================////      io/serial/common/serial.c////      High level serial driver////==========================================================================//####COPYRIGHTBEGIN####//                                                                          // -------------------------------------------                              // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in         // compliance with the License.  You may obtain a copy of the License at    // http://www.redhat.com/                                                   //                                                                          // Software distributed under the License is distributed on an "AS IS"      // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied.  See the // License for the specific language governing rights and limitations under // the License.                                                             //                                                                          // The Original Code is eCos - Embedded Configurable Operating System,      // released September 30, 1998.                                             //                                                                          // The Initial Developer of the Original Code is Red Hat.                   // Portions created by Red Hat are                                          // Copyright (C) 1998, 1999, 2000 Red Hat, Inc.                             // All Rights Reserved.                                                     // -------------------------------------------                              //                                                                          //####COPYRIGHTEND####//==========================================================================//#####DESCRIPTIONBEGIN####//// Author(s):    gthomas// Contributors: gthomas, grante, jlarmour, jskov// Date:         1999-02-04// Purpose:      Top level serial driver// Description: ////####DESCRIPTIONEND####////==========================================================================#include <pkgconf/io.h>#include <pkgconf/io_serial.h>#include <cyg/io/io.h>#include <cyg/io/devtab.h>#include <cyg/io/serial.h>#include <cyg/infra/cyg_ass.h>      // assertion support#include <cyg/infra/diag.h>         // diagnostic outputstatic Cyg_ErrNo serial_write(cyg_io_handle_t handle, const void *buf, cyg_uint32 *len);static Cyg_ErrNo serial_read(cyg_io_handle_t handle, void *buf, cyg_uint32 *len);static Cyg_ErrNo serial_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info);static Cyg_ErrNo serial_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *buf, cyg_uint32 *len);static Cyg_ErrNo serial_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *buf, cyg_uint32 *len);DEVIO_TABLE(cyg_io_serial_devio,            serial_write,            serial_read,            serial_select,            serial_get_config,            serial_set_config    );static void serial_init(serial_channel *chan);static void serial_xmt_char(serial_channel *chan);static void serial_rcv_char(serial_channel *chan, unsigned char c);#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUSstatic void serial_indicate_status(serial_channel *chan,                                   cyg_serial_line_status_t *s);#endif#if CYGINT_IO_SERIAL_BLOCK_TRANSFERstatic rcv_req_reply_t serial_data_rcv_req(serial_channel *chan, int avail,                                            int* space_avail,                                            unsigned char** space);static void serial_data_rcv_done(serial_channel *chan, int chars_rcvd);static xmt_req_reply_t serial_data_xmt_req(serial_channel *chan, int space,                                           int* chars_avail,                                            unsigned char** chars);static void serial_data_xmt_done(serial_channel *chan, int chars_sent);# ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HWSERIAL_CALLBACKS(cyg_io_serial_callbacks,                  serial_init,                  serial_xmt_char,                  serial_rcv_char,                 serial_data_rcv_req,                 serial_data_rcv_done,                 serial_data_xmt_req,                 serial_data_xmt_done,                 serial_indicate_status);# elseSERIAL_CALLBACKS(cyg_io_serial_callbacks,                  serial_init,                  serial_xmt_char,                  serial_rcv_char,                 serial_data_rcv_req,                 serial_data_rcv_done,                 serial_data_xmt_req,                 serial_data_xmt_done);# endif#else# ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUSSERIAL_CALLBACKS(cyg_io_serial_callbacks,                  serial_init,                  serial_xmt_char,                  serial_rcv_char,                 serial_indicate_status);# elseSERIAL_CALLBACKS(cyg_io_serial_callbacks,                  serial_init,                  serial_xmt_char,                  serial_rcv_char);# endif#endif// ---------------------------------------------------------------------------#ifdef CYGPKG_IO_SERIAL_FLOW_CONTROLstatic __inline__ voidthrottle_tx( serial_channel *chan ){    chan->flow_desc.flags |= CYG_SERIAL_FLOW_OUT_THROTTLED;    // the throttling itself occurs in the serial_xmt_char() callback}static __inline__ voidrestart_tx( serial_channel *chan ){    serial_funs *funs = chan->funs;    chan->flow_desc.flags &= ~CYG_SERIAL_FLOW_OUT_THROTTLED;#ifdef CYGPKG_IO_SERIAL_SELECT_SUPPORT    // See if there is now enough room to say it is available    // for writing    {        cbuf_t *cbuf = &chan->out_cbuf;        int space;                space = cbuf->len - cbuf->nb;        if (space >= cbuf->low_water)            cyg_selwakeup( &cbuf->selinfo );    }#endif    if ( chan->out_cbuf.nb > 0 )        (funs->start_xmit)(chan);}static __inline__ voidthrottle_rx( serial_channel *chan, cyg_bool force ){    serial_funs *funs = chan->funs;    chan->flow_desc.flags |= CYG_SERIAL_FLOW_IN_THROTTLED;#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_SOFTWARE    // send an xoff    if ( force || chan->config.flags & CYGNUM_SERIAL_FLOW_XONXOFF_RX ) {        chan->flow_desc.xchar = CYGDAT_IO_SERIAL_FLOW_CONTROL_XOFF_CHAR;        // Make sure xmit is running so we can send it        (funs->start_xmit)(chan);     }#endif#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW    {        cyg_uint32 i=1;        cyg_uint32 len = sizeof(i);                // set hardware flow control - don't care if it fails        if ( force || (chan->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_RX) ||             (chan->config.flags & CYGNUM_SERIAL_FLOW_DSRDTR_RX) )            (funs->set_config)(chan,                               CYG_IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE,                               &i, &len);    }#endif}static __inline__ voidrestart_rx( serial_channel *chan, cyg_bool force ){    serial_funs *funs = chan->funs;    chan->flow_desc.flags &= ~CYG_SERIAL_FLOW_IN_THROTTLED;#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_SOFTWARE    // send an xon    if ( force || chan->config.flags & CYGNUM_SERIAL_FLOW_XONXOFF_RX ) {        chan->flow_desc.xchar = CYGDAT_IO_SERIAL_FLOW_CONTROL_XON_CHAR;        (funs->start_xmit)(chan);  // Make sure xmit is running so we can send it    }#endif#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW    {        cyg_uint32 i=0;        cyg_uint32 len = sizeof(i);                // set hardware flow control - don't care if it fails        if ( force || (chan->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_RX) ||             (chan->config.flags & CYGNUM_SERIAL_FLOW_DSRDTR_RX) )            (funs->set_config)(chan,                               CYG_IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE,                               &i, &len);    }#endif}#endif// ---------------------------------------------------------------------------static voidserial_init(serial_channel *chan){    if (chan->init) return;    if (chan->out_cbuf.len != 0) {#ifdef CYGDBG_IO_INIT        diag_printf("Set output buffer - buf: %x len: %d\n", chan->out_cbuf.data, chan->out_cbuf.len);#endif        chan->out_cbuf.waiting = false;        chan->out_cbuf.abort = false;#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING        chan->out_cbuf.blocking = true;#endif        chan->out_cbuf.pending = 0;        cyg_drv_mutex_init(&chan->out_cbuf.lock);        cyg_drv_cond_init(&chan->out_cbuf.wait, &chan->out_cbuf.lock);        chan->out_cbuf.low_water = chan->out_cbuf.len / 4;#ifdef CYGPKG_IO_SERIAL_SELECT_SUPPORT        cyg_selinit( &chan->out_cbuf.selinfo );#endif            }    if (chan->in_cbuf.len != 0) {        cbuf_t *cbuf = &chan->in_cbuf;#ifdef CYGDBG_IO_INIT        diag_printf("Set input buffer - buf: %x len: %d\n", cbuf->data, cbuf->len);#endif        cbuf->waiting = false;        cbuf->abort = false;#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING        cbuf->blocking = true;#endif#ifdef CYGPKG_IO_SERIAL_SELECT_SUPPORT        cyg_selinit( &cbuf->selinfo );#endif#ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL        cbuf->low_water =            (CYGNUM_IO_SERIAL_FLOW_CONTROL_LOW_WATER_PERCENT * cbuf->len) / 100;        cbuf->high_water =            (CYGNUM_IO_SERIAL_FLOW_CONTROL_HIGH_WATER_PERCENT * cbuf->len) / 100;# ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_SOFTWARE        // But make sure it is at least 35 below buffer size, to allow        // for 16 byte fifos, twice, plus some latency before s/w flow        // control can kick in. This doesn't apply to h/w flow control        // as it is near-instaneous        if ( (cbuf->len - cbuf->high_water) < 35 )            cbuf->high_water = cbuf->len - 35;        // and just in case...        if ( cbuf->high_water <= 0 )            cbuf->high_water = 1;        if ( cbuf->low_water > cbuf->high_water )            cbuf->low_water = cbuf->high_water;# endif#endif        cyg_drv_mutex_init(&cbuf->lock);        cyg_drv_cond_init(&cbuf->wait, &cbuf->lock);    }#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS    chan->status_callback = NULL;#endif#ifdef CYGDBG_USE_ASSERTS#if CYGINT_IO_SERIAL_BLOCK_TRANSFER    chan->in_cbuf.block_mode_xfer_running = false;    chan->out_cbuf.block_mode_xfer_running = false;#endif // CYGINT_IO_SERIAL_BLOCK_TRANSFER#endif // CYGDBG_USE_ASSERTS    chan->init = true;}// ---------------------------------------------------------------------------// FIXME:@@@ Throughout this file there are uses of cyg_drv_cond_signal and// cyg_drv_cond_broadcast. Does it matter which? -Jiflstatic Cyg_ErrNo serial_write(cyg_io_handle_t handle, const void *_buf, cyg_uint32 *len){    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;    serial_channel *chan = (serial_channel *)t->priv;    serial_funs *funs = chan->funs;    cyg_int32 size = *len;    cyg_uint8 *buf = (cyg_uint8 *)_buf;    int next;    cbuf_t *cbuf = &chan->out_cbuf;    Cyg_ErrNo res = ENOERR;    cyg_drv_mutex_lock(&cbuf->lock);    cbuf->abort = false;    if (cbuf->len == 0) {        // Non interrupt driven (i.e. polled) operation        while (size-- > 0) {#ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL            while ( ( 0 == (chan->flow_desc.flags & CYG_SERIAL_FLOW_OUT_THROTTLED) ) &&                    ((funs->putc)(chan, *buf) == false) )                 ;  // Ignore full, keep trying#else            while ((funs->putc)(chan, *buf) == false)                 ;  // Ignore full, keep trying#endif            buf++;        }    } else {        cyg_drv_dsr_lock();  // Avoid race condition testing pointers        while (size > 0) {                   next = cbuf->put + 1;            if (next == cbuf->len) next = 0;            if (cbuf->nb == cbuf->len) {                cbuf->waiting = true;                // Buffer full - wait for space#ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL                if ( 0 == (chan->flow_desc.flags & CYG_SERIAL_FLOW_OUT_THROTTLED) )#endif                    (funs->start_xmit)(chan);  // Make sure xmit is running                // Check flag: 'start_xmit' may have obviated the need                // to wait :-)                if (cbuf->waiting) {#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING                    // Optionally return if configured for non-blocking mode.                    if (!cbuf->blocking) {                        *len -= size;   // number of characters actually sent                        cbuf->waiting = false;                        res = -EAGAIN;                        break;                    }#endif // CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING                    cbuf->pending += size;  // Have this much more to send [eventually]                    if( !cyg_drv_cond_wait(&cbuf->wait) )                        cbuf->abort = true;                    cbuf->pending -= size;                }                if (cbuf->abort) {                    // Give up!                    *len -= size;   // number of characters actually sent                    cbuf->abort = false;                    cbuf->waiting = false;                    res = -EINTR;                    break;                }            } else {                cbuf->data[cbuf->put++] = *buf++;                cbuf->put = next;                cbuf->nb++;                size--;  // Only count if actually sent!            }        }#ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL        if ( 0 == (chan->flow_desc.flags & CYG_SERIAL_FLOW_OUT_THROTTLED) )#endif            (funs->start_xmit)(chan);  // Start output as necessary        cyg_drv_dsr_unlock();    }    cyg_drv_mutex_unlock(&cbuf->lock);    return res;}// ---------------------------------------------------------------------------static Cyg_ErrNo serial_read(cyg_io_handle_t handle, void *_buf, cyg_uint32 *len){    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;    serial_channel *chan = (serial_channel *)t->priv;    serial_funs *funs = chan->funs;    cyg_uint8 *buf = (cyg_uint8 *)_buf;    cyg_int32 size = 0;    cbuf_t *cbuf = &chan->in_cbuf;    Cyg_ErrNo res = ENOERR;#ifdef XX_CYGDBG_DIAG_BUF            extern int enable_diag_uart;            int _enable = enable_diag_uart;            int _time, _stime;            externC cyg_tick_count_t cyg_current_time(void);#endif // CYGDBG_DIAG_BUF

⌨️ 快捷键说明

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