Go Down

### Topic: Interrupt response time (Read 1 time)previous topic - next topic

#### vpapanik

##### Jun 26, 2012, 04:16 pmLast Edit: Jun 26, 2012, 04:19 pm by vpapanik Reason: 1
Hello !

I would like to ask a simple question regarding external interrupt response time.

I have enabled an external interrupt in void setup() :

Code: [Select]
attachInterrupt(0,MyInterrupt,RISING);

and I am calling a single library function there (MyFunction). The called function belongs to a class (MyLib) that reads/writes something from/to the SPI bus :

Code: [Select]
void MyInterrupt() { MyLib.MyFunction(); }}

I have monitored the bus via a logic analyzer and found out that the response time of the called function was about 17.5 us. I am running on Arduino Pro @ 8 Mhz (SPI bus is set @ 2 Mhz).

Afterwards, when I explicitly copy the code from the library inside the MyInterrupt ISR function, the response time drops to about 8.5 us.

My question is how this large difference is justified.

Ideally, I would like my ISR code to start executing as close as possible to the rising edge of the interrupt pin.

I would really appreciate any help

#### majenko

#1
##### Jun 26, 2012, 04:41 pm
What you want to do is compile your code to assembly and then take a look at what it creates.

I think you'll be surprised by the number of instructions used just to enter an ISR, what with all the storing of context state etc.
Get 10% off all 4D Systems TFT screens this month: use discount code MAJENKO10

#### Tom Carpenter

#2
##### Jun 26, 2012, 04:45 pm
It takes at least 2uS to just enter the interrupt, then it takes quite a bit to jump to another function from the interrupt.
~Tom~

#### vpapanik

#3
##### Jun 27, 2012, 06:50 pm
So, is there any way to speed up the interrupt response ?

#### Tom Carpenter

#4
##### Jun 27, 2012, 07:25 pm
There are indeed. For a start it would be best to use this:

attachInterrupt(0,MyLib.MyFunction,RISING);

That way you are calling your function directly which should improve performace.

Beyond that its hard to say what can be done without seeing more code.

One thing that is a helpful thing to look at is the assembled version of the code.
If you select File->Preferences and check the 'compilation' box next to 'show veribose output'

This will show you where the temporary folder Arduino is using to compile in is located. It will also mention a filename with .elf after it, e.g.
C:\Users\*******\AppData\Local\Temp\build7146138534555655544.tmp\ProjectName.cpp.elf

If you load up cmd (command prompt) and navigate to: <Arduino IDE directory>\hardware\tools\avr\bin\
Then run:
avr-objdump -S C:\directory\to\ProjectName.cpp.elf > C:\your\documents\directory\ProjectName.asm

This will generate the assembler version of your code. If you post that I can give you some pointers in the right direction.
~Tom~

#### vpapanik

#5
##### Jun 27, 2012, 07:29 pm
hey, thanks a very lot ! I will try and come back

#### vpapanik

#6
##### Jul 12, 2012, 07:27 am
Well, I've made some changes. First I changed the Arduino stuff to pure C++ :

init phase :

Code: [Select]
setBit(EICRA,ISC01); // trigger INT0 on rising edgesetBit(EICRA,ISC00); // trigger INT0 on rising edgesetBit(EIMSK,INT0); // enable INT0 (on PORTD pin 2)

handler :

Code: [Select]
ISR(INT0_vect) {code here}

and I inlined the time-sensitive code inside the ISR, rather than a function call.

the result is that the interrupt response dropped to about 7?s.

Actually, the time-sensitive code is the acceleration read from a BMA180 sensor. My concern was to read the acceleration as fast as possible in order to reduce the output noise, as the datasheet suggests.

#### Nick Gammon

#7
##### Jul 12, 2012, 08:29 am
http://www.gammon.com.au/interrupts

In there I look at response times. In particular, using attachInterrupt generates different code to making your own ISR(blah) function.

The reason is, attachInterrupt calls a function indirectly (table lookup) so the compiler must save and restore every possible register that might change. If you make an ISR function the compiler knows which registers to save and restore.

Your change above, and the speed saving, would be accounted for by that.

On my page above I calculated an attachInterrupt call takes at least 5.125 uS (at 16 MHz) but an ISR function only 2.625 uS (that would vary depending on what the function did).

Double those figures to allow for your 8 MHz clock, and add on a bit for what the function actually does, and those figures roughly agree with yours.

Quote
So, is there any way to speed up the interrupt response ?

Doubling the clock speed would help.
http://www.gammon.com.au/electronics

#### vpapanik

#8
##### Jul 12, 2012, 08:41 am
Thanks for the input Nick !

I stick to the 8 MHz Arduino Pro, because it runs @3.3V which is pin-compatible with all my peripherals. However, it is safe to raise the clock to 12 MHz (according to datasheet specs), or even overclock it to 16 MHz, which I have read that it doesn't cause any problems under normal temperatures. I would surely consider it as an option.

#### WizenedEE

#9
##### Jul 12, 2012, 08:50 am
Depending on what you do in the ISR, you could try to make it ISR_NAKED.
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

#### Tom Carpenter

#10
##### Jul 12, 2012, 10:06 am
It's not as simple as making it naked as that removes everything the compiler adds including the reti instruction which means you cant return from the inerrupt unless you add all the required inline assembly yourself.
~Tom~

#11
##### Jul 12, 2012, 10:27 am
...all the required inline assembly yourself.

...also including: saving and restoring SREG; saving and restoring all used registers.  Naked really does mean naked.

#### Nick Gammon

#12
##### Jul 12, 2012, 10:40 am
My advice is: don't try to out-think the compiler. Why buy a dog, and bark yourself?

The compiler will save and restore the registers you use. Why defeat that, and then do it yourself?
http://www.gammon.com.au/electronics

#### MarkT

#13
##### Jul 12, 2012, 11:41 am

Thanks for the input Nick !

I stick to the 8 MHz Arduino Pro, because it runs @3.3V which is pin-compatible with all my peripherals. However, it is safe to raise the clock to 12 MHz (according to datasheet specs), or even overclock it to 16 MHz, which I have read that it doesn't cause any problems under normal temperatures. I would surely consider it as an option.

12MHz is going to cause you headaches compiling a compatible bootloader - people do get away with 16MHz at 3.3V, but note that there is no guarantee that future batches of the chip will work reliably at that speed.  Of course future revisions of the chip might officially support higher clock speeds anyway...
[ I won't respond to messages, use the forum please ]

Go Up