# Forum: ARM programming with GCC/GNU tools nested interrupts

Rate this post
 0 ▲ 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?

Rate this post
 0 ▲ 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/

Rate this post
 0 ▲ useful ▼ not useful
The macros I use for IENABLE and IDISABLE look like this:

  #define IENABLE asm(" MRS LR, SPSR"); /* Copy SPSR_irq to LR */ \ asm("STMFD SP!, {LR} "); /* Save SPSR_irq */ \ asm("MSR CPSR_c, #0x1F "); /* Switch to SYS mode with IRQ enabled*/ \ asm("STMFD SP!, {LR} ") ; /* Save SYS mode LR */ #define IDISABLE asm("LDMFD SP!, {LR}") ; /* Restore SYS mode LR */ \ asm("MSR CPSR_c, #0x92") ; /* Switch to IRQ mode with IRQ disabled*/ \ asm("LDMFD SP!, {R0}") ; /* Restore SPSR_irq to R0 */ \ 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:

  void SW_IRQHandler(void) { // switch to system mode with IRQ enabled //IENABLE; // clear software interrupt VIC1->SWINTCR |= (1 << 15); // halfmsfunction(); // switch to IRQ mode with IRQ disabled //IDISABLE; // write any value to VIC1 VAR VIC1->VAR = 0xFF; } 

Unfortunately this doesn't work.

Rate this post
 0 ▲ 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

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/

Rate this post
 0 ▲ 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

Rate this post
 0 ▲ 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/

Rate this post
 0 ▲ 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.

Rate this post
 0 ▲ 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/

Rate this post
 0 ▲ 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

Rate this post
 0 ▲ 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/

• $formula (LaTeX syntax)$