lpcware

On an LPC1769, reading the LPC_UART0->IIR clears the RBR register

Discussion created by lpcware Employee on Jun 15, 2016
Latest reply on Jun 15, 2016 by lpcware
Content originally posted in LPCWare by Fklein23 on Fri Oct 10 06:58:51 MST 2014
I added UART0 to my UART interrupt handler, and the code is virtually the same as your quoted code (the variables are even named the same).
The handler for all 4 UARTS start the same (usual) way:

IIRValue = LPC_UART0->IIR;

IIRValue >>= 1; /* skip pending bit in IIR */
IIRValue &= 0x07; /* check bit 1~3, interrupt identification */
if ( IIRValue == IIR_RLS ) /* Receive Line Status */
{  ...
   rbr_value = LPC_UART0->RBR   // the program NEVER gets here for reasons explained below.
   ...

... and so on...

Here is the strange thing I am seeing. This instruction: "IIRValue = LPC_UART0->IIR;" clears the RBR register!!!!

Without breakpoints, the symptom is that the transmit functionality works perfectly, but the receive function doesn't do ANYTHING.
I can see the character sent by the terminal on the oscilloscope, the interrupt fires, but no characters appear in the application's input channel.
WITH breakpoints, I stopped the IRQ handler at this instruction and before reading the IIR register, my watch window shows

LPC_UART0->IIRconst volatile uint32_t196
LPC_UART0->RBRconst volatile uint8_t85 'U'

Then after a single step through THIS instruction: "IIRValue = LPC_UART0->IIR;"

Now my watch windows look like this:

LPC_UART0->IIRconst volatile uint32_t193
LPC_UART0->RBRconst volatile uint8_t0 '\0'

Note that not only does the RBR register get cleared, but the
I have tried several workarounds, because I was concerned that the very existence of the watch window, which displayed the value of the RBR register, might have caused the actual register to clear as if my program had read it. (I get paranoid about stuff like that after 30 years of living with the "errata" of the microprocessor world! :-)

Note not only does the RBR register get cleared by reading the IIR register, but the RX data available bit ALSO clears in the IIR register after reading it.

So I put the "read RBR"  instruction BEFORE the "read IIR" register and set a breakpoint AFTER both instructions. I then hit a key on the terminal and rbr_value was ZERO!  ????????

I am not sure what to do. The interrupt handler is straight out of the "LPC_17xx bible", chapter and verse, and I was assured by my colleagues here that the same handler, when aimed at UART2 works flawlessly.

So my next step is to rewire the breadboard temporarily, to use UART2 instead of UART0 and try the same experiment and see what happens in the UART2 IRQ handler (which is identical to the UART0 handler).

I wonder if UART0 has some known quirks that make it different that UART2 and 3. I know that 0,2 and 3 are different than UART1, but the same method should work for AT LEAST UART0 and 2.

Any thoughts?
Anyone else ever seen this?

Thanks - Frank

Outcomes