📄 mn10300_serial.c
字号:
// And finally, the device table entries:#ifndef CYG_HAL_MN10300_STDEVAL1#ifdef CYGPKG_IO_SERIAL_MN10300_SERIAL0// On the standard eval board serial0 is not connected. If enabled, it// generates continuous frame error and overrun interrupts. Hence we do// not touch it.DEVTAB_ENTRY(mn10300_serial_io0, CYGDAT_IO_SERIAL_MN10300_SERIAL0_NAME, 0, // Does not depend on a lower level interface &serial_devio, mn10300_serial_init, mn10300_serial_lookup, // Serial driver may need initializing &mn10300_serial_channel0 );#endif // CYGPKG_IO_SERIAL_MN10300_SERIAL0#endif#ifdef CYGPKG_IO_SERIAL_MN10300_SERIAL1DEVTAB_ENTRY(mn10300_serial_io1, CYGDAT_IO_SERIAL_MN10300_SERIAL1_NAME, 0, // Does not depend on a lower level interface &serial_devio, mn10300_serial_init, mn10300_serial_lookup, // Serial driver may need initializing &mn10300_serial_channel1 );#endif // CYGPKG_IO_SERIAL_MN10300_SERIAL1#ifdef CYGPKG_IO_SERIAL_MN10300_SERIAL2DEVTAB_ENTRY(mn10300_serial_io2, CYGDAT_IO_SERIAL_MN10300_SERIAL2_NAME, 0, // Does not depend on a lower level interface &serial_devio, mn10300_serial_init, mn10300_serial_lookup, // Serial driver may need initializing &mn10300_serial_channel2 );#endif // CYGPKG_IO_SERIAL_MN10300_SERIAL2//-------------------------------------------------------------------------// Read the serial line's status register. Serial 2 has an 8 bit status// register while serials 0 and 1 have 16 bit registers. This function// uses the correct size access, but passes back a 16 bit quantity for// both.static cyg_uint16 mn10300_read_sr( mn10300_serial_info *mn10300_chan ){ cyg_uint16 sr = 0; if( mn10300_chan->is_serial2 ) { cyg_uint8 sr8; HAL_READ_UINT8(mn10300_chan->base+SERIAL_STR, sr8); sr = sr8; } else { HAL_READ_UINT16(mn10300_chan->base+SERIAL_STR, sr); } return sr;}//-------------------------------------------------------------------------static boolmn10300_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init){ mn10300_serial_info *mn10300_chan = (mn10300_serial_info *)chan->dev_priv; cyg_uint16 cr = 0;#if defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) // If we are using CYGMON, do not reinitialize serial 2 at this // point, since it appears to upset GDB. if( mn10300_chan->is_serial2 ) return true;#endif // Disable device entirely. HAL_WRITE_UINT16(mn10300_chan->base+SERIAL_CTR, 0); HAL_WRITE_UINT8(mn10300_chan->base+SERIAL_ICR, 0); // Set up baud rate if( mn10300_chan->is_serial2 ) { // Serial 2 is a bit different from 0 and 1 in the way that the // baud rate is controlled. cyg_uint8 baud_divisor = select_baud_2[new_config->baud].timer2_val; if (baud_divisor == 0) return false; // Invalid baud rate selected HAL_WRITE_UINT8(mn10300_chan->timer_base+TIMER_BR, baud_divisor); HAL_WRITE_UINT8(mn10300_chan->timer_base+TIMER_MD, 0x80 ); baud_divisor = select_baud_2[new_config->baud].serial2_val; HAL_WRITE_UINT8(mn10300_chan->base+SERIAL_TIM, baud_divisor); cr |= 0x0001; // Source clock from timer 2 } else { cyg_uint8 baud_divisor = select_baud_01[new_config->baud]; if (baud_divisor == 0) return false; // Invalid baud rate selected HAL_WRITE_UINT8(mn10300_chan->timer_base+TIMER_BR, baud_divisor); HAL_WRITE_UINT8(mn10300_chan->timer_base+TIMER_MD, 0x80 ); cr |= 0x0004; // Source clock from timer 0 or 1 } HAL_WRITE_UINT8( PORT3_MD, 0x01 ); // set up other config values: cr |= select_word_length[new_config->word_length - CYGNUM_SERIAL_WORD_LENGTH_5]; cr |= select_stop_bits[new_config->stop]; cr |= select_parity[new_config->parity];#ifdef CYGPKG_IO_SERIAL_MN10300_POLLED_MODE // enable RX and TX cr |= LCR_RXE | LCR_TXE;#else // Enable RX only cr |= LCR_RXE;#endif // Write CR into hardware HAL_WRITE_UINT16(mn10300_chan->base+SERIAL_CTR, cr); mn10300_read_sr(mn10300_chan); if (new_config != &chan->config) { chan->config = *new_config; } return true;}//-------------------------------------------------------------------------// Function to initialize the device. Called at bootstrap time.bool mn10300_serial_init(struct cyg_devtab_entry *tab){ serial_channel *chan = (serial_channel *)tab->priv; mn10300_serial_info *mn10300_chan = (mn10300_serial_info *)chan->dev_priv;#if defined(CYG_HAL_USE_ROM_MONITOR_CYGMON) // If we are using CYGMON, do not reinitialize serial 2. If we do then we // will steal the receive interrupt and disable Ctrl-C handling. if( mn10300_chan->is_serial2 ) return true;#endif (chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices#ifndef CYGPKG_IO_SERIAL_MN10300_POLLED_MODE if (chan->out_cbuf.len != 0) { // Install and enable the receive interrupt cyg_drv_interrupt_create(mn10300_chan->rx_int, 4, // Priority - what goes here? (cyg_addrword_t)chan, // Data item passed to interrupt handler mn10300_serial_rx_ISR, mn10300_serial_rx_DSR, &mn10300_chan->rx_interrupt_handle, &mn10300_chan->rx_interrupt); cyg_drv_interrupt_attach(mn10300_chan->rx_interrupt_handle); cyg_drv_interrupt_unmask(mn10300_chan->rx_int); // Install and enable the transmit interrupt cyg_drv_interrupt_create(mn10300_chan->tx_int, 4, // Priority - what goes here? (cyg_addrword_t)chan, // Data item passed to interrupt handler mn10300_serial_tx_ISR, mn10300_serial_tx_DSR, &mn10300_chan->tx_interrupt_handle, &mn10300_chan->tx_interrupt); cyg_drv_interrupt_attach(mn10300_chan->tx_interrupt_handle); cyg_drv_interrupt_mask(mn10300_chan->tx_int); }#endif mn10300_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 mn10300_serial_lookup(struct cyg_devtab_entry **tab, struct cyg_devtab_entry *sub_tab, const char *name){ serial_channel *chan = (serial_channel *)(*tab)->priv; (chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices return ENOERR;}//-------------------------------------------------------------------------// Return 'true' if character is sent to deviceboolmn10300_serial_putc(serial_channel *chan, unsigned char c){ mn10300_serial_info *mn10300_chan = (mn10300_serial_info *)chan->dev_priv; cyg_uint8 sr = mn10300_read_sr( mn10300_chan); if( (sr & SR_TBF) == 0 ) { HAL_WRITE_UINT8( mn10300_chan->base+SERIAL_TXB, c ); return true; } else return false;}//-------------------------------------------------------------------------unsigned char mn10300_serial_getc(serial_channel *chan){ unsigned char c; mn10300_serial_info *mn10300_chan = (mn10300_serial_info *)chan->dev_priv; do { cyg_uint8 sr = mn10300_read_sr( mn10300_chan ); if( (sr & SR_RBF) != 0 ) { HAL_READ_UINT8( mn10300_chan->base+SERIAL_RXB, c ); break; } } while(1); return c;}//-------------------------------------------------------------------------bool mn10300_serial_set_config(serial_channel *chan, cyg_serial_info_t *config){ return mn10300_serial_config_port(chan, config, false);}//-------------------------------------------------------------------------// Enable the transmitter on the devicestatic voidmn10300_serial_start_xmit(serial_channel *chan){#ifndef CYGPKG_IO_SERIAL_MN10300_POLLED_MODE mn10300_serial_info *mn10300_chan = (mn10300_serial_info *)chan->dev_priv; cyg_uint16 cr; HAL_READ_UINT16( mn10300_chan->base+SERIAL_CTR, cr ); cr |= LCR_TXE; HAL_WRITE_UINT16( mn10300_chan->base+SERIAL_CTR, cr ); cyg_drv_interrupt_unmask(mn10300_chan->tx_int); (chan->callbacks->xmt_char)(chan);#endif }//-------------------------------------------------------------------------// Disable the transmitter on the devicestatic void mn10300_serial_stop_xmit(serial_channel *chan){#ifndef CYGPKG_IO_SERIAL_MN10300_POLLED_MODE mn10300_serial_info *mn10300_chan = (mn10300_serial_info *)chan->dev_priv; cyg_uint16 cr; cyg_uint16 sr; // Wait until the transmitter has actually stopped before turning it off. do { sr = mn10300_read_sr( mn10300_chan ); } while( sr & SR_TXF ); HAL_READ_UINT16( mn10300_chan->base+SERIAL_CTR, cr ); cr &= ~LCR_TXE; HAL_WRITE_UINT16( mn10300_chan->base+SERIAL_CTR, cr ); cyg_drv_interrupt_mask(mn10300_chan->tx_int); #endif }//-------------------------------------------------------------------------// Serial I/O - low level interrupt handlers (ISR)#ifndef CYGPKG_IO_SERIAL_MN10300_POLLED_MODEstatic cyg_uint32 mn10300_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data){ serial_channel *chan = (serial_channel *)data; mn10300_serial_info *mn10300_chan = (mn10300_serial_info *)chan->dev_priv; cyg_drv_interrupt_mask(mn10300_chan->rx_int); cyg_drv_interrupt_acknowledge(mn10300_chan->rx_int); return CYG_ISR_CALL_DSR; // Cause DSR to be run}static cyg_uint32 mn10300_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data){ serial_channel *chan = (serial_channel *)data; mn10300_serial_info *mn10300_chan = (mn10300_serial_info *)chan->dev_priv; cyg_drv_interrupt_mask(mn10300_chan->tx_int); cyg_drv_interrupt_acknowledge(mn10300_chan->tx_int); return CYG_ISR_CALL_DSR; // Cause DSR to be run}#endif//-------------------------------------------------------------------------// Serial I/O - high level interrupt handler (DSR)#ifndef CYGPKG_IO_SERIAL_MN10300_POLLED_MODEstatic void mn10300_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data){ serial_channel *chan = (serial_channel *)data; mn10300_serial_info *mn10300_chan = (mn10300_serial_info *)chan->dev_priv; cyg_uint8 sr = mn10300_read_sr( mn10300_chan); if( (sr & SR_RBF) != 0 ) { cyg_uint8 rxb; HAL_READ_UINT8( mn10300_chan->base+SERIAL_RXB, rxb ); (chan->callbacks->rcv_char)(chan, rxb); } cyg_drv_interrupt_unmask(mn10300_chan->rx_int);}static void mn10300_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data){ serial_channel *chan = (serial_channel *)data; mn10300_serial_info *mn10300_chan = (mn10300_serial_info *)chan->dev_priv; cyg_uint8 sr = mn10300_read_sr( mn10300_chan); if( (sr & SR_TBF) == 0 ) { (chan->callbacks->xmt_char)(chan); } cyg_drv_interrupt_unmask(mn10300_chan->tx_int);}#endif#endif // CYGPKG_IO_SERIAL_MN10300//-------------------------------------------------------------------------// EOF mn10300.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -