It's a rare occurrence on a LPC11U35FHI33. IIR (the interrupt reason register) says UART interrupt is owing to CTI (character time-out), but LSR (line status register) is all zero. My ISR ends up in an infinite loop, because it reads the Rx FIFO only if the data ready bit is set, but there is nothing to read here as the Rx FIFO is empty. CTI won't clear without reading the Rx FIFO, so it keeps on reasserting the interrupt endlessly.
On the surface this seems something impossible to happen. If Rx FIFO is empty why can't CTI de-assert itself? Right now I (think I) have a workaround by reading Rx FIFO anyway even if it is empty, if it is a CTI and LSR says no data is ready.
I'm working with an LPC11U68 based board and did not have the above described issue until I started work on our standard method of invoking the manufacturing test routine. Invoking manufacturing test is supposed to be extremely difficult for anyone [in the field] to accidentally do and involves using the bootstrap loader to branch to a routine that simply sets a variable and then branches to the normal startup code. The application can test this variable and execute the manufacturing test code or the normal application code. The initialization of everything on the board is common for either mode of operation.
The problem I have is that when I start via the bootloader, as soon as the normal startup code enables the USART0 RX data ready interrupt, this continuous UART character timeout problem shows up and the ISR triggers in an infinite loop. Worse, no matter how many ways I've tried to handle this problem, I can find no way to clear this flag in the IIR register, so the RX data ready interrupt is *always* active.
Interestingly, this apparent chip bug and any *official* workaround for it is not in the chip errata.
This is my ISR code. The preprocessor directives show the things I've tried. None of them work. Can anyone suggest some other thing I could try to fix this problem?
extern "C" void USART0_IRQHandler(void){
enter_critical();
uint8_t c; // for interacting with FIFO's
uint8_t * p; // for interacting with FIFO's
fifo_size_t count; // for interacting with FIFO's
bool bCTI; // tracks interrupt ID register character timeout flag
uint32_t status; // for saving status register contents
LPC_USART0_Type * pUART = LPC_USART0;
for(;;){
status = pUART->LSR;
if(((pUART->IIR & 0xE) >> 1) == 6u){ // save state of character timeout flag
bCTI = true;
}else{
bCTI = false;
}
if(bCTI){
LED_error(1);
}
c = (uint8_t) pUART->RBR;
if(status & RDR){ // receive data available?
p = &c;
count = 1;
uart[0].rxfifo->write(&p,&count); //lint !e534
#if 1
}else{
break; // error LED blinks continuously
}
#elif 0
}else if(!bCTI){
break; // error LED never turns off
}
#else
}
break; // error LED blinks continuously
#endif
}
if(status & THRE){ // transmit holding register empty?
count = 1;
if(uart[0].txfifo->read(&c, count)){
pUART->THR = c;
}else{
pUART->IER &= ~THRE_INT;
}
}
if(bCTI){ // make error LED blink
uint32_t i;
i = 300000;
while(i--);
LED_error(0);
i = 300000;
while(i--);
}
exit_critical();
}
Hello,
It seems to be a familiar error where CTI will be set eventhough there is no data on Rx FIFO. This post also has a similiar issue and it recommends to read Rx FIFO (in order to clear CTI) no matter if LSR register specifies no received data: Continuous UART Character Timeout Interrupts (CTI) but not characters in FIFO | www.LPCware.com
Solution basically implements:
I hope this can help you!
Regards,
Isaac