cancel
Showing results for 
Search instead for 
Did you mean: 

EIC->ICR==0 in interrupt?

jodonnell
Associate II
Posted on March 01, 2006 at 10:12

EIC->ICR==0 in interrupt?

8 REPLIES 8
jodonnell
Associate II
Posted on February 24, 2006 at 18:39

I am having a funky problem. I have a P0 output which is toggled in a interrupt and a different P0 output which is changed in main.

In order to prevent stepping on each others toes, I bracket the bit change in main with EIC->ICR=0; and EIC->ICR=1;

This works most of the time, but occasionally, it does not work.

I added an ASSERT(EIC->ICR) check to the very beginning of my interrupt handler and it is failing :-? How is it possible to enter an interrupt when interrupts are disabled globally?

I have scoured my code for any other references to ICR and cannot find any.

Could someone please point me in the right direction?

Thanks,

Jon O'Donnell

NuVo Technologies

cgrun
Associate II
Posted on February 25, 2006 at 19:02

For me it may be a pipeline effect:

You disable interrupt, which took some asm instruction...

and the interrupt can occur during the disable instruction !

So when you enter the interrupt, but the last intruction is terminated, and letting the interrupt diasbled, and the isr is already started !...

To overcome this problem, and correct your program, for me you have to add some instruction in the main programm to ensure that int are really disabled before starting to manage P0 :

EIC->ICR=0

; Some instructions to ensure that no int occur during the last intructions...

; Your P0 stuff now is sure to not be interrupted by the isr

EIC->ICR=1;

Let me know if i'm right.

Regards

Chris.

jodonnell
Associate II
Posted on February 27, 2006 at 16:36

Thanks. I added some do-nothing code after the EIC->ICR=0; and so far it appears to be working. Unfortunately, the bug is very sporadic and hard to reproduce to be guaranteed that it is fixed.

How long is the pipeline? I added 16 instructions, but this is a pain and hurts performance. It is also difficult to guarantee a certain number of instructions between the EIC->ICR=0; and the sensitive code when optimizer/compiler settings change.

Jon O'Donnell

NuVo Technologies

cgrun
Associate II
Posted on February 28, 2006 at 09:02

Hi,

''Three-stage pipeline''

http://www.arm.com/products/CPUs/ARM7TDMI.html

You can add inline assembler, to ensure the number of instruction...

Regards,

chris.

jodonnell
Associate II
Posted on February 28, 2006 at 10:28

I'm sorry, but I do not believe ''three-stage'' does not necessarily means ''three instructions''. Also, I think the core may be influenced by the 128-bit flash memory bus architecture of the STR71x. My original code already had 6 instructions after the interrupts were disabled before the sensitive read.

Are there any authorities answers from ST? I hate to base code on educated guesses or trial-and-error.

Thanks for the help ,

Jon O'Donnell

donald
Associate II
Posted on February 28, 2006 at 11:43

There are almost certainly other issues here.

There is no good downloadable reference on the ARM core that I have found but ARM Architecture Reference Manual by David Seal is inexpensive and almost a necessity.

It says the ARM core checks for interrupt on each instruction boundary - no suggestion it executes the rest of the pipeline - and it does not make sense for it to do this anyway - if you think it through it would only delay the interrupt. It would not save any memory fetches because pipeline is lost on call to ISR and Return from ISR regardless.

You have a couple of other options. You could clear the interrupt enable bit for the peripheral that generates the interrupt with the conflicting code (if it is just one ISR). You must take care if the ISR sets the interrupt enable for it's own interrupt - but this is rare and at least you are only stalling one interrupt source.

The other option is to disable IRQ interrupts in the ARM core. You must be in a priveleged mode and execute something like

MRS R0,CPSR

ORR R0,R0,#0x80

MSR CPSR_c,R0

XXX

The interrupt may still occur between MSR and XXX but not after XXX.

Most compilers have a __disable_interrupts() or similar internal function.

It should be made very clear that EIC->ICR =0; DOES NOT DISABLE INTERRUPTS. It prevents new pending interrupts from being created. Old pending interrupts are still executed. So seeing EIC->ICR==0 in an ISR is entirely possible!

Now it is entirely possible that EIC has delays between clearing of ICR and not generating an IRQ request. It would be good to know how many APB clocks this is. It is safe to assume though there is a window for disaster here so if any ISR sets EIC_ICR you may not even turn the interrupts off! The problem is

Interrupt event happens and EIC generates interrupt

EIC->ICR set to 0

ISR called.

ISR sets EIC->ICR. !! Interrupts STILL enabled !!

Donald.

[ This message was edited by: Donald on 01-03-2006 14:22 ]

donald
Associate II
Posted on March 01, 2006 at 09:50

Better still use core interrupt mask bit instead of EIC_ICR. Then EIC_ICR is not touched under interrupts.

jodonnell
Associate II
Posted on March 01, 2006 at 10:12

Thanks to everyone! Everything works great when I use CPSR to enable/disable the interrupts.

I believe the limitations on using EIC->ICR should be documented because it is not obvious.

Jon O'Donnell