This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
Make better use of the 16x5x UART transmit FIFO
- From: daniel dot neri at sigicom dot se (Daniel Néri)
- To: ecos-patches at sources dot redhat dot com
- Date: Tue, 07 Feb 2006 12:29:55 +0100
- Subject: Make better use of the 16x5x UART transmit FIFO
- Cancel-lock: sha1:+IbVTZBK5w7QrGRCvGqaJQ3xWFY=
- Organization: Sigicom AB, Stockholm, Sweden
Hello,
I've finally cleaned up my fix for the generic 16x5x UART driver, as
previously mentioned on ecos-discuss.
Best wishes,
--Daniel
diff -r e8bf60a19428 devs/serial/generic/16x5x/current/ChangeLog
--- a/devs/serial/generic/16x5x/current/ChangeLog Wed Nov 24 10:24:02 2004 +0000
+++ b/devs/serial/generic/16x5x/current/ChangeLog Tue Feb 7 12:28:47 2006 +0100
@@ -1,3 +1,15 @@ 2003-09-19 Gary Thomas <gary@mlbassoc.
+2006-02-07 Daniel Néri <daniel.neri@sigicom.se>
+
+ * cdl/ser_generic_16x5x.cdl
+ (CYGNUM_IO_SERIAL_GENERIC_16X5X_FIFO_TX_SIZE): New option.
+
+ * src/ser_16x5x.c (serial_config_port, pc_serial_putc,
+ pc_serial_DSR): At TX interrupt, write up to
+ CYGNUM_IO_SERIAL_GENERIC_16X5X_FIFO_TX_SIZE bytes to the transmit
+ FIFO. This makes better use of the FIFO, since the LSR_THE flag
+ resets when the FIFO is non-empty (not when it's full, as this
+ code previously assumed).
+
2003-09-19 Gary Thomas <gary@mlbassoc.com>
* src/ser_16x5x.c (pc_serial_init):
diff -r e8bf60a19428 devs/serial/generic/16x5x/current/cdl/ser_generic_16x5x.cdl
--- a/devs/serial/generic/16x5x/current/cdl/ser_generic_16x5x.cdl Wed Nov 24 10:24:02 2004 +0000
+++ b/devs/serial/generic/16x5x/current/cdl/ser_generic_16x5x.cdl Tue Feb 7 12:28:47 2006 +0100
@@ -94,6 +94,15 @@ cdl_package CYGPKG_IO_SERIAL_GENERIC_16X
the RX interrupt occurs when a FIFO is used. (16550 and
above only), this may be after 1, 4, 8 or 14 characters."
}
+
+ cdl_option CYGNUM_IO_SERIAL_GENERIC_16X5X_FIFO_TX_SIZE {
+ display "16x5x TX FIFO size"
+ flavor data
+ default_value 16
+ description "
+ Configures the maximum number of bytes written to the
+ 16x5x UART transmit FIFO when the TX interrupt occurs."
+ }
}
cdl_component CYGPKG_IO_SERIAL_GENERIC_16X5X_OPTIONS {
diff -r e8bf60a19428 devs/serial/generic/16x5x/current/src/ser_16x5x.c
--- a/devs/serial/generic/16x5x/current/src/ser_16x5x.c Wed Nov 24 10:24:02 2004 +0000
+++ b/devs/serial/generic/16x5x/current/src/ser_16x5x.c Tue Feb 7 12:28:47 2006 +0100
@@ -212,6 +212,8 @@ typedef struct pc_serial_info {
s16550,
s16550a
} deviceType;
+ unsigned tx_fifo_size;
+ volatile unsigned tx_fifo_avail;
#endif
} pc_serial_info;
@@ -332,10 +334,15 @@ serial_config_port(serial_channel *chan,
_fcr_thresh=FCR_RT14; break;
}
_fcr_thresh|=FCR_FE|FCR_CRF|FCR_CTF;
+ ser_chan->tx_fifo_size = CYGNUM_IO_SERIAL_GENERIC_16X5X_FIFO_TX_SIZE;
HAL_WRITE_UINT8(base+REG_fcr, _fcr_thresh); // Enable and clear FIFO
}
- else
+ else {
+ ser_chan->tx_fifo_size = 1;
HAL_WRITE_UINT8(base+REG_fcr, 0); // make sure it's disabled
+ }
+
+ ser_chan->tx_fifo_avail = ser_chan->tx_fifo_size;
#endif
if (chan->out_cbuf.len != 0) {
_ier = IER_RCV;
@@ -423,16 +430,26 @@ static bool
static bool
pc_serial_putc(serial_channel *chan, unsigned char c)
{
+#ifndef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
cyg_uint8 _lsr;
+#endif
pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
cyg_addrword_t base = ser_chan->base;
+#ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
+ if (ser_chan->tx_fifo_avail > 0) {
+ HAL_WRITE_UINT8(base+REG_thr, c);
+ --ser_chan->tx_fifo_avail;
+ return true;
+ }
+#else
HAL_READ_UINT8(base+REG_lsr, _lsr);
if (_lsr & LSR_THE) {
// Transmit buffer is empty
HAL_WRITE_UINT8(base+REG_thr, c);
return true;
}
+#endif
// No space
return false;
}
@@ -626,6 +643,9 @@ pc_serial_DSR(cyg_vector_t vector, cyg_u
break;
}
case ISR_Tx:
+#ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
+ ser_chan->tx_fifo_avail = ser_chan->tx_fifo_size;
+#endif
(chan->callbacks->xmt_char)(chan);
break;
--
Daniel Néri <daniel.neri@sigicom.se>
Sigicom AB, Stockholm, Sweden