This isn't a Soviet washing machine in the strictest sense; it appears to be more a case of a de facto standard (i.e., a grand game of follow the lemming) having preserved half of a useful feature - presumably because it had always been there - but lost the other half - perhaps because nobody remembered what it was for - thereby becoming more of a defective standard.
Yes, today's gripe is the UART in the LPC21xx microcontrollers, and in particular the way it was copied from the ubiquitous 16C550, which was copied... well, eventually it goes back to the 8250, and before that to the old 40-pin UARTs (AY-n-nnnn, whatever the numbers were).
Y'see, there are basically two transmitter status bits. One says it's time to feed the transmitter (originally THRE, Transmitter Holding Register Empty); the other says the transmitter has actually run dry (TEMT, Transmitter EMpTy).
Now, on a full-duplex line, all you need is the THRE bit, which tells you that you can stuff more bytes into the transmitter. All the current UARTs provide an interrupt on this condition. This works nicely.
For half-duplex, though, it's really useful to know when the last bit has been transmitted, so that you can turn the channel around. Doing this when the transmitter has just started shifting out the last character (the THRE interrupt) is simply not acceptable.
And so it comes to pass that I, attempting to implement a half-duplex line discipline, wish to receive an interrupt on TEMT.
Oops.
It appears that a TEMT status interrupt isn't available.
Somewhere along the line - and I'm looking at you, Mr. National Semiconductor, and your INS82C50A, and your Series 32000 Databook for June 1985 - the canonical UART with microprocessor bus interface was designed with a TEMT status bit that can be polled, but no ability to get an interrupt when it goes active.
Grrrr.
This means that, for the half-duplex scenario, I need to set an alarm after loading the buffer for the last time (which may be up to 16 characters), and poll for the freakin' TEMT bit, at system-timer intervals.
Life just got a whole bunch more complicated.
Update: not as complicated as I'd feared. Add a static variable containing the line status register contents for each UART as of the last TX or line-status interrupt, and a routine (should be an optionally-linked-in module, really) called from the 1ms polling task to check for TEMT having changed for the higher, and in any case to update the old-LSR variable.
I'm not crazy about the up-to-1ms turnaround time after transmission, but, since the RS-485 interface in the application at hand will only be running at 9600 Baud, that's only one character time, and it so happens that the other side is expected to transmit infrequently.
Recent Comments