--- In lpc2000@yahoogroups.com, "Leighton Rowe" <leightonsrowe@y...>
wrote:
>
> Just for clarification on the UART Block Diagram (see UM)...
> 1. Do U0TSR & U0RSR actually representthe Tx & Rx FIFO buffers? I
> only see U0TSR & U0RSR illustrated here and I can't find any other
> documentation for it.
No, they are the actual shift registers. U0TSR can be checked with
U0LSR bit 6, TEMT. TEMT=0 => U0TSR is shifting out a byte, TEMT=1 =>
U0TSR is idle. The 16-byte FIFOs aren't shown in the figure, but
would rather correspond to U0THR and U0RBR. For better
documentation, Google for 16C550.
> Now concerning U0THR & U0RBR (data registers)...
> 2. Why do they both share the same memory address? I'd really like
> to know the purpose of this.
Writing to the address means writing to U0THR, and reading from the
address means reading from U0RBR. They occupy the same address
because Philips chose to be software compatible with the 16C550,
which was designed to be hardware and software compatible with the
8250, which was designed at a time when I/O addresses apparently were
very precious. For an even worse example of this mindset, see the
Intel 8259 interrupt controller which occupies two(!) I/O addresses.
> 3. What will happen if the lpc receives a character while I'm
> writing to the transmit register?
Nothing special, the receiver and transmitter work independently.
But make sure that you don't miss any of them in your interrupt
handler.
> I ask this because currently, I'm having trouble running the serial
> port both ways (with interrupts) while sending replies and
receiving
> command packets from the PC. Sometimes the protocol I'm using
works.
> However, while debugging I always notice the lpc losing receiver
> bytes whenever communication goes wrong. I only observe this
> happening if the lpc's replying to a command packet and another
> command packet's coming in the same time.
When you enable more than one interrupt in U0IER (such as both
receive and transmit interrupt), you should in your interrupt handler
check U0IIR to see what caused the interrupt. More than one
interrupt can occur at a time, and the highest priority one is
indicated in U0IIR.
Pay close attention to the "Interrupt Reset" column in the UART0
Interrupt Handling table. When you have seen in U0IIR what caused
the interrupt, you should handle it, and then do the action in
the "Interrupt Reset" column to tell the UART that you have handled
it. For a receive interrupt, the Interrupt Reset action is to
read U0RBR, so it is a quite normal part of handling a receive
interrupt. For a transmit interrupt, the reset action is simply
reading U0IIR, which you have already done since you know it is a
transmit interrupt.
If you don't do the Interrupt Reset action in your interrupt handler
for a pending interrupt, the UART will immediately interrupt again.
So you can write your interrupt handler in two ways:
a. Check U0IIR, handle the highest-priority pending interrupt,
thereby doing the Interrupt Reset action, and return. If more than
one interrupt was pending, the UART will immediately interrupt again,
and then present the next-highest priority interrupt in U0IIR, and so
on. This way is the easiest, and the best one if multiple
simultaneous interrupts are rare.
b. Check U0IIR, handle the highest-priority pending interrupt,
thereby doing the Interrupt Reset action. Re-check U0IIR, and loop
around if another interrupt is pending. When no more interrupts are
pending, return. This way is better if multiple simultaneous
interrupts are so likely that it pays off to save the multiple
interrupt entry/exit code.
Regards,
Karl Olsen