📄 tx3904_serial.c
字号:
n *= 11; // allow for start and stop bits and 8 data bits while( n-- ) { cyg_count32 i,j,k; for( i = 0; i < clock_loop; i++ ) for( j = 0; j < div_loop; j++ ) for( k = 0; k < bit_time; k++ ) continue; }}//-------------------------------------------------------------------------static booltx3904_serial_config_port(serial_channel *chan, cyg_serial_info_t *new_config, bool init){ tx3904_serial_info *tx3904_chan = (tx3904_serial_info *)chan->dev_priv; cyg_uint16 cr = 0; cyg_uint16 icr = 0; cyg_uint16 baud_divisor = select_baud[new_config->baud]; if (baud_divisor == 0) return false; // Invalid baud rate selected // 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]; // Source transfer clock from BRG cr |= LCR_BRG;#ifndef CYGPKG_IO_SERIAL_TX39_JMR3904_POLLED_MODE // Enable RX interrupts only at present#ifdef CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL0 if ((chan->out_cbuf.len != 0) || (chan == &tx3904_serial_channel0)) {#else if (chan->out_cbuf.len != 0) {#endif icr |= ICR_RXE; }#endif // Avoid any interrupts while we are fiddling with the line parameters. cyg_drv_interrupt_mask(tx3904_chan->int_num); // In theory we should wait here for the transmitter to drain the // FIFO so we dont change the line parameters with characters // unsent. Unfortunately the TX39 serial devices do not allow us // to discover when the FIFO is empty. delay_char_time(tx3904_chan, 8); // Disable device entirely.// HAL_WRITE_UINT16(tx3904_chan->base+SERIAL_CR, 0);// HAL_WRITE_UINT8(tx3904_chan->base+SERIAL_ICR, 0); // Reset the FIFOs HAL_WRITE_UINT16(tx3904_chan->base+SERIAL_FCR, 7); HAL_WRITE_UINT16(tx3904_chan->base+SERIAL_FCR, 0); // Set up baud rate HAL_WRITE_UINT16( tx3904_chan->base+SERIAL_BRG, baud_divisor ); // Write CR into hardware HAL_WRITE_UINT16(tx3904_chan->base+SERIAL_CR, cr); // Write ICR into hardware HAL_WRITE_UINT16(tx3904_chan->base+SERIAL_ICR, icr); // Re-enable interrupts. cyg_drv_interrupt_unmask(tx3904_chan->int_num); // Save current baud rate tx3904_chan->cur_baud = new_config->baud; if (new_config != &chan->config) { chan->config = *new_config; } return true;}//-------------------------------------------------------------------------// Function to initialize the device. Called at bootstrap time.bool tx3904_serial_init(struct cyg_devtab_entry *tab){ serial_channel *chan = (serial_channel *)tab->priv; tx3904_serial_info *tx3904_chan = (tx3904_serial_info *)chan->dev_priv; (chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices tx3904_chan->cur_baud = CYGNUM_SERIAL_BAUD_38400; #ifndef CYGPKG_IO_SERIAL_TX39_JMR3904_POLLED_MODE if (chan->out_cbuf.len != 0) { // Install and enable the interrupt cyg_drv_interrupt_create(tx3904_chan->int_num, 4, // Priority (cyg_addrword_t)chan, // Data item passed to interrupt handler (cyg_ISR_t *)tx3904_serial_ISR, tx3904_serial_DSR, &tx3904_chan->interrupt_handle, &tx3904_chan->interrupt); cyg_drv_interrupt_attach(tx3904_chan->interrupt_handle); cyg_drv_interrupt_unmask(tx3904_chan->int_num); }#endif tx3904_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 tx3904_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 devicebooltx3904_serial_putc(serial_channel *chan, unsigned char c){ tx3904_serial_info *tx3904_chan = (tx3904_serial_info *)chan->dev_priv; cyg_uint16 isr; HAL_READ_UINT16( tx3904_chan->base+SERIAL_ISR, isr ); if( isr & ISR_TXRDY ) { HAL_WRITE_UINT8( tx3904_chan->base+SERIAL_TXB, c ); isr &= ~ISR_TXRDY; HAL_WRITE_UINT16( tx3904_chan->base+SERIAL_ISR, isr ); return true; } else return false;}//-------------------------------------------------------------------------unsigned char tx3904_serial_getc(serial_channel *chan){ unsigned char c; tx3904_serial_info *tx3904_chan = (tx3904_serial_info *)chan->dev_priv; cyg_uint16 isr; do { HAL_READ_UINT16( tx3904_chan->base+SERIAL_ISR, isr ); // Eliminate any RX errors if( isr & ISR_ERROR ) { cyg_uint16 sr = 0; isr &= ISR_ERROR;// HAL_READ_UINT16( tx3904_chan->base+SERIAL_SR, sr ); HAL_WRITE_UINT16( tx3904_chan->base+SERIAL_SR, sr ); HAL_WRITE_UINT16( tx3904_chan->base+SERIAL_ISR, isr ); } } while( (isr & ISR_RXRDY) != ISR_RXRDY ); HAL_READ_UINT8( tx3904_chan->base+SERIAL_RXB, c ); isr &= ~ISR_RXRDY; HAL_WRITE_UINT16( tx3904_chan->base+SERIAL_ISR, isr ); return c;}//-------------------------------------------------------------------------bool tx3904_serial_set_config(serial_channel *chan, cyg_serial_info_t *config){ return tx3904_serial_config_port(chan, config, false);}//-------------------------------------------------------------------------// Enable the transmitter on the devicestatic voidtx3904_serial_start_xmit(serial_channel *chan){#ifndef CYGPKG_IO_SERIAL_TX39_JMR3904_POLLED_MODE tx3904_serial_info *tx3904_chan = (tx3904_serial_info *)chan->dev_priv; cyg_uint16 icr; HAL_READ_UINT16( tx3904_chan->base+SERIAL_ICR, icr ); icr |= ICR_TXE; HAL_WRITE_UINT16( tx3904_chan->base+SERIAL_ICR, icr );#endif }//-------------------------------------------------------------------------// Disable the transmitter on the devicestatic void tx3904_serial_stop_xmit(serial_channel *chan){#ifndef CYGPKG_IO_SERIAL_TX39_JMR3904_POLLED_MODE tx3904_serial_info *tx3904_chan = (tx3904_serial_info *)chan->dev_priv; cyg_uint16 icr; HAL_READ_UINT16( tx3904_chan->base+SERIAL_ICR, icr ); icr &= ~ICR_TXE; HAL_WRITE_UINT16( tx3904_chan->base+SERIAL_ICR, icr );#endif }//-------------------------------------------------------------------------// Serial I/O - low level interrupt handlers (ISR)#ifndef CYGPKG_IO_SERIAL_TX39_JMR3904_POLLED_MODEstatic cyg_uint32 tx3904_serial_ISR(cyg_vector_t vector, cyg_addrword_t data, cyg_addrword_t *regs){ serial_channel *chan = (serial_channel *)data; tx3904_serial_info *tx3904_chan = (tx3904_serial_info *)chan->dev_priv; cyg_uint8 isr; cyg_uint32 result = 0; cyg_drv_interrupt_mask(tx3904_chan->int_num); cyg_drv_interrupt_acknowledge(tx3904_chan->int_num); HAL_READ_UINT16( tx3904_chan->base+SERIAL_ISR, isr ); // Eliminate any RX errors if( isr & ISR_ERROR ) { cyg_uint16 sr = 0; isr &= ~ISR_ERROR; HAL_READ_UINT16( tx3904_chan->base+SERIAL_SR, sr ); HAL_WRITE_UINT16( tx3904_chan->base+SERIAL_SR, 0 ); } // Check for a TX interrupt and set the flag if so. if( isr & ISR_TXRDY ) { isr &= ~ISR_TXRDY; tx3904_chan->output_ready = true; result |= CYG_ISR_CALL_DSR; // Cause DSR to be run } // Check here for an RX interrupt and fetch the character. If it // is a ^C then call into GDB stub to handle it. if( isr & ISR_RXRDY ) { cyg_uint8 rxb; HAL_READ_UINT8( tx3904_chan->base+SERIAL_RXB, rxb ); isr &= ~ISR_RXRDY; if( cyg_hal_is_break( &rxb , 1 ) ) cyg_hal_user_break( regs ); else { tx3904_chan->input_char = rxb; tx3904_chan->input_char_valid = true; result |= CYG_ISR_CALL_DSR; // Cause DSR to be run } } HAL_WRITE_UINT16( tx3904_chan->base+SERIAL_ISR, isr ); return result;}#endif//-------------------------------------------------------------------------// Serial I/O - high level interrupt handler (DSR)#ifndef CYGPKG_IO_SERIAL_TX39_JMR3904_POLLED_MODEstatic void tx3904_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data){ serial_channel *chan = (serial_channel *)data; tx3904_serial_info *tx3904_chan = (tx3904_serial_info *)chan->dev_priv; cyg_uint8 isr; HAL_READ_UINT16( tx3904_chan->base+SERIAL_ISR, isr ); if( tx3904_chan->input_char_valid ) { (chan->callbacks->rcv_char)(chan, tx3904_chan->input_char); tx3904_chan->input_char_valid = false;#if 0 // And while we are here, pull any further characters out of the // FIFO. This should help to reduce the interrupt rate. HAL_READ_UINT16( tx3904_chan->base+SERIAL_ISR, isr ); while( isr & ISR_RXRDY ) { cyg_uint8 rxb; HAL_READ_UINT8( tx3904_chan->base+SERIAL_RXB, rxb ); (chan->callbacks->rcv_char)(chan, rxb); isr &= ~ISR_RXRDY; HAL_WRITE_UINT16( tx3904_chan->base+SERIAL_ISR, isr ); HAL_READ_UINT16( tx3904_chan->base+SERIAL_ISR, isr ); }#endif } if( tx3904_chan->output_ready ) { (chan->callbacks->xmt_char)(chan); tx3904_chan->output_ready = false; } cyg_drv_interrupt_unmask(tx3904_chan->int_num);}#endif#endif // CYGPKG_IO_SERIAL_TX39_JMR3904//-------------------------------------------------------------------------// EOF tx3904_serial.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -