UART TX FIFO and INTs problem
2004-02-17 by forum_microbit
Hi all,
[I'm reposting on the URL, the new lpc2000 address doesn't seem to wor
I'm a bit stuck with this one, and hope someone has some advice,
I must be overlooking something and I just don't see it.......
I'm using Two 256 byte circular buffers for RX and TX Interrupts on
UART0.
Putchar() writes a char to the TX buffer's current head pointer and
post increments it (auto wrap on index byte). It then increments the
# of TX chars in the buffer (tx_chars) and enables the THRE Interrupt.
The THRE handler part takes a character from the tail pointer, and
post increments. It then decrements tx_chars.
If TX buffer tail equals TX buffer Head, the THRE Interrupt is
disabled.
Of course in case I write too fast to the TX buffer and it overflows
(to simplify for the time being) at the end of Putchar() I check if
tx_chars is larger than say, 200 Chars.
If it is, I wait in a while loop for tx_chars to drop below a
threshold, say 32.
I've used this principle on many MCUs, and never had a problem.
The problem is that if I write a _constant_ flow of characters much
faster than the Baudrate after quite some time the transmission INTs
stop. [ NO other interrupts are running during this test ]
To test it, I set a pin HIGH when Putchar() is waiting for the TX
buffer to empty a bit, and clear it when buffer filling resumes - a
bit like this :
volatile unsigned char tx_chars;
..... /* write char to buffer */
++tx_chars ; /* another char in TX buffer */
if ( tx_chars > 200 )
{
/* set test pin HIGH */
while ( tx_chars > 32 ) ; /* let TX buffer flush out a bit */
}
/* set test pin LOW */
}
I can see all is fine, the TEST pin spends time HIGH while the buffer
is being flushed, and is then LOW for a few mS (printf() is re-
filling up the buffer from 32 or less to > 200 chars)
When the transmit out of UART0 TX stops, tx_chars is set to one more
than the threshold (for example - here 33 ), and Tail and Head
Pointer of TX buffer are equal, hence the THRE interrupt is disabled.
The code of course is stuck in the while ( tx_chars > 32 ) loop ......
A plausible explanation would be that at times, the TX FIFO holds
more than one byte, and when the THRE interrupt occurs, more than one
char should be subtracted from tx_chars.
This could explain why tx_chars isn't <Zero> when TX Head and TX Tail
become equal and THRE INTs turn OFF.
On the other hand this doesn't make sense, as the TX FIFO should be
transparent to that process. Also, if this was a simple FIFO issue,
that process should lock up after a few hundred characters are
transmitted.
There is nothing in the user guide on LPC2106 that clarifies how
exactly the TX FIFO and the THRE interact.
Although the guide says that FIFOs should be enabled for proper UART
operation, leaving U0FCR to ZERO makes no difference, nor does
changing the FIFO trigger level (again wording is ambiguous here,
left column implies RX FIFO only , right column bitmap implies both
RX and TX FIFOs.
In fact I don't see the point of the TX FIFO if your THRE/TEMT can't
tell you whether you just flushed out 1 or <trigger level> bytes.
Is anyone seeing what the problem is ?
I'm stumped.
Best regards,
Kris