EmbDev.net

Forum: ARM programming with GCC/GNU tools nested interrupts


von Rumkugel (Guest)


Rate this post
useful
not useful
Hi,

I have one pretty long function (about 0.5ms) that I want to be executed 
on time, even if other long functions (less important) are running in my 
main loop.

So my Idea was to write this function in an interrupt, that can be 
interrupted by my other, short interrupts (communication etc.)

I am trying to use the IENABLE and IDISABLE macros for the interruptable 
interrupt, but they don't seem to have any effect (or even cause 
crashes)

I'm using STR91FAM with uvision3 and ARM-ELF-GCC

Any ideas?

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Rumkugel wrote:
> I am trying to use the IENABLE and IDISABLE macros for the interruptable
> interrupt, but they don't seem to have any effect (or even cause
> crashes)
>
> I'm using STR91FAM with uvision3 and ARM-ELF-GCC

You will have to understand ARM's interrupt mechanism. Simply reenabling 
interrupts will not work as you might expect. Too long to explain here. 
http://infocenter.arm.com/help/topic/com.arm.doc.dui0203i/Cacbhjjj.html#Bgbeacfi

--
Marcus
http://www.doulos.com/arm/

von Rumkugel (Guest)


Rate this post
useful
not useful
The macros I use for IENABLE and IDISABLE look like this:
1
#define IENABLE asm(" MRS LR, SPSR"); /* Copy SPSR_irq to LR */ \ 
2
asm("STMFD SP!, {LR} "); /* Save SPSR_irq */ \ 
3
asm("MSR CPSR_c, #0x1F "); /* Switch to SYS mode with IRQ enabled*/ \ 
4
asm("STMFD SP!, {LR} ") ; /* Save SYS mode LR */
5
6
#define IDISABLE asm("LDMFD SP!, {LR}") ; /* Restore SYS mode LR */ \ 
7
asm("MSR CPSR_c, #0x92") ; /* Switch to IRQ mode with IRQ disabled*/ \ 
8
asm("LDMFD SP!, {R0}") ; /* Restore SPSR_irq to R0 */ \ 
9
asm("MSR SPSR_cxsf, R0") ; /* Copy R0 to SPSR_irq */

I was thinking about putting my 0.5ms function in an extra interrupt, 
which I trigger from out of another interrupt (every 2ms). Inside the 
software-interrupt I tried to use the macros mentioned like this:
1
 void SW_IRQHandler(void)
2
{
3
    // switch to system mode with IRQ enabled
4
  //IENABLE;
5
6
  // clear software interrupt
7
  VIC1->SWINTCR |= (1 << 15); 
8
      
9
  // halfmsfunction();   
10
11
  // switch to IRQ mode with IRQ disabled 
12
  //IDISABLE;
13
14
  // write any value to VIC1 VAR  
15
  VIC1->VAR = 0xFF;    
16
}

Unfortunately this doesn't work.

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Rumkugel wrote:
> I was thinking about putting my 0.5ms function in an extra interrupt,
> which I trigger from out of another interrupt (every 2ms).

What you are trying to do seems overly complicated. As others have 
suggested, it may even be better calling this function from your 
super-loop. If the function takes that long to execute I am sure there 
is already a significant jitter so that deferring the function call adds 
a negligible overhead.

At least you could put that function call into the original interrupt.

> Inside the software-interrupt I tried to use the macros mentioned like
> this: [...]

But what about other interrupts? After IENABLE() any IRQ can now 
interrupt your SW_IRQHandler(). Are these aware of this and properly 
save/restore the context?

--
Marcus
http://www.doulos.com/arm/

von Rumkugel (Guest)


Rate this post
useful
not useful
I would love to find a way other than nested interrupts...

Here's my problem:
-Every time a new SPI-package is complete (every 2ms) my 0.5ms routine 
has to be executed.
-Multiple short interrupts are needed for communication etc.
-The main loop should be free, so that another developer can simply 
place his routines (possibly long ones) in there without worrying about 
my 0.5ms routine being executed

The first and second point are no problem and is already running. Now 
I'm working on the second point, which turns out to be pretty tricky to 
me, especially since this is all new to me and I have no idea of 
Assembler.

Any Ideas would be very much appreciated

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Rumkugel wrote:
> -The main loop should be free, so that another developer can simply
> place his routines (possibly long ones) in there without worrying about
> my 0.5ms routine being executed

This cannot work with an interrupt driven system. First of all the 
"other routines" will have to wait anyway if this 0.5ms routine executes 
as the super-loop will be preempted. Second, the issue gets actually 
worse since other developers have no control over when exactly this 
happens.

--
Marcus
http://www.doulos.com/arm/

von Rumkugel (Guest)


Rate this post
useful
not useful
It is no problem if the "other routines" are interrupted. They would not 
be time-critical anyway.
The idea is just to be able to use the remaining controller capacity for 
some unrelated calculations, which should not disturb the original 
program.

So I was thinking about a hierarchy like this:

  short interrupts
 (highest priority)

  0.5ms Routine
 (high priority, time critical)

 Other big routines
 (very low priority)


The upper part is already working, if the 0.5ms is placed in the 
super-loop, but now I need a hierarchy level underneath this function. 
This is why I was thinking about moving it into an interruptible 
interrupt.

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Rumkugel wrote:
> So I was thinking about a hierarchy like this:
>
>   short interrupts
>  (highest priority)
>
>   0.5ms Routine
>  (high priority, time critical)
>
>  Other big routines
>  (very low priority)

OK, the picture becomes clearer now. But why this double-nesting of a 
SPI(?) interrupt triggering a Software Generated Interrupt (SGI, ARM's 
official term to avoid confusion with SWI/SVC). Just give your SPI 
interrupt the lowest priority and try to understand how nested 
interrupts work in ARM based systems. Or use a canned solution. Where do 
these macros come from? Are you sure that you won't have to do anything 
else? Look at example code.

--
Marcus
http://www.doulos.com/arm/

von Rumkugel (Guest)


Rate this post
useful
not useful
I got those Macros from an Application Note (AN2593), although I have to 
admit that I do not quite understand everything.
It seems like all the descriptions I find on how to implement nested 
interrupts include Assember code, which I know very little about.

I tried to do exactly what you suggested, by putting the function in the 
SPI interrupt and giving it the lowest priority, but the whole nesting 
thing doesn't seem to work.

Thanks for your help, by the way

von Marcus H. (mharnisch)


Rate this post
useful
not useful
Rumkugel wrote:
> I got those Macros from an Application Note (AN2593)

This takes care of only part of the problem.

> It seems like all the descriptions I find on how to implement nested
> interrupts include Assember code

That is because you need assembler code for implementing nested 
interrupts on ARM cores (Cortex-M variants being an exception of 
course).

Get yourself a book about ARM processors and start reading -- or a 
training. Alternatively hire someone to implement this part for you.

> I tried to do exactly what you suggested, by putting the function in the
> SPI interrupt and giving it the lowest priority, but the whole nesting
> thing doesn't seem to work.

Of course not. This was only for simplifying the whole thing.

Good luck
Marcus
http://www.doulos.com/arm/

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.