MCF5485 EPORT Interrupts

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

MCF5485 EPORT Interrupts

462 Views
felben
Contributor I

I have two external interrupt sources tied to the 5485 EPORT module.  One source is tied to IRQ2 the other to IRQ3.  Using a logic analyzer I can see that when IRQ2 is asserted during assertion of IRQ3 the ISR for IRQ2 never gets control.  It is as if the 5485 thinks IRQ2 never happened in this case.

 

I have tried using both falling-edge and level triggering and both behave the same way.  I am not using CodeWarrior (am using gcc) so the problem is not related to the much-discussed status register mask issue there (but even if it was, shouldn't that simply delay recognition of IRQ2 rather than cause it to be completely ignored?).

 

Bottom line, I am trying to understand what can make the Coldfire forget about a lower priority IRQ that happens to be asserted while a higher priority IRQ is asserted.  I am perfectly fine with IRQ3 preempting IRQ2 (I expect that), but only if IRQ2 is eventually recognized and processed.

 

Thanks for any thoughts and assistance.

Labels (1)
0 Kudos
2 Replies

343 Views
felben
Contributor I

Almost as soon as I finished posting the question I solved the problem.  Of course, it was my stupid stupid software.  For posterity and possible help to others as dumb as I was today...

 

Here is the problem... in the ISR for IRQ3 (the higher priority IRQ) I was writing to the MCF_EPORT_EPFR register in order to clear the interrupt condition but instead of simply writing to the one bit I needed to clear (bit 3 in this case), I was or'ing the bit into place... MCF_EPORT_EPFR |= MCF_EPORT_EPFR_EPF(3)... however, when IRQ2 happens during IRQ3 processing (or any other time) it posts to bit 2 of the EPFR and or'ing the register with itself clears that IRQ as well as IRQ3.  I was causing IRQ2 to be cleared inadvertently.  All I had to do was get rid of the or and change to a straight write MCF_EPORT_EPFR = MCF_EPORT_EPFR_EPF(3) of the register (in both ISRs) and everything is now working exactly as expected.  Maybe this will help someone else one day.

0 Kudos

343 Views
TomE
Specialist II

These "write one to clear" registers are designed for "an even greater purpose".

 

Instead of "service one interrupt and clear it" the "write one to clear" register allows you to:

 

nInterruptsPendingNow = INTERRUPT_STATUS_REGISTER

if (nInterruptsPendingNow & INTERRUPT_ONE)

{

    Service Interrupt one;

}

if (nInterruptsPendingNow & INTERRUPT_TWO)

{

    Service Interrupt two;

}

... And so on for 3, 4, 5

INTERRUPT_STATUS_REGISTER = nInterruptsPendingNow;

 

What you've done in the above is captured the pending interrupts at the one point in time, serviced all of them and then cleared just them. Any new ones that have popped up will be caught the next time. That also gives you control in software of the priority and order of servicing a group of interrupts. In most cases you'd want to service receive interrupts before transmit one, for instance.

 

In some cases it might be preferable to read, then clear, then process. It depends on the details of what happens if another one comes in before-after-during the servicing of the previous one:

 

nInterruptsPendingNow = INTERRUPT_STATUS_REGISTER

INTERRUPT_STATUS_REGISTER = nInterruptsPendingNow;

if (nInterruptsPendingNow & INTERRUPT_ONE)

...

 

Tom

 

0 Kudos