I had a few questions about ISRs that i hoped you could help me to answer, I've used them before but never needed to study their methods of operation in great detail so there are some specific aspects about them, which don't seem that clear in the arduino documentation webpages, and which I've never quite understood but suddenly need to:
1.What happens if another interrupt fires when an ISR is in progress?
I understand that functions called by interrupts will not themselves ever be interrupted but the page at attachInterrupt() - Arduino Reference says "If your sketch uses multiple ISRs, only one can run at a time, other interrupts will be executed after the current one finishes in an order that depends on the priority they have". And I'm not sure how to interpret it. Right now I'm in a situation where I need to use an interrupt routine to detect a pin falling to low and then inside the function that gets called by the interrupt I have quite a few instances of delayMicroseconds() because I am reading a digital signal which is coming in on that pin. Now if after this interrupt function completes I get the same function triggered again and again for every falling edge that may have happened during the message that the function was picking up I could have some severe problems. What must I do to ensure that if during the interrupt any conditions arise which would trigegr the same interrupt again then that re-triggered interrupt will NOT run at all and will not run after the current interrupt finishes? I would be happy with any method which guarantees that any interrupts triggered during another interrupt will not run at all.
2.I know about the need for volatile variables if you have variables which get their values changed by an interrupt ad then need to be read or modified in the main loop of the code. I also know that in the main loop you typically need an
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
code...
}
to contain lines where those volatile variables get copied into non-volatile ones, so as to ensure that the interrupt can't occur while the copying is in progress. But what about the other way around? Is there any need to have volatile variables if they are being set in the main code and read in the interrupt? What about the use of atomic blocks in these circumstances, if a variable which gets modified in the main loop of code needs to be read in an interrupt then should any places in the main code where that variable gets altered be surrounded by an atomic block, hence ensuring that an interrupt which reads from this variable can't trigger at a time when the variable's value is in the middle of being changed?
3.Can a piece of code have multiple interrupts present, I never want them to run at the same time but I've got a need for one interrupt to do free running conversions on an ADC, another for receiving I2C messages from a master device (the arduino is a slave) and replying in an onRequest callback and yet another to monitor digital pin 2? Is it ok o have multiple interrupts present, on the whole these interrupts don't share any variables between them, each just shares things with the main loop of code.
4.If your main script has two separate atomic blocks in it as follows
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
code...
}
//gap between them
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
other code...
}
can an interrupt occur in that "gap between them", I recognise that in that gap no operations is being performed so I guess that there are either zero or very few clock cycles between the two atomic blocks, but I'm unsure as to whether (if there are a non-zero numebr of clock cycles to end one atomic block and start another) an interrupt could be triggered in that gap? if you wanted to ensure that interrupts could trigger in the gap would you be better doing some junk calculations during that gap to occupy a few clock cycles during which an interrupt may trigger?
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
code...
}
int answer=(54+80+100)/2;
int answer2=6;
int answer3=answer+answer2;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
other code...
}
??
5.Is it ever necessary to put atomic blocks into something like
byte number =65;
ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
byte answer=(number+75)/2
}
or does the use of bytes mean that only takes one clock cycle anyway? What if ints of floats or longs were in use? Also is there any practical limit to how large a number of lines can be in an atomic block, or can it be any length so long as you are ok with not having interrupts occur during the block?
6.Do atomic blocks prevent things like delay() from working within them? I understand that delay() involves an interrupt as does the incrementation of millis(). Also can other functions be called from within an atomic block?
7.Does the arduino pulseIn() function require interrupts to be used? The documentation says that pulseInLong() does but doesn't state whether pulseIn does or not? Can pulseIn run within interrupt routines and/or atomic blocks?
8.Lastly, and similar to my first question in some ways, if an interrupt occurs while an atomic block is running then will the interrupt code run after the atomic bock has finished, or not at all?
Thanks