Yahoo Groups archive

AVR-Chat

Index last updated: 2026-04-28 22:41 UTC

Thread

Re: Any way to make interrupts faster, please?

Re: Any way to make interrupts faster, please?

2010-01-20 by Don Kinzer

>I seem to remember that there's a way to tell the compiler to not do >context saving/restoring when going into an ISR on ATMega chips
If you can do so and how you do so depends on the compiler you're using.  For avr-gcc, for example, you can add the "naked" attribute to the declaration of an ISR.  That attribute directs the compiler not to generate the usual prologue/epilogue (including the reti).  Unless you absolutely know what you're doing, however, it is probably a bad idea to do this.

If you need an ISR that takes less time, you may have to resort to coding it entirely in assembly language.  This can be easy or difficult depending on what needs to be done in the ISR and your experience level.

Another option is to reduce the amount of work done in the ISR and, importantly, avoid calling other functions, doing complicated math operations, floating point, etc.

What does your ISR do and how much time is it taking?  By how much do you need to reduce the execution time?

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

Re: Any way to make interrupts faster, please?

2010-01-20 by Don Kinzer

>I would save and restore SREG but that's all I would do...
That's a recipe for disaster unless your application is so simple that it's doing nothing but looping forever.  What makes you think that you can modify registers in an ISR without concern for what was going on at the time of the interrupt?

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

Any way to make interrupts faster, please?

2010-01-20 by Cat C

Hi,
I seem to remember that there's a way to tell the compiler to not do context saving/restoring when going into an ISR on ATMega chips (I know XMegas, etc can do it, I'm only interested in the ATMega now).

Am I dreaming, or is it possible?

Or is it only possible in assembly, in which case how would an assembly ISR look in the middle of C code, please?

Thanks,

Cat
 		 	   		  

[Non-text portions of this message have been removed]

RE: [AVR-Chat] Any way to make interrupts faster, please?

2010-01-20 by Cat C

I think I'm talking about using "ISR_NAKED" as an attribute, but how do I do that?

For example, if this is my code:
>>>
ISR(PCINT0_vect)
{
    if(bit_is_set(PINB,PORTB2))
    {
        SPCR = 0;
        ui8Status = 1;
    }
}
<<<

I know I'll have to end the routine with "reti(); but how do I specify the "ISR_NAKED" attribute, and how do I know if I need to save any registers?
For the code about, I would save and restore SREG but that's all I would do...

Thanks,

Cat


> To: avr-chat@yahoogroups.com
> From: catalin_cluj@hotmail.com
> Date: Wed, 20 Jan 2010 14:06:54 -0700
> Subject: [AVR-Chat] Any way to make interrupts faster, please?
> 
> 
> Hi,
> I seem to remember that there's a way to tell the compiler to not do context saving/restoring when going into an ISR on ATMega chips (I know XMegas, etc can do it, I'm only interested in the ATMega now).
> 
> Am I dreaming, or is it possible?
> 
> Or is it only possible in assembly, in which case how would an assembly ISR look in the middle of C code, please?
> 
> Thanks,
> 
> Cat
>  		 	   		  
> 
> [Non-text portions of this message have been removed]
> 
> 
> 
> ------------------------------------
> 
> Yahoo! Groups Links
> 
> 
> 
 		 	   		  

[Non-text portions of this message have been removed]

Re: Any way to make interrupts faster, please?

2010-01-20 by Don Kinzer

>I suppose only the Rxx that are inside the ISR in the lss
>file need savin'
That is clearly true.  The problem is, however, that you can't guarantee that some future version of the compiler won't use different registers compared to the one you're using now.  Even with the same version of the compiler, if you build your application for a different AVR the registers used might change.  These are clearly "accidents waiting to happen" and you can probably count on them happening at the most inopportune time.

In situations like this I would highly recommend moving the entire ISR to a .S file where you'll have complete control and the assurance of no surprises in the future.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

RE: [AVR-Chat] Re: Any way to make interrupts faster, please?

2010-01-20 by Cat C

