Content originally posted in LPCWare by Fklein23 on Fri Oct 10 07:00:52 MST 2014
Ex-Zero:
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).
QUOTE:
void UART1_IRQHandler (void)
{
uint8_t IIRValue, LSRValue;
uint8_t Dummy = Dummy;
IIRValue = LPC_UART1->IIR;
IIRValue >>= 1; /* skip pending bit in IIR */
IIRValue &= 0x07; /* check bit 1~3, interrupt identification */
if ( IIRValue == IIR_RLS ) /* Receive Line Status */
{
LSRValue = LPC_UART1->LSR;
/* Receive Line Status */
if ( LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI) )
{
/* There are errors or break interrupt */
... and so on
END QUOTE
OK, my handler does UART0, not UART1.
But 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 the variable that received the RBR data was ZERO! ????????
I am not sure what to do. The interrupt handler is virtually identical to yours, 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