URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
[/] [openrisc/] [trunk/] [rtos/] [ecos-3.0/] [packages/] [devs/] [serial/] [mips/] [jmr3904/] [current/] [src/] [tx3904_serial.c] - Rev 786
Compare with Previous | Blame | View Log
//========================================================================== // // tx3904_serial.c // // Serial device driver for TX3904 on-chip serial devices // //========================================================================== // ####ECOSGPLCOPYRIGHTBEGIN#### // ------------------------------------------- // This file is part of eCos, the Embedded Configurable Operating System. // Copyright (C) 1998, 1999, 2000, 2001, 2002 Free Software Foundation, Inc. // // eCos is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 2 or (at your option) any later // version. // // eCos is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License // along with eCos; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // // As a special exception, if other files instantiate templates or use // macros or inline functions from this file, or you compile this file // and link it with other works to produce a work based on this file, // this file does not by itself cause the resulting work to be covered by // the GNU General Public License. However the source code for this file // must still be made available in accordance with section (3) of the GNU // General Public License v2. // // This exception does not invalidate any other reasons why a work based // on this file might be covered by the GNU General Public License. // ------------------------------------------- // ####ECOSGPLCOPYRIGHTEND#### //========================================================================== //#####DESCRIPTIONBEGIN#### // // Author(s): nickg // Contributors: nickg // Date: 1999-03-3 // Purpose: TX3904 serial device driver // Description: TX3904 serial device driver // //####DESCRIPTIONEND#### // //========================================================================== #include <pkgconf/hal.h> #include <pkgconf/io_serial.h> #include <cyg/hal/hal_io.h> #include <cyg/hal/hal_intr.h> #include <cyg/io/io.h> #include <cyg/io/devtab.h> #include <cyg/io/serial.h> #ifdef CYGPKG_IO_SERIAL_TX39_JMR3904 cyg_bool cyg_hal_is_break(char *buf, int size); void cyg_hal_user_break( CYG_ADDRWORD *regs ); //------------------------------------------------------------------------- extern void diag_printf(const char *fmt, ...); //------------------------------------------------------------------------- // Forward definitions static bool tx3904_serial_init(struct cyg_devtab_entry *tab); static bool tx3904_serial_putc(serial_channel *chan, unsigned char c); static Cyg_ErrNo tx3904_serial_lookup(struct cyg_devtab_entry **tab, struct cyg_devtab_entry *sub_tab, const char *name); static unsigned char tx3904_serial_getc(serial_channel *chan); static Cyg_ErrNo tx3904_serial_set_config(serial_channel *chan, cyg_uint32 key, const void *xbuf, cyg_uint32 *len); static void tx3904_serial_start_xmit(serial_channel *chan); static void tx3904_serial_stop_xmit(serial_channel *chan); #ifndef CYGPKG_IO_SERIAL_TX39_JMR3904_POLLED_MODE static cyg_uint32 tx3904_serial_ISR(cyg_vector_t vector, cyg_addrword_t data, cyg_addrword_t *regs); static void tx3904_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data); #endif //------------------------------------------------------------------------- // TX3904 serial line control register values: // Offsets to serial control registers from base #define SERIAL_CR 0x00 #define SERIAL_SR 0x04 #define SERIAL_ICR 0x08 #define SERIAL_ISR 0x0C #define SERIAL_FCR 0x10 #define SERIAL_BRG 0x14 #define SERIAL_TXB 0x20 #define SERIAL_RXB 0x30 // Status register bits #define ISR_RXRDY 0x01 #define ISR_TXRDY 0x02 #define ISR_ERROR 0x04 // Control register bits #define LCR_SB1 0x0000 #define LCR_SB1_5 0x0000 #define LCR_SB2 0x0004 #define LCR_PN 0x0000 // Parity mode - none #define LCR_PS 0x0000 // Forced "space" parity #define LCR_PM 0x0000 // Forced "mark" parity #define LCR_PE 0x0018 // Parity mode - even #define LCR_PO 0x0010 // Parity mode - odd #define LCR_WL5 0x0001 // not supported - use 7bit #define LCR_WL6 0x0001 // not supported - use 7bit #define LCR_WL7 0x0001 // 7 bit chars #define LCR_WL8 0x0000 // 8 bit chars #define LCR_BRG 0x0020 // Select baud rate generator #define ICR_RXE 0x0001 // receive enable #define ICR_TXE 0x0002 // transmit enable //------------------------------------------------------------------------- // Tables to map input values to hardware settings static unsigned char select_word_length[] = { LCR_WL5, // 5 bits / word (char) LCR_WL6, LCR_WL7, LCR_WL8 }; static unsigned char select_stop_bits[] = { 0, LCR_SB1, // 1 stop bit LCR_SB1_5, // 1.5 stop bit LCR_SB2 // 2 stop bits }; static unsigned char select_parity[] = { LCR_PN, // No parity LCR_PE, // Even parity LCR_PO, // Odd parity LCR_PM, // Mark parity LCR_PS, // Space parity }; // The values in this table plug straight into the BRG register // in the serial driver hardware. They comprise a baud rate divisor // in the bottom 8 bits and a clock selector in the top 8 bits. // These figures all come from Toshiba. #if (CYGHWR_HAL_MIPS_CPU_FREQ == 50) static unsigned short select_baud[] = { 0, // Unused 0, // 50 0, // 75 0, // 110 0, // 134.5 0, // 150 0, // 200 0, // 300 0x0300|20, // 600 0x0300|10, // 1200 0, // 1800 0x0300|05, // 2400 0, // 3600 0x0300|10, // 4800 0, // 7200 0x0200|05, // 9600 0, // 14400 0x0100|10, // 19200 0x0100|05, // 38400 0, // 57600 0, // 115200 0, // 230400 }; #elif (CYGHWR_HAL_MIPS_CPU_FREQ == 66) static unsigned short select_baud[] = { 0, // Unused 0, // 50 0, // 75 0, // 110 0, // 134.5 0, // 150 0, // 200 0, // 300 0x0300|27, // 600 0x0200|54, // 1200 0, // 1800 0x0200|27, // 2400 0, // 3600 0x0100|54, // 4800 0, // 7200 0x0100|27, // 9600 0, // 14400 0x0000|54, // 19200 0x0000|27, // 38400 0, // 57600 0, // 115200 0, // 230400 }; #else #error Unsupported CPU frequency #endif //------------------------------------------------------------------------- // Info for each serial device controlled typedef struct tx3904_serial_info { CYG_ADDRWORD base; CYG_WORD int_num; cyg_interrupt interrupt; cyg_handle_t interrupt_handle; cyg_uint8 input_char; cyg_bool input_char_valid; cyg_bool output_ready; cyg_uint16 cur_baud; } tx3904_serial_info; //------------------------------------------------------------------------- // Callback functions exported by this driver static SERIAL_FUNS(tx3904_serial_funs, tx3904_serial_putc, tx3904_serial_getc, tx3904_serial_set_config, tx3904_serial_start_xmit, tx3904_serial_stop_xmit ); //------------------------------------------------------------------------- // Hardware info for each serial line #ifdef CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL0 static tx3904_serial_info tx3904_serial_info0 = { 0xFFFFF300, CYGNUM_HAL_INTERRUPT_SIO_0 }; #if CYGNUM_IO_SERIAL_TX39_JMR3904_SERIAL0_BUFSIZE > 0 static unsigned char tx3904_serial_out_buf0[CYGNUM_IO_SERIAL_TX39_JMR3904_SERIAL0_BUFSIZE]; static unsigned char tx3904_serial_in_buf0[CYGNUM_IO_SERIAL_TX39_JMR3904_SERIAL0_BUFSIZE]; #endif #endif // CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL0 #ifdef CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL1 static tx3904_serial_info tx3904_serial_info1 = { 0xFFFFF400, CYGNUM_HAL_INTERRUPT_SIO_1 }; #if CYGNUM_IO_SERIAL_TX39_JMR3904_SERIAL1_BUFSIZE > 0 static unsigned char tx3904_serial_out_buf1[CYGNUM_IO_SERIAL_TX39_JMR3904_SERIAL1_BUFSIZE]; static unsigned char tx3904_serial_in_buf1[CYGNUM_IO_SERIAL_TX39_JMR3904_SERIAL1_BUFSIZE]; #endif #endif // CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL1 //------------------------------------------------------------------------- // Channel descriptions: #ifdef CYGPKG_IO_SERIAL_TX39_JMR3904_POLLED_MODE #define SIZEOF_BUF(_x_) 0 #else #define SIZEOF_BUF(_x_) sizeof(_x_) #endif #ifdef CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL0 #if CYGNUM_IO_SERIAL_TX39_JMR3904_SERIAL0_BUFSIZE > 0 static SERIAL_CHANNEL_USING_INTERRUPTS(tx3904_serial_channel0, tx3904_serial_funs, tx3904_serial_info0, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_TX39_JMR3904_SERIAL0_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, CYG_SERIAL_WORD_LENGTH_DEFAULT, CYG_SERIAL_FLAGS_DEFAULT, &tx3904_serial_out_buf0[0], SIZEOF_BUF(tx3904_serial_out_buf0), &tx3904_serial_in_buf0[0], SIZEOF_BUF(tx3904_serial_in_buf0) ); #else static SERIAL_CHANNEL(tx3904_serial_channel0, tx3904_serial_funs, tx3904_serial_info0, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_TX39_JMR3904_SERIAL0_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, CYG_SERIAL_WORD_LENGTH_DEFAULT, CYG_SERIAL_FLAGS_DEFAULT ); #endif #endif // CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL0 #ifdef CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL1 #if CYGNUM_IO_SERIAL_TX39_JMR3904_SERIAL1_BUFSIZE > 0 static SERIAL_CHANNEL_USING_INTERRUPTS(tx3904_serial_channel1, tx3904_serial_funs, tx3904_serial_info1, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_TX39_JMR3904_SERIAL1_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, CYG_SERIAL_WORD_LENGTH_DEFAULT, CYG_SERIAL_FLAGS_DEFAULT, &tx3904_serial_out_buf1[0], SIZEOF_BUF(tx3904_serial_out_buf1), &tx3904_serial_in_buf1[0], SIZEOF_BUF(tx3904_serial_in_buf1) ); #else static SERIAL_CHANNEL(tx3904_serial_channel1, tx3904_serial_funs, tx3904_serial_info1, CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_TX39_JMR3904_SERIAL1_BAUD), CYG_SERIAL_STOP_DEFAULT, CYG_SERIAL_PARITY_DEFAULT, CYG_SERIAL_WORD_LENGTH_DEFAULT, CYG_SERIAL_FLAGS_DEFAULT ); #endif #endif // CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL1 //------------------------------------------------------------------------- // And finally, the device table entries: #ifdef CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL0 DEVTAB_ENTRY(tx3904_serial_io0, CYGDAT_IO_SERIAL_TX39_JMR3904_SERIAL0_NAME, 0, // Does not depend on a lower level interface &cyg_io_serial_devio, tx3904_serial_init, tx3904_serial_lookup, // Serial driver may need initializing &tx3904_serial_channel0 ); #endif // CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL0 #ifdef CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL1 DEVTAB_ENTRY(tx3904_serial_io1, CYGDAT_IO_SERIAL_TX39_JMR3904_SERIAL1_NAME, 0, // Does not depend on a lower level interface &cyg_io_serial_devio, tx3904_serial_init, tx3904_serial_lookup, // Serial driver may need initializing &tx3904_serial_channel1 ); #endif // CYGPKG_IO_SERIAL_TX39_JMR3904_SERIAL1 // ------------------------------------------------------------------------ // Delay for some number of character times. This is based on the baud // rate currently set. We use the numbers that plug in to the BRG // clock select and divider to control two loops. The innermost delay // loop uses a count that is derived from dividing the CPU frequency // by the BRG granularity (and we then add 1 to compensate for any // rounding). This gives the number of cycles that the innermost loop // must consume. For the sake of simplicity we assume that this loop // will take 1 cycle per loop, which is roughly true in optimized // code. void delay_char_time(tx3904_serial_info *tx3904_chan, int n) { static cyg_uint16 clock_val[4] = { 4, 16, 64, 256 }; cyg_uint16 baud_val = select_baud[tx3904_chan->cur_baud]; cyg_count32 clock_loop = clock_val[baud_val>>8]; cyg_count32 div_loop = baud_val & 0xFF; cyg_count32 bit_time = ((CYGHWR_HAL_MIPS_CPU_FREQ_ACTUAL)/(2457600)) + 1; 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 bool tx3904_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 device bool tx3904_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; } //------------------------------------------------------------------------- static Cyg_ErrNo tx3904_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 != tx3904_serial_config_port(chan, config, false) ) return -EINVAL; } break; default: return -EINVAL; } return ENOERR; } //------------------------------------------------------------------------- // Enable the transmitter on the device static void tx3904_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 device static 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_MODE static 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_MODE static 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