Thank you Don,
In the mean time I looked at the lss file and it looks like I should also save R24.
I didn't know but it looks like SREG is saved through the use of another register (can't push directly).
Apart from that, I suppose only the Rxx that are inside the ISR in the lss file need savin'

So now it's like this:

>>>
ISR(PCINT0_vect, ISR_NAKED)
{
    asm("push R24\n");        //Save R24 because it's used
 11a:    8f 93           push    r24
    asm("in    R24, 0x3f\n");    //Save SREG in R24
 11c:    8f b7           in    r24, 0x3f    ; 63
    asm("push R24\n");        //Push R24 again
 11e:    8f 93           push    r24
    if(bit_is_set(PINB,PORTB2))
 120:    1a 9b           sbis    0x03, 2    ; 3
 122:    04 c0           rjmp    .+8          ; 0x12c <__vector_3+0x12>
    {
        SPCR = _BV(SPIE) |_BV(SPE) | _BV(CPOL); 
 124:    88 ec           ldi    r24, 0xC8    ; 200
 126:    8c bd           out    0x2c, r24    ; 44
        GPIOR0 = sInByte1;
 128:    82 e0           ldi    r24, 0x02    ; 2
 12a:    8e bb           out    0x1e, r24    ; 30
    }
    asm("pop R24\n");        //Restore R24 for SREG
 12c:    8f 91           pop    r24
    asm("out 0x3f, R24\n"); //Restore SREG
 12e:    8f bf           out    0x3f, r24    ; 63
    asm("pop R24\n");        //Restore R24 for itself
 130:    8f 91           pop    r24
    asm("reti\n"); 
 132:    18 95           reti

<<<

See anything wrong with this?

Thanks again,

Cat


 		 	   		  

[Non-text portions of this message have been removed]

Re: Any way to make interrupts faster, please?

2010-01-20 by Don Kinzer

> unless you'd show me how
There are examples in many places, including AVR Freaks, but it is pretty simple in concept.  It gets a little messier if you want to ensure portability to other devices.  I've shown some code below than can all be put in a .S file (note that it must be upper case S not lower case s).

If you don't care about portability you can delete the macros and their usage, replacing them with the normal assembler instructions.  The documentation for the gnu assembler, including the macro syntax, can be found on the Internet.

You'll need to add an include file for the value of sInByte1 and you may have to modify that include file to keep the assembler from seeing parts that it doesn't know how to handle.  This can be done with a conditional like #if !defined(__ASSEMBLER__).

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

// what follows is AVR assembly language code for avr-as
#include <avr/io.h>

// these definitions should go in a .h file
#define IO(x) (_SFR_IO_ADDR(x))

// macro to input from an I/O port to a register
.macro inPort _reg, _port
.if (IO(\_port) < 64)
in \_reg, IO(\_port)
.else
lds \_reg, \_port
.endif
.endm

// macro to output from a register to an I/O port
.macro outPort _port, _reg
.if (IO(\_port) < 64)
out IO(\_port), \_reg
.else
sts \_port, \_reg
.endif
.endm

// macro to skip the next instruction if a bit in an I/O port is set
.macro skbs _port, _bit, _reg
.if (IO(\_port) < 32)
sbis IO(\_port), \_bit
.else
inPort \_reg, \_port
sbrs \_reg, \_bit
.endif
.endm
// end of definitions that should go in a .h file

.section .text

.global PCINT0_vect
PCINT0_vect:
push r24
inPort r24, SREG
push r24
skbs PINB, PORTB2, r24
rjmp 1f
ldi r24, _BV(SPIE) |_BV(SPE) | _BV(CPOL)
outPort SPCR, r24
ldi r24, sInByte1
outPort GPIOR0, r24
1:
pop r24
outPort SREG, r24
pop r24
reti

.end

RE: [AVR-Chat] Re: Any way to make interrupts faster, please?

2010-01-20 by Cat C

That's seems like great advice,  
But I've never done a thing like that before (reminds me of a nice song ;-)
... so it will take me some time to figure it out, unless you'd show me how, seeing that you're already so involved :-)

