I've got an interrupt on pin D2 which needs to be able to be triggered even while an interrupt on D3 is running. The D3 interrupt is a pretty long one, many milliseconds, and if it gets a D2 interrupt's worth of time (the D2 interrupt is very fast) extra inserted into it somewhere then that is not a problem. But if D2 gets triggered it must happen immediately without waiting for the D3 interrupt to end. When turning interupts back on within the D3 interrupt how should I ensure that only the D2 interrupt can run in such a situation, but that other interrupts such as SPI, timer compare and I2C cannot trigger during the run of the D3 interrupt. I also do not wish to turn on the D3 interrupt within itself.
The design works ok, I'm not looking to make majpr chanegs at present. Can I just check how to ensure that the D2 interrupt can be triggered from within the D3 triggered ISR. Thanks.
I was thinking of something like the below, can you advise on the bits where I've put the question marks? Thanks
void D2interruptFunction(){
cli();//ansolutely ensure interrupts cannot be triggered from within here
//do quick stuff
}//at this point reti runs and takes us back into where we were in either the main loop or D3 depending on where we were when triggered, but somehow need to ensure that this reti won't re-enable global interrupts when we re-enter the D3 loop, is there any special code I must write to ensure this?
voidD3interruptFunction(){
//so long as the flags are working I can cope with the risk of the the D2 being late by a few clock cycles so long as it still executes once sei(); is done
//somehow now disable just the D3 interrupt, how?usual detachInterrupt()??
sei();//now we enable all interrupts but D3 has been disabeld so we know we won't get nested triggering at any more than a single layer of a D2 inside a D3
//do long stuff which should be able to get interrupted by a D2 interrupt
cli();//now disable the global interrupt flag, if D2 gets it's flag set during this time it can execute once we are back in the main loop and any small delay to it doing so won't be a problem
//somehow re-enable the D3 interrupt, how is this done? usual attachInterrupt()??the global flag is presently disabled so it can't start nested exeuting here?
}//at this point reti runs and takes us back to the main loop
void setup(){
//various pin modes
attachInterrupt(digitalPinToInterrupt(2), D2interruptFunction, FALLING);
attachInterrupt(digitalPinToInterrupt(3), D3interruptFunction, FALLING);//but could also make this a LOW instead if that would help
}
//do long stuff which should be able to get interrupted by a D2 interrupt
As has been suggested, don't do "long stuff" in an ISR. Flag the fact that the interrupt has been triggered, maybe save some values then exit then ISR.
Read the flag elsewhere in the program and take the necessary action(s). You will no longer be in an ISR so it is safe for your D2 interrupt to occur and be dealt with.
Of course, it is entirely possible that you don't need to use interrupts at all. What is it that you are doing ?
I don’t think that you can interrupt from within an interrupt ( maybe with low level bodgery) because it’s not a good idea and up can end up stacking interrupts .
Why not have your first interrupt (D3) just set a variable , then the delay is tiny whilst that is serviced . You can deal with the request made outside of the interrupt .If the 2nd interrupt comes along during the first it will be serviced straight after anyway .
Note that there is a priority order with interrupts anyway and that long interrupt routines are not a good idea anyway for various reasons .