Delay Interrupt from fireing

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

Delay Interrupt from fireing

3,112 Views
WOLF
Contributor I
I have a MCF52231 Design which has  an interrupt signal connect to Edge port flag 1, and flag 2, Is there a way to have the intrrupt hold off on calling its handler, until I allow the to fire.
 
When the interrupts are resumed, I want any lines that have toggled to then call their handler, so I dont miss the interrupt.
 
I have a loop that looks like
Code:
while(1){   PauseInt();                  // Set interrupt to hold off   MainLoop_Check_FUNCTION();   // Process some code   ResumeInt();                 // resume interrupts   tk_sleep(200*5);             // Sleep process for 5 sec (while interrupts clear)}

 
Thanks
Labels (1)
0 Kudos
9 Replies

654 Views
RichTestardi
Senior Contributor II
An easy way to hold off certain interrupts while allowing others is to use the processor interrupt priority mask in bits 10-8 of the processor Status Register (see 1.5.1 of ColdFire® Family Programmer’s Reference Manual).  This field is defined as:
 

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

 
You then want to assign (thru the MCF_INTC0_ICR*) your e-port interrupts to use, for example, priority 1, and your clock interrupt (or other interrupts which you don't want to hold off) to use, for example, priority 6.
 
Then you can hold off priority 1, 2, and 3 interrupts while allowing priority 4, 5, and 6 (and 7) interrupts by setting the processor interrupt priority mask to 3 (in your PauseInt()).  You can later restore the mask to 0 to allow all interrupts again (in your ResumeInt()).
 
One word of caution -- I don't understand the difference between "priority" and "level" in the MCF_INTC0_ICR*, but have never had a problem with just setting them to be the same -- i.e., 6 and 6, or 1 and 1, etc.
 
0 Kudos

654 Views
WOLF
Contributor I
are you 100% sure that when I change the priority level (to hold of the interrupts), that once i restore the priority level, and interupts that should of be serviced then are serviced, and NOT missed?
0 Kudos

654 Views
RichTestardi
Senior Contributor II
Are you using edge- or level-triggered interrupts with the e-port module?

To guarantee that a level-sensitive interrupt request is acknowledged,
the interrupt source must keep the signal asserted until acknowledged by software. Level sensitivity must be selected
to bring the device out of stop mode with an IRQn interrupt.
Pins configured as edge-triggered are latched and need not remain asserted for interrupt generation. A pin
configured for edge detection can trigger an interrupt regardless of its configuration as input or output.
Interrupt requests generated in the EPORT module can be masked by the interrupt controller module.

If you are using edge-triggered, then I believe you are fine -- once triggered, the e-port will continue to request the interrupt for you until it is acknowledged (it will see what looks like a very slow response time).
 
Again, this is my understanding, but I'd say it always warrants confirmation with the hardware.  (I actually run my e-port interrupt at a *higher* priority than my timer and USB, so I can't confirm it empirically -- I can tell you, however, I've never lost a timer or USB interrupt, on the other end of the equation.)
 
0 Kudos

654 Views
mjbcswitzerland
Specialist V
Hi

I believe that the same can be achieved in two other ways too.

1. Simply mask the edge port interrupts using the appropriate bit in IC_IMRL_0 / IC_IMRH_1. Edge sensitive interripts will set the pending bit but the interrupt will only be serviced once the mask has been removed.

2. Set the corresponding ICR values to 0 ( IC_ICR_0_1..IC_ICR_0_7 / IC_ICR_1_32..IC_ICR_1_38). This gives the interrupt a priority of 0 and so it will never be service even if its mask is cleared. When its priority is raised, by setting ICR again to any level value from 1..7 it will be serviced if pending (latched on previous edge).

Note that the edge ports IRQ1 to IRQ7 have fixed priority (mid-level) so only the level is relevant in their cases - however IRQ8..IRQ15 can have both level and priority assigned.

Regards

Mark

www.uTasker.com
0 Kudos

654 Views
WOLF
Contributor I
Thanks for everyones responses.
 
One more question I'm using Interrupts 1,2,3,5 of EPORT. I know the priority is hard coded for these, but is there any chance that is lets say Int1 fires, and before it finishes int 5 fires. can 5 actually interrupt the the 1st interrupt?
 
in my code i have
 
 MCF_INTC1_ICR33 = MCF_INTC_ICR_IL(1);
 MCF_INTC1_ICR34 = MCF_INTC_ICR_IL(1);
 MCF_INTC1_ICR35 = MCF_INTC_ICR_IL(1);
 MCF_INTC1_ICR37 = MCF_INTC_ICR_IL(1);
 
0 Kudos

654 Views
RichTestardi
Senior Contributor II
Hi,
 
I believe that once you reach the interrupt service routine for interrupt level 1, other interrupt level 1 interrupts are automatically masked.  See section 11.1 (Exception Processing Overview) of ColdFire® Family Programmer’s Reference Manual:

Exception processing can be defined as the time from the detection of the fault
condition until the fetch of the first handler instruction has been initiated. It
consists of the following four major steps:
  1. The processor makes an internal copy of the status register (SR) and then
  enters supervisor mode by setting SR[S] and disabling trace mode by clearing
  SR[T]. The occurrence of an interrupt exception also clears SR[M] and sets
  the interrupt priority mask, SR[I] to the level of the current interrupt request.
  2. ...

Now if you change the SR Interrupt priority mask explicitly, you probably can override that behavior, but that seems dangerous as it can lead to a lot of stack growth -- typically you want to only need to reserve stack space for one instance of each unique interrupt level's handlers...  (I'm assuming you are not doing that.)

 

-- Rich

 

0 Kudos

654 Views
mjbcswitzerland
Specialist V
Hi

When the IRQ is taken, the SR register is set with the level of the interrupt - this stops equally or lower levels from interrupting each other. Higher levels can interrupt after one instruction.

The CW assembler puts the following instruction (not interruptable) at the first line of an irq:
strldsr #0x2700

This masks all interrupts (apart from NMI level 7).

I believe that the way that the assembler (compiler) operates is configurable so that nested interrupts can be defined as default (the mask would be left as it is), but I couldn't find a reference to it when I just checked through the docs. With GCC, interrupts can be specifically defined to be fully masked or interruptable by using the appropriate interrupt definition.

Does any one know the CW equivalent?

Regards

Mark

www.uTasker.com



0 Kudos

654 Views
JimDon
Senior Contributor III
I believe the syntax is:

Code:
;
;   21: }
;   22: 
;   23: 
;   24: static __declspec(interrupt:5) void DMATIM0_ISR()
;   25: {
;   26:  
;
0x00000000                    _DMATIM0_ISR:
;                             DMATIM0_ISR:
0x00000000  0x40E746FC0005           strldsr  #0x5
0x00000006  0x4E560000               link     a6,#0
0x0000000A  0x598F                   subq.l   #4,a7
;
;   27: }
;
0x0000000C  0x4E5E                   unlk     a6
0x0000000E  0x588F                   addq.l   #4,a7
0x00000010  0x4E73                   rte     
0x00000012  0x51FC                   trapf   

 

 

BTW  CW 7.1 for CF has been posted.


0 Kudos

654 Views
mjbcswitzerland
Specialist V
Hi Jim

Thanks - this is good to know.

I just searched the forum with this syntax and found a good complete description from Simon Marsden:
http://forums.freescale.com/freescale/board/message?board.id=CFCOMM&message.id=2021

I knew that I had seen some thing on this before so have set a book mark so that I don't lose it again!

Regards

Mark


0 Kudos