Edge Port IRQ7 problem on MCF52252 ColdFire V2:

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

Edge Port IRQ7 problem on MCF52252 ColdFire V2:

1,553 Views
Mudwog
Contributor I


ICR001, ICR003, ICR005, and ICR007 are read only special for the Edge Port (section 16.1.1 in the reference manual (Rev 4)),  They cannot be configured.  They are hard coded in Silicone to the Midpoint Priority and some levels that the manual didn't mention.
Based on other information, I suspect that the levels and priorities are:

IRQ 7 - Level 7 Priority 3.5
IRQ 5 - Level 5 Priority 3.5
IRQ 3 - Level 3 Priority 3.5
IRQ 1 - LEvel 1 Priority 3.5

NOTE: Level 7 is non-maskeable and will preempt any lower level interrupt, but that should be fine for this application.

 

I have other  interrupts: PIT0, UART0, UART2, analog to digital converters, and three Edge Port interrupts.  The Levels/Priorities are unique for each interrupt. 

 

If I use IRQ1, IRQ3, and IRQ5 the system runs beautifully. 
Unfortunately I had originally planned to use IRQ3, IRQ5, and IRQ7 but since IRQ7 caused problems, a re-work was added to move that input to IRQ1.  We will not have time to re-lay out the board, and there will be significant number of boards, so it would be very helpful to eliminate the re-work.

 

