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

📄 serial.c

📁 eCos操作系统源码
💻 C
📖 第 1 页 / 共 3 页
字号:
            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    cyg_drv_mutex_lock(&cbuf->lock);    cbuf->abort = false;    if (cbuf->len == 0) {        // Non interrupt driven (i.e. polled) operation        while (size++ < *len) {            cyg_uint8 c = (funs->getc)(chan);#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_SOFTWARE            // for software flow control, if the driver returns one of the            // characters we act on it and then drop it (the app must not            // see it)            if ( chan->config.flags & CYGNUM_SERIAL_FLOW_XONXOFF_TX ) {                if ( c == CYGDAT_IO_SERIAL_FLOW_CONTROL_XOFF_CHAR ) {                    throttle_tx( chan );                } else if ( c == CYGDAT_IO_SERIAL_FLOW_CONTROL_XON_CHAR ) {                    restart_tx( chan );                }                else                    *buf++ = c;            }            else                *buf++ = c;#else            *buf++ = c;#endif            }    } else {        cyg_drv_dsr_lock();  // Avoid races        while (size < *len) {            if (cbuf->nb > 0) {#ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL                if ( (cbuf->nb <= cbuf->low_water) &&                      (chan->flow_desc.flags & CYG_SERIAL_FLOW_IN_THROTTLED) )                    restart_rx( chan, false );#endif                *buf++ = cbuf->data[cbuf->get];                if (++cbuf->get == cbuf->len) cbuf->get = 0;                cbuf->nb--;                size++;            } else {#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING                if (!cbuf->blocking) {                    *len = size;        // characters actually read                    res = size == 0 ? -EAGAIN : ENOERR;                    break;                }#endif // CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING                cbuf->waiting = true;#ifdef XX_CYGDBG_DIAG_BUF                enable_diag_uart = 0;                HAL_CLOCK_READ(&_time);                _stime = (int)cyg_current_time();                diag_printf("READ wait - get: %d, put: %d, time: %x.%x\n", cbuf->get, cbuf->put, _stime, _time);                enable_diag_uart = _enable;#endif // CYGDBG_DIAG_BUF                if( !cyg_drv_cond_wait(&cbuf->wait) )                    cbuf->abort = true;#ifdef XX_CYGDBG_DIAG_BUF                enable_diag_uart = 0;                HAL_CLOCK_READ(&_time);                _stime = (int)cyg_current_time();                diag_printf("READ continue - get: %d, put: %d, time: %x.%x\n", cbuf->get, cbuf->put, _stime, _time);                enable_diag_uart = _enable;#endif // CYGDBG_DIAG_BUF                if (cbuf->abort) {                    // Give up!                    *len = size;        // characters actually read                    cbuf->abort = false;                    cbuf->waiting = false;                    res = -EINTR;                    break;                }            }        }        cyg_drv_dsr_unlock();    }#ifdef XX_CYGDBG_DIAG_BUF    cyg_drv_isr_lock();    enable_diag_uart = 0;    HAL_CLOCK_READ(&_time);    _stime = (int)cyg_current_time();    diag_printf("READ done - size: %d, len: %d, time: %x.%x\n", size, *len, _stime, _time);    enable_diag_uart = _enable;    cyg_drv_isr_unlock();#endif // CYGDBG_DIAG_BUF    cyg_drv_mutex_unlock(&cbuf->lock);    return res;}// ---------------------------------------------------------------------------static cyg_boolserial_select(cyg_io_handle_t handle, cyg_uint32 which, CYG_ADDRWORD info){#ifdef CYGPKG_IO_SERIAL_SELECT_SUPPORT    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;    serial_channel *chan = (serial_channel *)t->priv;        switch( which )    {    case CYG_FREAD:        {            cbuf_t *cbuf = &chan->in_cbuf;            // Check for data in the input buffer. If there is none,            // register the select operation, otherwise return true.            if( cbuf->nb == 0 )                cyg_selrecord( info, &cbuf->selinfo );            else return true;        }        break;            case CYG_FWRITE:        {            // Check for space in the output buffer. If there is none,            // register the select operation, otherwise return true.            cbuf_t *cbuf = &chan->out_cbuf;            int space = cbuf->len - cbuf->nb;#ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL            if ( (space < cbuf->low_water) ||                 (chan->flow_desc.flags & CYG_SERIAL_FLOW_OUT_THROTTLED) )                cyg_selrecord( info, &cbuf->selinfo );#else            if (space < cbuf->low_water)                cyg_selrecord( info, &cbuf->selinfo );#endif            else return true;        }        break;    case 0: // exceptions - none supported        break;    }    return false;#else    // With no select support, we simply return true.    return true;#endif    }// ---------------------------------------------------------------------------static Cyg_ErrNo serial_get_config(cyg_io_handle_t handle, cyg_uint32 key, void *xbuf,                  cyg_uint32 *len){    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;    serial_channel *chan = (serial_channel *)t->priv;    cyg_serial_info_t *buf = (cyg_serial_info_t *)xbuf;    Cyg_ErrNo res = ENOERR;    cbuf_t *out_cbuf = &chan->out_cbuf;    cbuf_t *in_cbuf = &chan->in_cbuf;    serial_funs *funs = chan->funs;    switch (key) {    case CYG_IO_GET_CONFIG_SERIAL_INFO:        if (*len < sizeof(cyg_serial_info_t)) {            return -EINVAL;        }        *buf = chan->config;        *len = sizeof(chan->config);        break;           case CYG_IO_GET_CONFIG_SERIAL_BUFFER_INFO:        // return rx/tx buffer sizes and counts        {            cyg_serial_buf_info_t *p;            if (*len < sizeof(cyg_serial_buf_info_t))                return -EINVAL;                      *len = sizeof(cyg_serial_buf_info_t);            p = (cyg_serial_buf_info_t *)xbuf;                        p->rx_bufsize = in_cbuf->len;            if (p->rx_bufsize)                p->rx_count = in_cbuf->nb;            else                p->rx_count = 0;                        p->tx_bufsize = out_cbuf->len;            if (p->tx_bufsize)                p->tx_count = out_cbuf->nb;            else                p->tx_count = 0;        }      break;          case CYG_IO_GET_CONFIG_SERIAL_OUTPUT_DRAIN:// Wait for any pending output to complete        if (out_cbuf->len == 0) break;  // Nothing to do if not buffered        cyg_drv_mutex_lock(&out_cbuf->lock);  // Stop any further output processing        cyg_drv_dsr_lock();        while (out_cbuf->pending || (out_cbuf->nb > 0)) {            out_cbuf->waiting = true;            if(!cyg_drv_cond_wait(&out_cbuf->wait) )                res = -EINTR;        }        cyg_drv_dsr_unlock();        cyg_drv_mutex_unlock(&out_cbuf->lock);        break;    case CYG_IO_GET_CONFIG_SERIAL_INPUT_FLUSH:        // Flush any buffered input        if (in_cbuf->len == 0) break;  // Nothing to do if not buffered        cyg_drv_mutex_lock(&in_cbuf->lock);  // Stop any further input processing        cyg_drv_dsr_lock();        if (in_cbuf->waiting) {            in_cbuf->abort = true;            cyg_drv_cond_broadcast(&in_cbuf->wait);            in_cbuf->waiting = false;        }        in_cbuf->get = in_cbuf->put = in_cbuf->nb = 0;  // Flush buffered input        // Pass to the hardware driver in case it wants to flush FIFOs etc.        (funs->set_config)(chan,                           CYG_IO_SET_CONFIG_SERIAL_INPUT_FLUSH,                           NULL, NULL);        cyg_drv_dsr_unlock();        cyg_drv_mutex_unlock(&in_cbuf->lock);#ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL        // Restart receiver if it was shutdown        if ((chan->flow_desc.flags & CYG_SERIAL_FLOW_IN_THROTTLED) != 0) {            restart_rx( chan, false );        }#endif        break;    case CYG_IO_GET_CONFIG_SERIAL_ABORT:        // Abort any outstanding I/O, including blocked reads        // Caution - assumed to be called from 'timeout' (i.e. DSR) code        if (in_cbuf->len != 0) {            in_cbuf->abort = true;            cyg_drv_cond_broadcast(&in_cbuf->wait);        }        if (out_cbuf->len != 0) {            out_cbuf->abort = true;            cyg_drv_cond_broadcast(&out_cbuf->wait);        }        break;    case CYG_IO_GET_CONFIG_SERIAL_OUTPUT_FLUSH:// Throw away any pending output        if (out_cbuf->len == 0) break;  // Nothing to do if not buffered        cyg_drv_mutex_lock(&out_cbuf->lock);  // Stop any further output processing        cyg_drv_dsr_lock();        if (out_cbuf->nb > 0) {            out_cbuf->get = out_cbuf->put = out_cbuf->nb = 0;  // Empties queue!            (funs->stop_xmit)(chan);  // Done with transmit        }        // Pass to the hardware driver in case it wants to flush FIFOs etc.        (funs->set_config)(chan,                           CYG_IO_SET_CONFIG_SERIAL_OUTPUT_FLUSH,                           NULL, NULL);        if (out_cbuf->waiting) {            out_cbuf->abort = true;            cyg_drv_cond_broadcast(&out_cbuf->wait);            out_cbuf->waiting = false;        }        cyg_drv_dsr_unlock();        cyg_drv_mutex_unlock(&out_cbuf->lock);        break;#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING    case CYG_IO_GET_CONFIG_READ_BLOCKING:        if (*len < sizeof(cyg_uint32)) {            return -EINVAL;        }        *(cyg_uint32*)xbuf = (in_cbuf->blocking) ? 1 : 0;        break;    case CYG_IO_GET_CONFIG_WRITE_BLOCKING:        if (*len < sizeof(cyg_uint32)) {            return -EINVAL;        }        *(cyg_uint32*)xbuf = (out_cbuf->blocking) ? 1 : 0;        break;#endif // CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING    default:        res = -EINVAL;    }    return res;}// ---------------------------------------------------------------------------static Cyg_ErrNo serial_set_config(cyg_io_handle_t handle, cyg_uint32 key, const void *xbuf,                   cyg_uint32 *len){    Cyg_ErrNo res = ENOERR;    cyg_devtab_entry_t *t = (cyg_devtab_entry_t *)handle;    serial_channel *chan = (serial_channel *)t->priv;#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING    cbuf_t *out_cbuf = &chan->out_cbuf;    cbuf_t *in_cbuf = &chan->in_cbuf;#endif    serial_funs *funs = chan->funs;    switch (key) {#ifdef CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING    case CYG_IO_SET_CONFIG_READ_BLOCKING:        if (*len < sizeof(cyg_uint32) || 0 == in_cbuf->len) {            return -EINVAL;        }        in_cbuf->blocking = (1 == *(cyg_uint32*)xbuf) ? true : false;        break;    case CYG_IO_SET_CONFIG_WRITE_BLOCKING:        if (*len < sizeof(cyg_uint32) || 0 == out_cbuf->len) {            return -EINVAL;        }        out_cbuf->blocking = (1 == *(cyg_uint32*)xbuf) ? true : false;        break;#endif // CYGOPT_IO_SERIAL_SUPPORT_NONBLOCKING#ifdef CYGPKG_IO_SERIAL_FLOW_CONTROL    case CYG_IO_SET_CONFIG_SERIAL_FLOW_CONTROL_METHOD:        {            cyg_uint32 *f = (cyg_uint32 *)xbuf;            if (*len < sizeof(*f))                return -EINVAL;            cyg_drv_dsr_lock();            chan->config.flags &= ~(CYGNUM_SERIAL_FLOW_XONXOFF_RX|                                    CYGNUM_SERIAL_FLOW_XONXOFF_TX|                                    CYGNUM_SERIAL_FLOW_RTSCTS_RX|                                    CYGNUM_SERIAL_FLOW_RTSCTS_TX|                                    CYGNUM_SERIAL_FLOW_DSRDTR_RX|                                    CYGNUM_SERIAL_FLOW_DSRDTR_TX);            chan->config.flags |= (*f & (#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_SOFTWARE                CYGNUM_SERIAL_FLOW_XONXOFF_RX|                CYGNUM_SERIAL_FLOW_XONXOFF_TX|#endif#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW                CYGNUM_SERIAL_FLOW_RTSCTS_RX|                CYGNUM_SERIAL_FLOW_RTSCTS_TX|                CYGNUM_SERIAL_FLOW_DSRDTR_RX|                CYGNUM_SERIAL_FLOW_DSRDTR_TX|#endif                0));#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW            // up to hardware driver to clear flags if rejected            res = (funs->set_config)(chan,                                     CYG_IO_SET_CONFIG_SERIAL_HW_FLOW_CONFIG,                                     NULL, NULL);#endif            cyg_drv_dsr_unlock();        }        break;    case CYG_IO_SET_CONFIG_SERIAL_FLOW_CONTROL_FORCE:        {            cyg_uint32 *f = (cyg_uint32 *)xbuf;            if (*len < sizeof(*f))                return -EINVAL;                        cyg_drv_dsr_lock();            switch (*f) {            case CYGNUM_SERIAL_FLOW_THROTTLE_RX:                throttle_rx( chan, true );                break;            case CYGNUM_SERIAL_FLOW_RESTART_RX:                restart_rx( chan, true );                break;            case CYGNUM_SERIAL_FLOW_THROTTLE_TX:                throttle_tx( chan );                break;            case CYGNUM_SERIAL_FLOW_RESTART_TX:                restart_tx( chan );                break;            default:                res = -EINVAL;                break;            }            cyg_drv_dsr_unlock();        }        break;#endif // CYGPKG_IO_SERIAL_FLOW_CONTROL#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS    case CYG_IO_SET_CONFIG_SERIAL_STATUS_CALLBACK:        {            cyg_serial_line_status_callback_fn_t newfn;            CYG_ADDRWORD newpriv;            cyg_serial_line_status_callback_t *tmp =                 (cyg_serial_line_status_callback_t *)xbuf;

⌨️ 快捷键说明

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