avr-gcc-list
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [avr-gcc-list] interrupt optimization


From: David Bourgeois
Subject: Re: [avr-gcc-list] interrupt optimization
Date: Thu, 02 Feb 2006 18:27:47 +0100
User-agent: Opera M2/8.51 (Win32, build 7712)

Second, it dosen't matter what the compiler is doing, an ASM coded int needs to save SREG, and any regs you modify during the int, and that's all.

Not really. This is a very common problem and the compiler could be smarter about it.

Basically the function should be compiled as:

   push just the registers needed to decrement "sampling"
   decrement sampling
   if not zero goto exit:
        push the extra registers needed in the function
        call the function
        pop the extra registers
   exit:
   pop just the registers needed to decrement "sampling"

The problem is that the compiler pushes all the registers regardless of the code path. This is understandable, but it _could_ be better.

One thing that might work (but I never tried it) is to code the sampling decrement in assembly in a "naked" interrupt handler and mark the other function as "interrupt" so that it pushes everything.

Then, to call the function, just do in assembly:
        in __tmp_reg__, SREG
        push __tmp_reg__
        call _not_inline_function_

The __tmp_reg__ (SREG) push is made to match the IRET instruction from the now "interrupt" function.

This is still a little inneficient as some registers will be pushed twice, but is only inneficient when the function is actually called and not in all interrupt calls.

I hope this helps,


I'm always ashamed of the way I'm over complicating my questions. You wonderfully summed it up in a couple lines.

Your solution is very interesting. I was looking for a way to force a function to save/restore all registers it uses. Marking the function as "interrupt" (__attribute__ ((signal))) indeed did the trick. I end up with 2 RETI following each other but that should not be a problem. Thanks for the tip.

For information only, here's a summary of the other suggestions I had:
 solutions which .

- the best way is to have the complete ISR in assembly but can be troublesome if the function is complex;

- if I can live with some delay between the ISR & execution, it may be possible to move the function to the main loop and keep a short and simple ISR;

- using a naked interrupt and some inline asm for all push/pop works if I directly use the register names in asm push statements but then the code may be corrupted if for any reason the compiler uses different registers (code change, compiler update,...)
i.e.
        push    r0
        push    r24
        if :
                push rxx
                ...

- using a naked interrupt and some inline asm for all push/pop doesn't work if I use the variable names because the compiler does load the variables in registers before doing the first inline asm statement which is what it should do but not what I want.
i.e.
        __attribute__ ((naked)) ISR(SIG_OVERFLOW0)
        {
            asm("push %0" :: "r" (sampling));
        ...

gives the following asm:
        00000394 <__vector_16>:
        394:    80 91 0f 01     lds     r24, 0x010F
        398:    8f 93           push    r24
        39a:    80 91 0f 01     lds     r24, 0x010F

Thank you all guys for your valuable help

--
David Bourgeois




reply via email to

[Prev in Thread] Current Thread [Next in Thread]