The problem I'm having with IRQ7:
is that it permanently disables all of the other interrupts, killing the system.  (Sometimes it might take two IRQ7's to kill the system).  After the first (or sometimes second) IRQ7 the only interrupt that the processor gets is IRQ7.  The Edge Port interrupts are configured for both rising and falling edges.

 

My question:

Does any one know how to use IRQ7 and keep the other interrupts active?

 

 

 

Labels (1)
0 Kudos
8 Replies

1,060 Views
JimDon
Senior Contributor III

I've been using IRQ7 on the MCF52255 with no issues at all.

As far as I can tell, it should not behave any different that the other edge port interrupts.

My initialization code is the same for int 1-7, as is the interrupt handler.

void IRQInit(int IRQ, uint8 edge,void (*OnEdge)(uint32))

{

  uint8 bit = 1 << IRQ;

  if(IRQ > 7 ||  IRQ < 1 )

  return;

  OnEdges[IRQ] = OnEdge;

  // Set pin to this function.

  MCF_GPIO_PNQPAR &= ~(03 << (IRQ *2));

  MCF_GPIO_PNQPAR |= 1 << (IRQ*2);

  // Set to bit to input

  MCF_EPORT_EPDDR  &= ~bit;

  // Clear  out the level/edge  bits

  MCF_EPORT_EPPAR  &= ~(3 << (IRQ*2));

  MCF_EPORT_EPPAR  |= (edge << (IRQ*2));

  MCF_EPORT_EPFR |= bit;

  __VECTOR_RAM[64 + IRQ] =(uint32) pISR[IRQ];

  MCF_EPORT_EPIER  |= bit;

  MCF_INTC0_IMRL  &= ~(bit+1);

  // Clear any pending interrupt.

  MCF_EPORT_EPFR |= bit;

}

This is interrupt handler:

static __declspec(interrupt) void IRQ7_ISR(void)    

{

  Encoder1Counts--;

  MCF_EPORT_EPFR |= MCF_EPORT_EPFR_EPF7;

}

0 Kudos

1,060 Views
Mudwog
Contributor I

Jim,

thanks for your code exerpt.  I've been going over it bit by bit.  It looks like you might be running an "RTOS" of some sort so the key might be elsewhere.

It is encouraging to hear that someone else has used IRQ7 successfully on a processor in the same family, though I still haven't solved my problem.  It seems to me it should be just like IRQs 1, 3 and 5, and the fact that it is non maskeable shouldn't really make any difference for my application, the ISRs are very small.

I will probably end up taking Tom Evan's suggestion and grunt through it the hard way.

Tom

0 Kudos

1,060 Views
Mudwog
Contributor I

I grunted through a little of it and found that, as Tom Evans pointed out, the problem is in my own code.  The non-maskeable IRQ7 is bombing a maskeable interrupt ISR. 

IRQ7 seems to be just like all the other IRQs except that it is non-maskeable.

Thanks for your help.

Tom


0 Kudos

1,060 Views
TomE
Specialist II

Jim said:

> I've been using IRQ7 on the MCF52255 with no issues at all.

The thing about IRQ7 is that it can be used, but you REALLY have to know what you're doing. With the other interrupts, things are more likely to "just work".

The difference is that it is not maskable. That means that you have to guarantee EXTERNALLY to the normal interrupt system that the IRQ7 interrupt routine can't interrupt itself, or if it does, it doesn't do any unrecoverable damage. If the interrupt comes from external hardware (as in your case) then that has to be clocked hardware that has a maximum interrupt rate (so you can guarantee the service routine will run in time) or it has to have a hardware filter on it to guarantee that no noise or glitches  can generate two edges too closely together.

It is EDGE and not LEVEL sensitive. LEVEL sensitive ones re-trigger if they remain asserted and the masking generated by the combination of the CPU IPL and the interrupt controller masking is re-enabled. IPL7 has to go off and then on again in order to trigger. This means two things, both bad. It means you can miss interrupts. If your external hardware doesn't guarantee an off-then-on transition between successive events you won't see the next one (or won't see any more, ever, and that input will seem to be locked up).. If you get "noise" from external hardware, then you'll get multiple interrupts you can't prevent - in the middle of interrupt routines. You can't "disable then enable" the hardware interrupt in the middle of the ISR (like you can do in other interrupts) because a new edge then will make the interrupt re-enter. "Level plus Mask" is way better than "Edge". For more details (concentrating too much on sharing interrupts on a single PC bus), read the following:

Interrupt - Wikipedia, the free encyclopedia

> the problem is in my own code.  The non-maskeable IRQ7 is bombing a maskeable interrupt ISR.

There's another bug then. Maybe your code is written so that each interrupt tries to lock out all other interrupts (by setting the CPU IPL to "7"). Service routines should be written so that higher priority interrupts can interrupt lower priority interrupt. This is very powerful and very useful. This is not the same as the priority level determining which of multiple interrupt will get in next (like you get on more primitive CPUs, like PPCs, ARM, X86 :-), but interrupts interrupting interrupts. Your code should handle this, and has to handle this if you're using IPL7. The only reason I can think of for only having one interrupt at a time is if you have limited RAM with a small stack. With multiple interrupting levels the "worst case stack" has to hold the deepest mainline stack depth plus the maximum depths for all of the interrupts.

A very common practice on simpler CPUs is to use a disable-interrupt and enable-interrupt instruction pair around critical code. That causes all sorts of problems, even in the simpler ones. Code should always call functions that SAVE and RESTORE the interrupt levels. Otherwise you risk having a function that does a disable/enable called from an interrupt service routine, resulting in interrupts being fully enabled. That is a bug - that function can't be called from an ISR, but with save/restore this isn't a problem.

Here's an example of the "asm_set_ipl()" function that you should be using:

http://elk.informatik.fh-augsburg.de/rtlabor/ti-versuche/avr32/FreeRTOS-6.0.1/Demo/lwIP_MCF5235_GCC/...

Here's a previous post detailing its use:

Re: MCF52259 Spurious interrupt, help tracking it down

Tom

0 Kudos

1,060 Views
Mudwog
Contributor I

Thanks for the help.

I had a conflict in one of my other ISR's, a simple thing I fixed it last Saturday.  I've been running fine with IRQ7 since then.
I appreciate teh encouragement.

Tom

0 Kudos

1,060 Views
TomE
Specialist II

IRQ7 is a NON-MASKABLE interrupt level to the CPU. In general, the only way to safely use it is for dire emergencies only. I use it in a project as a software watchdog. If it triggers the device is getting reset very soon after, or getting shut down.

The only way to safely service any level "N" interrupt is to have the CPU set to level "N" while it is servicing that interrupt. That means that only requests of a higher priority can interrupt that interrupt. And more importantly, another level "N" (or the same level "N") can't get in and mess things up.

IRQ7 is different to the core and may be different to other hardware as well. The description of the Status Register contains:

Interrupt level mask. Defines current interrupt level. Interrupt requests are
inhibited for all priority levels less than or equal to current level,
except edge-sensitive level 7 requests, which cannot be masked.

The Interrupt Controller chapter says:

16.1 68K/ColdFire Interrupt Architecture Overview

Level 7 interrupts are treated as non-maskable and edge-sensitive within
the processor, while levels 1–6 are treated as level-sensitive and
may be masked depending on the value of the SR[I] field.

So when you're servicing any other interrupt, the CPU's IPL (in the status register) prevents any changes in the state of the pin that caused the interrupt (or any changes you make to the interrupt controller) from causing any problems, any Level 7 interrupt pin transition (the active edge presented from the interrupt controller to the CPU) can cause the Level 7 interrupt service routine to be re-entered. So if you disable that interrupt in the interrupt controller and then re-enable it, you're likely to get re-interrupted there.

The other bit problem is that you almost always want to protect data structures used by your mainline and the interrupt service routine from each other. If the mainline is changing a shared data structure you want to stop the interrupt service routine from affecting it. You do this by disabling interrupts around that mainline access. You can't do this with IPL7.

> The problem I'm having with IRQ7: is that it permanently disables all of the other interrupts, killing the system.

That may be what it looks like but probably isn't what is really happening. You should run with a debugger connected and try to find out what is really happening.

It may be possible to use IRQ7 as a "general purpose interrupt", but you'd be better off fixing the hardware.

Higher-end CPUs (like the MCF5329 I'm using) allow any priority level to be assigned to the seven IRQ pins and don't force them to be at  the-same-level-as-the-pin-name. That's a lot more flexible than the CF2 CPUs allow.

Tom

0 Kudos

1,060 Views
Mudwog
Contributor I

Tom,


Thanks for the response.

"That may be what it looks like but probably isn't what is really happening. You should run with a debugger connected and try to find out what is really happening."

I was hoping that some forum member who knows the answer would help me out

Tom

0 Kudos

1,060 Views
TomE
Specialist II

If you were running some "standard demo software" then someone else may have run into this problem with it. Since it is all your code, then you're going to have to work through the problems with it.

The only simple answer is "don't use IRQ7".

Tom

0 Kudos