Interrupting an interrupt

If I re-enable interrupts using sei() at the start of an ISR, will a higher priority interrupt be able to be triggered, serviced, and then return control to the first interrupt?

Thanks for any help.

Questions like these are easily answered by simply reading the micro controller's datasheet.

When an interrupt occurs, the Global Interrupt Enable I-bit is cleared and all interrupts are disabled. The
user software can write logic one to the I-bit to enable nested interrupts. All enabled interrupts can then
interrupt the current interrupt routine. The I-bit is automatically set when a Return from Interrupt
instruction – RETI – is executed.

IMHO you will just get into an impossible mess that will be impossible to debug.

Just let the first interrupt complete and the second one will be attended to immediately after.

...R

Robin2:
IMHO you will just get into an impossible mess that will be impossible to debug.

Just let the first interrupt complete and the second one will be attended to immediately after.

...R

Thanks, I'd rather not interrupt an interrupt, but how do I solve this problem?

I have three tasks:

  1. An interrupt that runs every 1ms. It updates a milliseconds counter and does some other small jobs, including the determination of whether it is time for task 2 to run.
  2. A task that must run every 50ms. It takes longer than 1ms, so must be interrupted by task 1.
  3. A task that runs once for every 20 times task 2 runs. It takes longer than task 1 and task 2, so must be interrupted many times by tasks 1 and 2.

The priority of the tasks is 1-2-3, with 1 being the highest priority, and task 3 using the processing time that is not required by tasks 1 and 2.

arduarn:
Questions like these are easily answered by simply reading the micro controller's datasheet.

Thanks. I read that before posting my question. It doesn't say if the original interrupt will be resumed. Does that go without saying, or will the original interrupt simply be abandoned, and start from scratch when re-triggered?

Beedoo:
Thanks, I'd rather not interrupt an interrupt, but how do I solve this problem?

I have three tasks:

  1. An interrupt that runs every 1ms. It updates a milliseconds counter and does some other small jobs, including the determination of whether it is time for task 2 to run.
  2. A task that must run every 50ms. It takes longer than 1ms, so must be interrupted by task 1.
  3. A task that runs once for every 20 times task 2 runs. It takes longer than task 1 and task 2, so must be interrupted many times by tasks 1 and 2.

The priority of the tasks is 1-2-3, with 1 being the highest priority, and task 3 using the processing time that is not required by tasks 1 and 2.

That's all very vague. You shouldn't need an ISR to update a millisecond counter. Maybe you should post more details of what your project actually involves and/or the code you have already.

Beedoo:
Thanks. I read that before posting my question. It doesn't say if the original interrupt will be resumed. Does that go without saying, or will the original interrupt simply be abandoned, and start from scratch when re-triggered?

There is a separate paragraph elsewhere that describes stack handling. But basically, yes the original interrupt function will be resumed, otherwise it would be impossible to run code deterministically.

Do you have blocking code somehwere? Have you tried using flags for functions to run in loop() instead of interrupts for task 2 and 3?

Interrupt 1 incrments a counter and sets a flag runRoutine2 = true, when the count reaches 50.

Let loop respond to that flag and run routine two. Interrupt1 will be running in the background while routine 2 executes. Routine 2 runs whatever it is currently doing, as well as canceling the runRoutine2 flag, increments a count, and sets a similar flag to run routine 3.

arduarn:
That's all very vague. You shouldn't need an ISR to update a millisecond counter.

I'm not aware of any hardware capability that runs a millisecond counter. I thought you either had to use the inbuilt Arduino one or make your own. I made my own because I have a few other small jobs that I wanted to be done every 1ms. The other reason I made my own was because (last time I checked) the arduino millis counter was implemented in a very strange way, so that it usually adds 1ms, and then has to play catch up at regular intervals by adding 2ms.

arduarn:
There is a separate paragraph elsewhere that describes stack handling. But basically, yes the original interrupt function will be resumed, otherwise it would be impossible to run code deterministically.

Thanks for explaining that. I'll try and find it, or if you know the page number of the manual please let me know.

cattledog:
Do you have blocking code somehwere? Have you tried using flags for functions to run in loop() instead of interrupts for task 2 and 3?

Interrupt 1 incrments a counter and sets a flag runRoutine2 = true, when the count reaches 50.

Let loop respond to that flag and run routine two. Interrupt1 will be running in the background while routine 2 executes. Routine 2 runs whatever it is currently doing, as well as canceling the runRoutine2 flag, increments a count, and sets a similar flag to run routine 3.

I don't think that would work.

Task 3 takes much longer to run than task 2, and task 2 takes much longer to run than task 1.

If I let task 3 run uninterrupted, then task 2 would be long overdue by the time the code looped around and checked the do-task-2 flag. Thats's why the tasks need to be carried out in strict priority order at all times. It would only work if I scattered task 2 flag checks liberally throughout the main (task 3) loop.

If I was running at 5V and 16MHz I wouldn't be bothering with this question because it would all loop round very quickly. But I'm not, I've got a BOD set to 1.8V, and a 2MHz clock.

Beedoo:
Thanks for explaining that. I'll try and find it, or if you know the page number of the manual please let me know.

For the 328/P, on page 29. There could be more detail elsewhere, but it is mentioned there in a loose way.

If I let task 3 run uninterrupted, then task 2 would be long overdue by the time the code looped around and checked the do-task-2 flag.

Is task 3 a blocking routine? I think you are going to have to post some code. Even at 2MHz, I can't see how task 3 takes longer than 50 ms. That 100,000 processor ticks.

cattledog:
Even at 2MHz, I can't see how task 3 takes longer than 50 ms. That 100,000 processor ticks.

Have you ever tried driving a 128x64 I2C display? Try plotting individual pixels to show some data, and having each data point move across one pixel at a time as new data is acquired once a second. Last time I tried this the lag was apparent as each existing pixel had to be deleted, and redrawn again in its new x-axis location.

No support for hardware scrolling on your screen? If there was, depending on the implementation, you may be able to do tricks with it to gain efficiency.

You need to totally redesign your tasks 2 and 3. See -- BLINK WITHOUT DELAY !!!

You should not be busy waiting for input!.

By the way, running at 2MHz still gives you a fantastlc amount of processing power.

Post your code so we can help with the redesign

Mark

Post your code so we can help with the redesign

Yes, please do. An ISR which takes over 50ms to run at 2 MHz (or over 12.5ms at 16 MHZ) is not good practice.

Can you provide a link to your display and the library you are using?

Beedoo:

  1. An interrupt that runs every 1ms. It updates a milliseconds counter and does some other small jobs, including the determination of whether it is time for task 2 to run.

Things that happen as slow as once every millisecond don't need an interrupt.

You need to post your complete program. My guess is that you are thinking of an unnecessarily complex solution.

...R