OR, I suppose I can just put the whole assembly in the C file like I already have some below?
Just take it from the "lss", wrap it with "asm - blah" and I'm done?
I think the s file would save me some "wrapping" so it would be nice :-)

The code that generated the assembly shown is:
>>>
ISR(PCINT0_vect, ISR_NAKED)
{
    asm("push R24\n");        //Save R24 because it's used
    asm("in    R24, 0x3f\n");    //Save SREG in R24
    asm("push R24\n");        //Push R24 again
    if(bit_is_set(PINB,PORTB2))
    {
        SPCR = _BV(SPIE) |_BV(SPE) | _BV(CPOL); 
        GPIOR0 = sInByte1;
    }
    asm("pop R24\n");        //Restore R24 for SREG
    asm("out 0x3f, R24\n"); //Restore SREG
    asm("pop R24\n");        //Restore R24 for itself
    asm("reti\n"); 
}
<<<

Thanks,

Cat

> To: AVR-Chat@yahoogroups.com
> From: dkinzer@easystreet.net
> Date: Wed, 20 Jan 2010 23:19:27 +0000
> Subject: [AVR-Chat] Re: Any way to make interrupts faster, please?
> 
> >I suppose only the Rxx that are inside the ISR in the lss
> >file need savin'
> That is clearly true.  The problem is, however, that you can't guarantee that some future version of the compiler won't use different registers compared to the one you're using now.  Even with the same version of the compiler, if you build your application for a different AVR the registers used might change.  These are clearly "accidents waiting to happen" and you can probably count on them happening at the most inopportune time.
> 
> In situations like this I would highly recommend moving the entire ISR to a .S file where you'll have complete control and the assurance of no surprises in the future.
> 

 		 	   		  

[Non-text portions of this message have been removed]

RE: [AVR-Chat] Re: Any way to make interrupts faster, please?

2010-01-21 by Cat C

Thanks Don,
I'll see if this makes it first of all, until then portability is a non issue, and without that the issue goes away (it can stay in my c file).

Thanks again, that's good to know either way.

Cat

> To: AVR-Chat@yahoogroups.com
> From: dkinzer@easystreet.net
> Date: Thu, 21 Jan 2010 00:35:39 +0000
> Subject: [AVR-Chat] Re: Any way to make interrupts faster, please?
> 
> > unless you'd show me how
> There are examples in many places, including AVR Freaks, but it is pretty simple in concept.  It gets a little messier if you want to ensure portability to other devices.  I've shown some code below than can all be put in a .S file (note that it must be upper case S not lower case s).
> 
> If you don't care about portability you can delete the macros and their usage, replacing them with the normal assembler instructions.  The documentation for the gnu assembler, including the macro syntax, can be found on the Internet.
> 
...
 		 	   		  

[Non-text portions of this message have been removed]

RE: [AVR-Chat] Re: Any way to make interrupts faster, please?

2010-01-21 by Cat C

Hi Don,

I had some time to look at your message again, and I want to thank you for taking the time, much appreciated!
Like I say, I don't know yet if this code will make it, but this is a good lesson in how things SHOULD be done.

Cat
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
> To: AVR-Chat@yahoogroups.com
> From: dkinzer@easystreet.net
> Date: Thu, 21 Jan 2010 00:35:39 +0000
> Subject: [AVR-Chat] Re: Any way to make interrupts faster, please?
> 
> > unless you'd show me how
> There are examples in many places, including AVR Freaks, but it is pretty simple in concept.  It gets a little messier if you want to ensure portability to other devices.  I've shown some code below than can all be put in a .S file (note that it must be upper case S not lower case s).
...
1:
> pop r24
> outPort SREG, r24
> pop r24
> reti
> 
> .end
> 
> 
> 
 		 	   		  

[Non-text portions of this message have been removed]

Move to quarantaine

This moves the raw source file on disk only. The archive index is not changed automatically, so you still need to run a manual refresh afterward.