I can't find any explanation of the difference (if any) between attachInterrupt() and ISR()
Will somebody be kind enough to explain.
Thanks
...R
I can't find any explanation of the difference (if any) between attachInterrupt() and ISR()
Will somebody be kind enough to explain.
Thanks
...R
Where have you seen ISR() ?
Can you provide a link or an example ?
Attachinterrupt() is probably easier and more directly related to the arduino per se.
ISR() is a standard embedded c method for calling an interrupt vector for atmega.
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html
I have the impression that ISR() is very widely used.
I found an example here Arduino Interrupts – uCHobby
//Timer2 overflow interrupt vector handler
ISR(TIMER2_OVF_vect) {
//Toggle the IO pin to the other state.
digitalWrite(TOGGLE_IO,!digitalRead(TOGGLE_IO));
//Capture the current timer value. This is how much error we
//have due to interrupt latency and the work in this function
latency=TCNT2;
//Reload the timer and correct for latency.
TCNT2=latency+timerLoadValue;
}
Am I write in thinking that this code could also be written like this ...
attachInterrupt(TIMER2_OVF_vect, myInt)
void myInt(){
//Toggle the IO pin to the other state.
digitalWrite(TOGGLE_IO,!digitalRead(TOGGLE_IO));
//Capture the current timer value. This is how much error we
//have due to interrupt latency and the work in this function
latency=TCNT2;
//Reload the timer and correct for latency.
TCNT2=latency+timerLoadValue;
}
...R
Or, of course, you could RTFM
Here's the scoop:
ISR() is how you tell the compiler to associate a function with a specific interrupt source. You can use it on any source of interrupts. You can only associate ONE function with each interrupt source, at compile time.
AttachInterrupt() is the arduino "language" function that allows you to associate a function with an external interrupt. You can only use it on external interrupts. You can change the function associated with the interrupt while the sketch is running.
AttachInterrupt() is implemented using ISR(). It is a layer on top of the raw C code that makes it easier and more convenient to use in a sketch.
If you try to use ISR() on one of the external interrupts in your sketch, you will get an error because the arduino core library already associates a function with those interrupt sources. If you want to do the equivalent of AttachInterrupt() on something besides an external interrupt, you will need to use ISR(). See the PCint library in the playground for an example.
A requested feature for arduino is to allow more sources of interrupts to be used with AttachInterrupt, such as the millis timer and the ADC completion interrupt. So far this hasn't happened.
HTH,
AttachInterrupt() is the arduino thing
ISR() is the AVR thing.
Thank you Ckiick. I think I am getting to grips with it now. Please let me know if the following is correct.
In the Atmel Datasheet (Doc 8161, Ch 11) there is a list of 26 interrupt vectors. If I want to use any of them I MUST use ISR().
Ch 12 of the datasheet deals with external interrupts and I MUST use attachInterrupt() to deal with them.
@AWOL, perhaps you would be kind enough to RTFM and tell me where it explains ISR()?
...R
How does an ISR work?
inside the atmega, we have a flag register, Eg, the overflow flag is in the TIMSK register. -->the overflow flag is set->As soon as it is set the internal circuitry know it---> If global interrupts are enabled and if you have local timer interrupts enabled-->It can Vector or go to the ISR() function as soon as that flag is set-->global interrupts are disabled as soon as you enter an ISR(normally)-->You do things in the ISR()-->global interrupts are re-enabled --> You go back where you were..
If you want to know slightly more then, Well, The assembly for a typical interrupt goes like this
INT0isr:
push r0 //Maybe something was there in the register before? so save that
in r0,SREG //Save the Status Register(Has all your basic system flags, overflow, negative, zero et al)
push r0//push it on to the stack to save it
call change //A good assembly ISR does nothing but call another subroutine.
pop r0 //The status register is popped back into r0 register (we do this as we may have used the register in the subroutine, It's mostly a precaution
out sreg,r0 //write the data back into the sreg.
pop r0 // Whatever data that was in r0 in the verrry beginning is written back to it
RETi //This restores the program counter to where it was before the ISR occurred and sets the I flag again(Remember i said it gets disabled when an ISR is called?)
This ISR is for an external interrupt, this had a button connected to it.
Thank you akshaykirti,
I'm sorry my Post #7 wasn't clear enough. I understand how interrupts and interrupt service routines work.
What I would like to do now is confirm that I properly understand Ckiick's explanation in Post #5 about when you create an interrupt routine using attachInterrupt() and when you use ISR().
...R
@AWOL, perhaps you would be kind enough to RTFM and tell me where it explains ISR()?
It doesn't, so that's how you know when and when not to use it.
I believe that attach interrupt is used to setup and work with an external interrupt. Internal interrupts are supposed to be setup by using isr(). Attachinterupt internally probably uses isr as it can be used to achieve the same thing
I'm on a phone. Sorry for any typos etc.
Thank you for the reference Nick.
Going back to my Post #7 does your document mean that my summary was not quite correct and that it is possible to use ISR() to create an interrupt routine for external interrupts as well as for the interrupts listed in Chapter 11?
Perhaps you can also confirm (or correct) my understanding that I cannot use attachInterrupt() for the interrupts listed in Chapter 11?
...R
Robin2:
Thank you for the reference Nick.Going back to my Post #7 does your document mean that my summary was not quite correct and that it is possible to use ISR() to create an interrupt routine for external interrupts as well as for the interrupts listed in Chapter 11?
Perhaps you can also confirm (or correct) my understanding that I cannot use attachInterrupt() for the interrupts listed in Chapter 11?
...R
attachInterrupt() only works for INT0 and INT1, all of the others (including pin-change interrupts) you use ISR for. On Mega's attachInterrupt handles the
other external interrupts too (there are more than two).
Ah, Nick. Where was that page when I was learning about Arduino interrupts? You coulda saved me a grundle of time.
Robin2:
Thank you for the reference Nick.Going back to my Post #7 does your document mean that my summary was not quite correct and that it is possible to use ISR() to create an interrupt routine for external interrupts as well as for the interrupts listed in Chapter 11?
Why ask when you can try for yourself? This compiles OK:
volatile int foo;
ISR (INT0_vect)
{
foo++;
}
void setup ()
{
} // end of setup
void loop () { }
However if you try to do both:
volatile int foo;
volatile int bar;
void anotherISR ()
{
bar++;
}
ISR (INT0_vect)
{
foo++;
}
void setup ()
{
attachInterrupt (0, anotherISR, RISING);
} // end of setup
void loop () { }
You get the error:
core.a(WInterrupts.c.o): In function `__vector_1':
/Applications/Arduino_1.0.4.app/Contents/Resources/Java/hardware/arduino/cores/arduino/WInterrupts.c:297: multiple definition of `__vector_1'
sketch_jun19a.cpp.o:/Applications/sketch_jun19a.ino:9: first defined here
That is because attachInterrupt (indirectly) uses ISR (INT0_vect) as well. So you can't do both.
Perhaps you can also confirm (or correct) my understanding that I cannot use attachInterrupt() for the interrupts listed in Chapter 11?
What MarkT said.
Using ISR for INT0_vect will be potentially faster because the compiler does not have to generate code to push and pop as many registers, potentially. Plus it doesn't have to generate code to go from ISR (INT0_vect) to anotherISR, in this case.
If you look in WInterrupts.c you will see what is happening:
SIGNAL(INT0_vect) {
if(intFunc[EXTERNAL_INT_0])
intFunc[EXTERNAL_INT_0]();
}
So when INTO_vect is called, it tests to see if a handler exists and if so, calls it. This takes time. Note that the source says SIGNAL is deprecated.
This is the same as the ISR macro without optional attributes. Deprecated. Do not use SIGNAL() in new code. Use ISR() instead.
Pity their own code uses it.
TanHadron:
Ah, Nick. Where was that page when I was learning about Arduino interrupts? You coulda saved me a grundle of time.
Ah well, it's there now. And the nice thing about writing pages like that is I learn stuff too. Documenting things means fully understanding them, so it's win win!
Thank you MarkT and Nick.
As far as I can see the answer to my original question is as follows "You can use ISR() with every interrupt vector, you can only use attachInterrupt() with INT0 and INT1".
I'm not sure how we have come onto page 2.
...R
Yes, on the Atmega328, more-or-less as stated here:
http://arduino.cc/en/Reference/AttachInterrupt
That refers to "external interrupts". On some processors (eg. the Mega) you can access the other external interrupts with attachInterrupt.