EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Is __attribute__ ((interrupt ("IRQ"))) still buggy?

Started by ttl_idiot October 15, 2009
I have some strange problem with screwed-up r14 (link register). It happens in IRQ mode, and seems to be related to an FIQ that interrupts the IRQ. I am currently using GCC 4.3.2, and using optimization. It's a bad time for upgrading GCC at this point, if it doesn't solve this specific problem.

1. Is the __attribute__ ((interrupt ("IRQ")) problem still unsolved in latest version of GCC?

2. Does the problem discussed as __attribute__ ((interrupt ("IRQ")) also apply similarily to __attribute__ ((interrupt ("FIQ")), i.e. when FIQs are interrupting IRQs?

I'd really appreciate input on this. Thanks!

An Engineer's Guide to the LPC2100 Series

Hi ttl_idiot,
I had problems with WinARM, but we finally come up with our 4.4.0 GCC
based
toolchains, and we got no problems with the IRQ preambles (FIQ untested)

Could you please post the objdump with the preambles and post of your
IRQ/FIQ functions?

arm-xxxx-objdump --disassemble yourfile.o

Miguel Angel Ajo Pelayo
http://www.nbee.es
+34 91 120 1798
+34 636 52 25 69
skype: ajoajoajo
2009/10/15 ttl_idiot

> I have some strange problem with screwed-up r14 (link register). It happens
> in IRQ mode, and seems to be related to an FIQ that interrupts the IRQ. I am
> currently using GCC 4.3.2, and using optimization. It's a bad time for
> upgrading GCC at this point, if it doesn't solve this specific problem.
>
> 1. Is the __attribute__ ((interrupt ("IRQ")) problem still unsolved in
> latest version of GCC?
>
> 2. Does the problem discussed as __attribute__ ((interrupt ("IRQ")) also
> apply similarily to __attribute__ ((interrupt ("FIQ")), i.e. when FIQs are
> interrupting IRQs?
>
> I'd really appreciate input on this. Thanks!
>
>
>


--- In l..., "ttl_idiot" wrote:
>
> I have some strange problem with screwed-up r14 (link register). It happens in IRQ mode, and seems to be related to an FIQ that interrupts the IRQ. I am currently using GCC 4.3.2, and using optimization. It's a bad time for upgrading GCC at this point, if it doesn't solve this specific problem.
>
> 1. Is the __attribute__ ((interrupt ("IRQ")) problem still unsolved in latest version of GCC?
>
> 2. Does the problem discussed as __attribute__ ((interrupt ("IRQ")) also apply similarily to __attribute__ ((interrupt ("FIQ")), i.e. when FIQs are interrupting IRQs?
>
> I'd really appreciate input on this. Thanks!
>
This has been discussed in depth and the 'consensus' is that using the __attribute__ approach is not the best way to do the job. Maybe a better characterization: it almost never works and it almost certainly won't nest. I'm pretty sure that's how it came out.

It is far better to write your handlers as normal functions and use a little wrapper to enter and exit.

See http://tech.groups.yahoo.com/group/lpc2000/message/32431 for one example.

I think there has been at least one other approach shown here but I didn't find it. Unfortunately, my Linux box is toast so I can't get at the files.

Search the archives for interrupt wrapper or something like that. Maybe search for __attribute__

Richard

If you don't want to rely on GCC to write your preamble/postamble, you can
use naked, and then asm(...) to write it yourself.

Remember that for FIQ you have your own set of registers that you shouldn't
need to save (unless you're nesting)
static void MyIntHandler(void) __attribute__ ((naked));

static void MyIntHandler(void) /* naked */
{
asm("SUB LR,LR,#4"); /* setup the return address */
asm("PUSH {R0-R12,LR}"); /* store all registers into stack */

asm("LDMFD SP!, {r0-r12,PC}^"); /*restore status and registers, return */
}

Miguel Angel Ajo Pelayo
http://www.espardino.com
+34 91 120 1798
+34 636 52 25 69
skype: ajoajoajo
2009/10/15 rtstofer

> --- In l... , "ttl_idiot"
> wrote:
> >
> > I have some strange problem with screwed-up r14 (link register). It
> happens in IRQ mode, and seems to be related to an FIQ that interrupts the
> IRQ. I am currently using GCC 4.3.2, and using optimization. It's a bad time
> for upgrading GCC at this point, if it doesn't solve this specific problem.
> >
> > 1. Is the __attribute__ ((interrupt ("IRQ")) problem still unsolved in
> latest version of GCC?
> >
> > 2. Does the problem discussed as __attribute__ ((interrupt ("IRQ")) also
> apply similarily to __attribute__ ((interrupt ("FIQ")), i.e. when FIQs are
> interrupting IRQs?
> >
> > I'd really appreciate input on this. Thanks!
> > This has been discussed in depth and the 'consensus' is that using the
> __attribute__ approach is not the best way to do the job. Maybe a better
> characterization: it almost never works and it almost certainly won't nest.
> I'm pretty sure that's how it came out.
>
> It is far better to write your handlers as normal functions and use a
> little wrapper to enter and exit.
>
> See http://tech.groups.yahoo.com/group/lpc2000/message/32431 for one
> example.
>
> I think there has been at least one other approach shown here but I didn't
> find it. Unfortunately, my Linux box is toast so I can't get at the files.
>
> Search the archives for interrupt wrapper or something like that. Maybe
> search for __attribute__
>
> Richard
>
>
>


> Could you please post the objdump with the preambles and post of your
> IRQ/FIQ functions?
>
> arm-xxxx-objdump --disassemble yourfile.o
>

I am quite new to the architechture. Correct me if I am wrong,
but it seems that the only preample of the FIQ is the following. The dump is from the elf file.

00000000 :
0: e24ee004 sub lr, lr, #4 ; 0x4
4: e92d403f push {r0, r1, r2, r3, r4, r5, lr}

and that the returns look like this:

390: e8fd803f ldm sp!, {r0, r1, r2, r3, r4, r5, pc}^

which appears in several other places also in the FIQ handler, two of them are conditional, "ldmhi" and "ldmeq".

And as I said, it is seems to be the link register that suddenly has the wrong value in the IRQ.

I can see from the program, that the problem occours after IRQ-preambling, and before it leaves IRQ. So, it has to do with the FIQ.

I saw the other answers. Sorry to bring up an old issue. I will study the pointed posts. Thank you! Anyway I would like to understand why the above code doesn't work. And just a confirmation that it is the same problem with FIQ over IRQ as with IRQ over user mode. Thanks!

Link registers (LR) aren't independent from mode-to-mode in ARM7 ?
FIQ shouldn't be overwriting your IRQ's LR....

Are the stacks big /separated enough? (I guessing that It could be an
overlapping stacks problem...)

Miguel Angel Ajo Pelayo
http://www.nbee.es
+34 91 120 1798
+34 636 52 25 69
skype: ajoajoajo
2009/10/15 ttl_idiot

> > Could you please post the objdump with the preambles and post of your
> > IRQ/FIQ functions?
> >
> > arm-xxxx-objdump --disassemble yourfile.o
> > I am quite new to the architechture. Correct me if I am wrong,
> but it seems that the only preample of the FIQ is the following. The dump
> is from the elf file.
>
> 00000000 :
> 0: e24ee004 sub lr, lr, #4 ; 0x4
> 4: e92d403f push {r0, r1, r2, r3, r4, r5, lr}
>
> and that the returns look like this:
>
> 390: e8fd803f ldm sp!, {r0, r1, r2, r3, r4, r5, pc}^
>
> which appears in several other places also in the FIQ handler, two of them
> are conditional, "ldmhi" and "ldmeq".
>
> And as I said, it is seems to be the link register that suddenly has the
> wrong value in the IRQ.
>
> I can see from the program, that the problem occours after IRQ-preambling,
> and before it leaves IRQ. So, it has to do with the FIQ.
>
> I saw the other answers. Sorry to bring up an old issue. I will study the
> pointed posts. Thank you! Anyway I would like to understand why the above
> code doesn't work. And just a confirmation that it is the same problem with
> FIQ over IRQ as with IRQ over user mode. Thanks!
>
>
>


> I will study the pointed posts.

Here's another discussion you can look at:

http://www.ovro.caltech.edu/~dwh/ucos/project_AR1803.pdf

It shows non-nested and nested interrupt code using assembler
stubs.

Cheers,
Dave
Since I started with questions, I'm going to declare my conclusions, as concise I possibly can:

The GCC OPTIMIZER disregards details about ARM mode switching.

That's it.

So, as long as you don't let the optimizer touch the code that does the mode switching, you're good. There are of course many ways to do that. One quite straight-forward way to do it, is this:

1. Make a special C file for wrapping-functions for the actual IRQ and FIQ handlers.
2. Declare the wrapper functions __attribute__((interrupt("IRQ"))). Or "FIQ".
3. Make those wrapper functions void with no arguments (of course).
4. The wrapper function implementations should do just one thing - call the actual IRQ or FIQ handler.
5. Make sure the wrapper function module is compiled WITHOUT optimization.

Note that this does NOT take care of another related problem - NESTING, that is, allow IRQ interrupts while another IRQ is being serviced. GCC simply has no support for that, not even dysfunctional.

This posting is dated GCC 4.3.2. Thanks all!


The 2024 Embedded Online Conference