The WDK serial driver uses WRITE_PORT_BUFFER_UCHAR to stuff a buffer full of bytes into the transmit FIFO on my hardware. The default amount stuff into the FIFO is 14 bytes as defined by SERIAL_TX_FIFO_DEFAULT. A 16550 standard serial device has 16 byte rx and tx FIFOs.
My question is lets say we do two transmissions in succession. What prevents the WDK function WRITE_PORT_BUFFER_UCHAR from trying to stuff 28 bytes into a 16 byte FIFO resulting in a loss of the last 12 bytes?
If there were a FIFO full status to be read from some register I could understand how to avoid this kind of overflow, but it seems to work as it is. How does it do it?
xxxxx@hotmail.com wrote:
The WDK serial driver uses WRITE_PORT_BUFFER_UCHAR to stuff a buffer full of bytes into the transmit FIFO on my hardware. The default amount stuff into the FIFO is 14 bytes as defined by SERIAL_TX_FIFO_DEFAULT. A 16550 standard serial device has 16 byte rx and tx FIFOs.
My question is lets say we do two transmissions in succession. What prevents the WDK function WRITE_PORT_BUFFER_UCHAR from trying to stuff 28 bytes into a 16 byte FIFO resulting in a loss of the last 12 bytes?
If there were a FIFO full status to be read from some register I could understand how to avoid this kind of overflow, but it seems to work as it is. How does it do it?
Incoming writes are queued up within the driver. The
WRITE_PORT_BUFFER_UCHAR only happens during the ISR when the write
threshhold bit tells it that there is enough room. Until then, the
characters just sit in the queue.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
>“The WRITE_PORT_BUFFER_UCHAR only happens during the ISR when the write
threshhold bit tells it that there is enough room. Until then, the
characters just sit in the queue.”
I must be overlooking something then. What/where is this write threshold bit you speak of?
Thanks!
> I must be overlooking something then. What/where is this write threshold
bit you speak of?
See bits 6 & 7 in the FIFO control register.
Loren
xxxxx@hotmail.com wrote:
> “The WRITE_PORT_BUFFER_UCHAR only happens during the ISR when the write
>
threshhold bit tells it that there is enough room. Until then, the
characters just sit in the queue.”
I must be overlooking something then. What/where is this write threshold bit you speak of?
Bit 5 of the “interrupt ID register” indicates whether the Transmit
Holding Register is empty or not. I believe that’s base address + 5.
The driver calls it SERIAL_IIR_THR.
It does seem interesting that the ISR *assumes* that only one interrupt
will fire at a time. Even though it is a bitmask, it does a switch
statement on the values of the individual bits. I’d call that a bug.
It should be “if( InterruptIdReg & SERIAL_IIR_RLS )”, etc.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.
Alright… I think I’ve got it figured out.
Writes get queued up in the WriteQueue and passed off to the ISR through SerialGiveWriteToIsr(). They only get written when the Transmit Holding Register is Empty as specified in BA+2 which is the IIR and interrupts sources are encoded w/ bits 3:0. So, the ISR only sends one item from the queue, and the next gets dequeued and transmitted once the previous one is completely gone.
It seems like you could keep the transmitter much busier, if you kept it full with available data. Instead, as it is the best we can do is to put (by default) 14 bytes into the FIFO, if it is holding we can fill it completely, transmit the 14 or 16 bytes, then put dequeue another 14/16 bytes and do it again.
I suppose the time to fill the transmitter with new data is so small that it it makes my claim insignificant.
xxxxx@hotmail.com wrote:
Alright… I think I’ve got it figured out.
Writes get queued up in the WriteQueue and passed off to the ISR through SerialGiveWriteToIsr(). They only get written when the Transmit Holding Register is Empty as specified in BA+2 which is the IIR and interrupts sources are encoded w/ bits 3:0. So, the ISR only sends one item from the queue, and the next gets dequeued and transmitted once the previous one is completely gone.
Right.
It seems like you could keep the transmitter much busier, if you kept it full with available data. Instead, as it is the best we can do is to put (by default) 14 bytes into the FIFO, if it is holding we can fill it completely, transmit the 14 or 16 bytes, then put dequeue another 14/16 bytes and do it again.
I suppose the time to fill the transmitter with new data is so small that it it makes my claim insignificant.
The key point to remember here is that the serial port is unbelievably
slow. Even at 38,400 baud, a 2GHz CPU will be able to execute 400,000
instructions between each byte. The interrupt will be acknowledged and
the buffer refilled in plenty of time to avoid any dead air.
–
Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.