Part Number: OMAPL138B-EP
Tool/software: Linux
I'm using a CriticalLink L138F SOM in my application and have come across an interesting issue with interrupts and the UARTs on the L138. The observed issue is that there are lots of spurious interrupts for whatever UART you are using (UART2 in my case) when transmitting characters. This can be seen using:
cat /proc/irq/61/spurious
I can transmit characters using a simple 'echo' command or by using something like 'dd if=/dev/zero of=/dev/ttyS2 bs=8 count=8'. Both methods create spurious interrupts. The serial port has been set up for 115200 baud and 'raw' mode (necessary for the end application).
I'm using the Linux kernel and file system provided by CriticalLink which is based on v3.2.0. From this I know that the serial port (tty) drivers are provided by drivers/tty/serial.8250.c. For this version, I can see that there is a timer set up which is used to circumvent some assumed incompatibility between how the driver wants the UART peripheral to perform and how it actually performs. More specifically the driver would like the UART to immediately raise a THRE flag the moment the interrupt flag for an empty transmitter is enabled. The L138 doesn't do this so it uses a timer to periodically poll the interrupt register to see if there are any pending interrupts. The issue I see with this is that you now have two sources of code trying to read the interrupt register (the timer and the real interrupt routine). When the interrupt register is read, the interrupt flags are cleared automatically so there could be a race condition between the two and that could be a source of the spurious interrupt count increasing, because if the interrupt service routine doesn't find an interrupt to service it returns a zero, not a one (see serial8250_handle_irq in 8250.c). I've disabled the timer and this has reduced the number of spurious interrupts seen but not completely.
Adding some debug to the 8250 driver I can output text to the console whenever a serial interrupt is raised. Using this method, I can see that interrupts get raised for sending data (as they should) but now and again, I will get a spurious interrupt for IRQ61 (UART2) when I shouldn't. The transmit process has completed as it should and the transmit interrupt enable has been turned off but there is still an interrupt coming from somewhere. It doesn't happen every time but when it does, the IIR register equals 0xC1, i.e. the IPEND flag is set meaning there are no interrupts pending, yet the interrupt happened all the same. As I have removed the timer already, there is only one point in the driver that reads the IIR register and that is in the interrupt routine.
I need some help on this because I've exhausted all other avenues.