[Top][All Lists]
[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
RE: [avr-gcc-list] interrupt optimization, Nigel Winterbottom, 2006/02/01
Re: [avr-gcc-list] interrupt optimization, Joerg Wunsch, 2006/02/01
Re: [avr-gcc-list] interrupt optimization, David Brown, 2006/02/02