Guidance on tracking down spurious interrupts

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Guidance on tracking down spurious interrupts

2,947 Views
FridgeFreezer
Senior Contributor I

I've read a couple of good posts on here, particularly from mjb, but I still don't quite have a full grasp on how to track down a problem I'm currently having with spurious interrupts.

 

Setup is MCF52259 on our own PCB, CW7.2 with USB Multilink, code is in C.

 

As it stands, the micro is (randomly) getting spurious interrupts from somewhere - which may or may not be the UART (see below).

 

As per mjb's post on the subject, I have a spurious_isr() routine which captures various registers and then sits in an infinite loop:

 

__interrupt__ void spurious_int(void) // Handles spurious interrupts{ static uint32 test[16]; uint8 i = 0;  test[0] = MCF_INTC0_IPRH; // Pending interrupts high test[1] = MCF_INTC0_IPRL; // Pending interrupts low test[2] = MCF_INTC0_IMRH; // Interrupt mask high test[3] = MCF_INTC0_IMRL; // Interrupt mask low test[4] = MCF_INTC0_IRLR; // Interrupt Request Level Register test[5] = MCF_INTC0_IACKLPR; // IACKLPR Interrupt Acknowledge Level and Priority Register test[6] = MCF_INTC0_SWIACK; // Software IACK Register test[7] = MCF_INTC0_L1IACK; // Level 1 IACK register test[8] = MCF_INTC0_L2IACK; // Level 2 IACK register test[9] = MCF_INTC0_L3IACK; // Level 3 IACK register test[10] = MCF_INTC0_L4IACK; // Level 4 IACK register test[11] = MCF_INTC0_L5IACK; // Level 5 IACK register test[12] = MCF_INTC0_L6IACK; // Level 6 IACK register test[13] = MCF_INTC0_L7IACK; // Level 7 IACK register test[14] = (test[0] & test[2]); // High mask & pending interrupts test[15] = (test[1] & test[3]); // Low mask & pending interrupts         while (1)        {     nop();        }    }

 

Now the bits I can't work out:

When it drops into the spurious_isr I don't know how to read the status register (SR) in C, I can't see a #define for it and don't have the asm knowledge to get it. I can't see any way to find out which interrupt number triggered the spurious interrupt, as it doesn't seem to be showing up in the debug data (below).

 

 

The results when it drops into the ISR are:

IPRH: 0x00000000

IPRL: 0x00008000

IMRH: 0x7E7FFFFF

IMRL: 0XFF839F56

IRLR: 0x00000000

IACKLPR: 0x00000000

SWIACK: 0x00000000

L1IACK: 0x00000000

L2IACK: 0x00000018

L3IACK: 0x00000018

L4IACK: 0x00000018

L5IACK: 0x00000018

L6IACK: 0x00000018

L7IACK: 0x00000018

 

Which points to interrupt 15 - UART2. The strange thing is UART2 has a full ISR the same as the other two UARTS, and although the UART is enabled it is not currently connected to anything so should be seeing no activity. If it did get any spurious data (from a floating pin etc.) then it would be ignored and the UART cleared (MCF_UART_UCR(2) = MCF_UART_UCR_RESET_ERROR:smileywink:

 

Can anyone point me in the direction of how to extract the data on the interrupt source so I can debug this?

Labels (1)
0 Kudos
7 Replies

835 Views
BlackNight
NXP Employee
NXP Employee

Hello,

it could be the kind of problem I had myself a couple of weeks ago: running an application on the 52259 with multiple different interrupt sources (serial line, timers, RTOS, ...) was causing some random interrupts, especially while debugging and under high interrupt load. Turned out that the problem is the (hardware) interrupt controller: if you have multiple interrupt sources with the same priority/level within priority then the interrupt controller behaves in an undefined manner if two interrupts happen about the same time. This is actually documented in the manual (I don't have the text at hand right now), but it is easy to overlook.

Assigining unique interrupt levels/priorities for every single interrupt solved the probelm for me.

 

BK

0 Kudos

835 Views
FridgeFreezer
Senior Contributor I

Thanks BK, I have tried to set a different level/priority for all interrupts but I will go through and check I haven't missed something.

0 Kudos

835 Views
FridgeFreezer
Senior Contributor I

I've done a bit more digging;

The IPRL was showing UART2 (Interrupt 15) as the source, but it was masked off in IMRL. Un-masking it and allowing the ISR to run & reset the UART seems (at the moment) to have cured it.

 

I have found a routine which runs twice, once for UART1 and once for UART2 where there were a couple of fixed references to UART1, but all that should mean is that UART2 may have been talking to itself, I would expect if the interrupt is masked off it shouldn't be able to cause a spurious interrupt?

0 Kudos

835 Views
BlackNight
NXP Employee
NXP Employee

Hello,

yes, I had masked off other interrupts too, but the issue I saw was that they still have been fired.

So I guess you still have interrupts with the same priority and level.

 

And here is the relevant part in the manual:

"16.3.6 Interrupt Control Registers (ICRnx)

...

It is the responsibility of the software to program the ICRnx registers with unique and non-overlapping
level and priority definitions. Failure to program the ICRnx registers in this manner can result in undefined
behavior. If a specific interrupt request is completely unused, the ICRnx value can remain in its reset (and
disabled) state."

 

BK

0 Kudos

835 Views
FridgeFreezer
Senior Contributor I

So even if you mask something off, it can still cause an interrupt? :smileyindifferent:

 

One thing the reference manual doesn't make clear is what the priority of the IRQ pins is considered to be - it says they are fixed at the mid-point, but does that mean they automatically occupy Priority 3, or Priority 4, or are they at their own separate "Priority 3.5"? I only ask as I have a few interrupts which are at pri3 or 4, I can easily change them but as with any intermittent fault it's difficult to know quickly if it's helped.

0 Kudos

835 Views
FridgeFreezer
Senior Contributor I

Well a bit more reading and I've answered a few of my own questions, discovered some new things, but am no closer to finding the source of the mysterious spurious interrupt.

 

The IRQ pins do have their own priority, 8, which sits in the middle of the priorities - so no overlap there.

 

It seems that common best practice is to mask interrupts by SET_IPL(7) before modifying the interrupt mask to prevent spurious interrupts. I'm now doing this every time I modify the IMR. I don't know if there are other places this should be done, for example when modifying peripherals interrupt control registers?

 

I have been using the command line debug for the first time, and discovered that the reg all command is a very useful way of getting the state of all the registers. Although I've found a few basic mentions of the command line debug in various manuals, I can't find any sort of in-depth guide to it, I suspect it's hiding in the depths of the freescale website somewhere, anyone know where?

 

Being able to direct the command line output to a file would be very useful to compare full dumps of the "running" registers to "spuriously interrupted" ones to maybe spot the differences.

0 Kudos

835 Views
Piotr
Contributor I

I suspect the problem can be caused by one  of interrupt sources set to Level 7. As level 7 is non-maskable this can lead to various unexpected effects. Could you check this ?

 

0 Kudos