📄 ser_16x5x.c
字号:
cyg_drv_interrupt_unmask(ser_chan->int_num); } serial_config_port(chan, &chan->config, true); return true;}// This routine is called when the device is "looked" up (i.e. attached)static Cyg_ErrNo pc_serial_lookup(struct cyg_devtab_entry **tab, struct cyg_devtab_entry *sub_tab, const char *name){ serial_channel *chan = (serial_channel *)(*tab)->priv; // Really only required for interrupt driven devices (chan->callbacks->serial_init)(chan); return ENOERR;}// Send a character to the device output buffer.// Return 'true' if character is sent to devicestatic boolpc_serial_putc(serial_channel *chan, unsigned char c){ cyg_uint8 _lsr; pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv; cyg_addrword_t base = ser_chan->base; HAL_READ_UINT8(base+REG_lsr, _lsr); if (_lsr & LSR_THE) {// Transmit buffer is empty HAL_WRITE_UINT8(base+REG_thr, c); return true; } else {// No space return false; }}// Fetch a character from the device input buffer, waiting if necessarystatic unsigned char pc_serial_getc(serial_channel *chan){ unsigned char c; cyg_uint8 _lsr; pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv; cyg_addrword_t base = ser_chan->base; // Wait for char do { HAL_READ_UINT8(base+REG_lsr, _lsr); } while ((_lsr & LSR_RSR) == 0); HAL_READ_UINT8(base+REG_rhr, c); return c;}// Set up the device characteristics; baud rate, etc.static Cyg_ErrNopc_serial_set_config(serial_channel *chan, cyg_uint32 key, const void *xbuf, cyg_uint32 *len){ switch (key) { case CYG_IO_SET_CONFIG_SERIAL_INFO: { cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf; if ( *len < sizeof(cyg_serial_info_t) ) { return -EINVAL; } *len = sizeof(cyg_serial_info_t); if ( true != serial_config_port(chan, config, false) ) return -EINVAL; } break;#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW case CYG_IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE: { cyg_uint8 _mcr; pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv; cyg_addrword_t base = ser_chan->base; cyg_uint8 *f = (cyg_uint8 *)xbuf; unsigned char mask=0; if ( *len < *f ) return -EINVAL; if ( chan->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_RX ) mask = MCR_RTS; if ( chan->config.flags & CYGNUM_SERIAL_FLOW_DSRDTR_RX ) mask |= MCR_DTR; HAL_READ_UINT8(base+REG_mcr, _mcr); if (*f) // we should throttle _mcr &= ~mask; else // we should no longer throttle _mcr |= mask; HAL_WRITE_UINT8(base+REG_mcr, _mcr); } break; case CYG_IO_SET_CONFIG_SERIAL_HW_FLOW_CONFIG: // Nothing to do because we do support both RTSCTS and DSRDTR flow // control. // Other targets would clear any unsupported flags here. // We just return ENOERR. break;#endif default: return -EINVAL; } return ENOERR;}// Enable the transmitter on the devicestatic voidpc_serial_start_xmit(serial_channel *chan){ pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv; cyg_addrword_t base = ser_chan->base; cyg_uint8 _ier; HAL_READ_UINT8(base+REG_ier, _ier); _ier |= IER_XMT; // Enable xmit interrupt HAL_WRITE_UINT8(base+REG_ier, _ier);}// Disable the transmitter on the devicestatic void pc_serial_stop_xmit(serial_channel *chan){ pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv; cyg_addrword_t base = ser_chan->base; cyg_uint8 _ier; HAL_READ_UINT8(base+REG_ier, _ier); _ier &= ~IER_XMT; // Disable xmit interrupt HAL_WRITE_UINT8(base+REG_ier, _ier);}// Serial I/O - low level interrupt handler (ISR)static cyg_uint32 pc_serial_ISR(cyg_vector_t vector, cyg_addrword_t data){ serial_channel *chan = (serial_channel *)data; pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv; cyg_drv_interrupt_mask(ser_chan->int_num); cyg_drv_interrupt_acknowledge(ser_chan->int_num); return CYG_ISR_CALL_DSR; // Cause DSR to be run}// Serial I/O - high level interrupt handler (DSR)static void pc_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data){ serial_channel *chan = (serial_channel *)data; pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv; cyg_addrword_t base = ser_chan->base; cyg_uint8 _isr; // Check if we have an interrupt pending - note that the interrupt // is pending of the low bit of the isr is *0*, not 1. HAL_READ_UINT8(base+REG_isr, _isr); while ((_isr & ISR_nIP) == 0) { switch (_isr&0x6) { case ISR_Rx: { cyg_uint8 _lsr; unsigned char c; HAL_READ_UINT8(base+REG_lsr, _lsr); while(_lsr & LSR_RSR) { HAL_READ_UINT8(base+REG_rhr, c); (chan->callbacks->rcv_char)(chan, c); HAL_READ_UINT8(base+REG_lsr, _lsr); } break; } case ISR_Tx: (chan->callbacks->xmt_char)(chan); break;#ifdef CYGOPT_IO_SERIAL_SUPPORT_LINE_STATUS case ISR_LS: { cyg_serial_line_status_t stat; cyg_uint8 _lsr; HAL_READ_UINT8(base+REG_lsr, _lsr); // this might look expensive, but it is rarely the case that // more than one of these is set stat.value = 1; if ( _lsr & LSR_OE ) { stat.which = CYGNUM_SERIAL_STATUS_OVERRUNERR; (chan->callbacks->indicate_status)(chan, &stat ); } if ( _lsr & LSR_PE ) { stat.which = CYGNUM_SERIAL_STATUS_PARITYERR; (chan->callbacks->indicate_status)(chan, &stat ); } if ( _lsr & LSR_FE ) { stat.which = CYGNUM_SERIAL_STATUS_FRAMEERR; (chan->callbacks->indicate_status)(chan, &stat ); } if ( _lsr & LSR_BI ) { stat.which = CYGNUM_SERIAL_STATUS_BREAK; (chan->callbacks->indicate_status)(chan, &stat ); } } break; case ISR_MS: { cyg_serial_line_status_t stat; cyg_uint8 _msr; HAL_READ_UINT8(base+REG_msr, _msr);#ifdef CYGOPT_IO_SERIAL_FLOW_CONTROL_HW if ( _msr & MSR_DDSR ) if ( chan->config.flags & CYGNUM_SERIAL_FLOW_DSRDTR_TX ) { stat.which = CYGNUM_SERIAL_STATUS_FLOW; stat.value = (0 != (_msr & MSR_DSR)); (chan->callbacks->indicate_status)(chan, &stat ); } if ( _msr & MSR_DCTS ) if ( chan->config.flags & CYGNUM_SERIAL_FLOW_RTSCTS_TX ) { stat.which = CYGNUM_SERIAL_STATUS_FLOW; stat.value = (0 != (_msr & MSR_CTS)); (chan->callbacks->indicate_status)(chan, &stat ); }#endif if ( _msr & MSR_DDCD ) { stat.which = CYGNUM_SERIAL_STATUS_CARRIERDETECT; stat.value = (0 != (_msr & MSR_CD)); (chan->callbacks->indicate_status)(chan, &stat ); } if ( _msr & MSR_RI ) { stat.which = CYGNUM_SERIAL_STATUS_RINGINDICATOR; stat.value = 1; (chan->callbacks->indicate_status)(chan, &stat ); } if ( _msr & MSR_TERI ) { stat.which = CYGNUM_SERIAL_STATUS_RINGINDICATOR; stat.value = 0; (chan->callbacks->indicate_status)(chan, &stat ); } } break;#endif } HAL_READ_UINT8(base+REG_isr, _isr); } // while cyg_drv_interrupt_unmask(ser_chan->int_num);}#endif// EOF ser_16x5x.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -