UART: Double Trouble
The DUART TL16c2752 is supposed to be a rather big upgrade to the Steckschwein “core”. Now two serial interfaces, with 64 byte FIFOs each, instead of only one interface with 16 byte FIFOs. Oh, the possibilities. Using one line to explore UART interrupt handling while still having another one to upload code. Cool!
With the 16C2752 being a part of the 16C550 family, we did expect it to be a simple drop in replacement for the latter one. As we all know, happiness is reality minus expectation, and oh boy did things get dreadful!
The easy fix: bus timing
First, I had to get the bus timing straight, as I did not qualify the /RD and /WR lines of the 16C550 through PHI2. The 16C550 apparently is slow enough to be fine this way. Hence, qualifying the /IOR and /IOW lines of the 16C2752 was the first step to talk to the CPU and let the CPU do a proper initialization.
To be really sure, I wrote known values into the so called “scratch pad register” and read it back. I repeated this a couple thousand times to make sure reading and writing to the chip works properly.
That was the easy part.
The ordeal
With a properly initialized DUART, it was time for a first test. A simple routine that receives one byte and echoes it back to us should to the trick. And it did. Encouraging. Next step, hooking one DUART channel up to our XMODEM routine. No luck, not one single XMODEM packet got transferred.
Back to square one. More thorough testing with the echo program. This time, I put both the UART and the DUART on the breadboard.

First, I used the UART to receive data, and echoed it back on the DUART. Which worked perfectly, so the DUART is sending data properly. The other way, receiving on the DUART and echo on the UART however, showed corrupt bytes. On receiving many bytes in a very short period, the first about 20 bytes would be received properly, and then most of the rest would be garbled. No wonder XMODEM would not work.
First test, just typing “abcde” into the terminal connected to the DUART does not look faulty at all.
But writing a few more bytes at a fast rate into the port makes the problem visible.
Here, everything after “t” is corrupted.
We were framed
What followed, were weeks of reading the data sheet, trying endless register combinations, baud rates, FIFO on or off, until I wisely decided to log the contents of the LSR register along with the received bytes. The LSR content when outputting the garbled bytes was $E9, or 11101001
| Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
|---|---|---|---|---|---|---|---|
| RX FIFO Global Error | THR & TSR Empty | THR Empty | RX Break | RX Framing Error | RX Parity Error | RX Overrun Error | RX Data Ready |
| 1 | 1 | 1 | 0 | 1 | 0 | 0 | 1 |
Bit 7 (“RX FIFO Global Error”) tells us, that there is at least one byte in the FIFO that has not been transmitted properly. Bit 3 reveals an “RX Framing Error” being the reason being for that. Now what? Could the CH340 USB to serial converter be the problem? Trying another module with an FTDI FT232 showed the same behaviour. Furthermore, the same modules work flawlessly on the UART. We already made sure we can rule out the bus interface. So what could the source of those framing errors be?
Maybe examining the transferred data using a logic analyzer helps..

Another run. The last output shows corrupt bytes after “q”.

Checking with the logic analyzer. As the protocol decoder shows, the bytes after “q” have been sent properly. So does the T16C2752 anything different than the 16C550?
They knew!
After some research, I found an errata document from TI 1 which pretty much fits the observed behaviour:
The TL16C752C, TL16C754C and TL16C2752 UARTs can encounter framing errors when receiving a stream of characters with short STOP bits.
and
The effect of the short STOP bit is cumulative so the framing error can occur after only a few or after many characters have been received.
A suggested workaround is to use 1.5 oder 2 stop bits.. and after configuring my serial terminal to 8N2, the garbled characters went away. So after spending hours and hours over almost three months troubleshooting my hardware design, hunting phantoms in my code, the culprit actually turns out to be the DUART chip itself!
What to make of this
What’s left is the question on how to deal with this. Use a faster oscillator might help, sticking with the very unusual and non standard 8N2 line parameters would work. Throwing the TL16C2752 in the bin and use a 16C2552 instead will very certainly work, too.
TI classifies the severity of this behaviour as “moderate”. I tend to disagree slighty.