2

I am using an ISR, which is written to be as minimal as possible:

volatile bool interrupt1{};

void ISR1() { interrupt1 = true; }

The interrupt is handled by polling the interrupt1 variable in loop():

if (interrupt1 == true) {

// Do stuff

interrupt1 = false; }

Even though the interrupt signal coming in on the gpio isn't polled, the method described above is instead polling the interrupt variable from loop().

As an alternative to the above, is it possible to use some kind of push logic on the software side whenever an interrupt occurs, instead of continuously polling the interrupt variable? I hesitate to handle the full task from the ISR, as it's performing a lot of things.

What are my options here?

Erik
  • 271
  • 1
  • 15

2 Answers2

10

If the task is pretty short and time sensitive, your best option is to put it in the interrupt handler.

If the task is big and not too urgent (like: it could well wait for a millisecond or so), your approach of polling the flag within loop() is the best one, provided the main program is non-blocking.

If the task is both big and urgent... you may have a difficult problem. You could try both approaches and see which one works best. Or you may try to split the task into a top half (short and urgent) and a bottom half (long but not so urgent). The interrupt handler would then perform the top half and set a flag, whereas the main loop would poll the flag and perform the bottom half.

Edit: for a short discussion on the top half / bottom half approach, see the first paragraphs of this article on Linux kernel development.

Edgar Bonet
  • 45,094
  • 4
  • 42
  • 81
3

Since you tagged it Teensy: You could also reduce the priority of the interrupt, so that it can be interrupted by higher priority interrupts. Thus you can implement interrupts with longer durations without blocking important system functions.

Here is an example using the GPT1 and GPT2 timers running at different priorities:

#include "Arduino.h"
#include "TeensyTimerTool.h"

using namespace TeensyTimerTool;

PeriodicTimer loPrioTimer(GPT1); PeriodicTimer hiPrioTimer(GPT2);

void onLowPrioTimer() // some long task running from interrupt with low prio { Serial.printf(" Start low prio isr @t=%d ms\n", millis());

for (int i = 0; i < 10; i++)
{
    Serial.printf("    lowPriority task %d\n",i);
    delay(10);
}

Serial.println("  Stop low prio isr");

}

void onHiPrioTimer() // high prio, will interrupt the low prio isr { Serial.printf("high priority @t=%d ms\n", millis()); }

void setup() { while (!Serial) {}

loPrioTimer.begin(onLowPrioTimer, 500ms); // GPT1
hiPrioTimer.begin(onHiPrioTimer, 50ms);   // GPT2

NVIC_SET_PRIORITY(IRQ_GPT1, 128); // lowest prio
NVIC_SET_PRIORITY(IRQ_GPT2, 16);  // high prio

}

void loop() { }

which prints:

high priority @t=1057 ms
high priority @t=1107 ms
high priority @t=1157 ms
high priority @t=1207 ms
high priority @t=1257 ms
high priority @t=1307 ms
high priority @t=1357 ms
high priority @t=1407 ms
high priority @t=1457 ms
high priority @t=1507 ms
  Start low prio isr @t=1507 ms
    lowPriority task 0
    lowPriority task 1
    lowPriority task 2
    lowPriority task 3
    lowPriority task 4
high priority @t=1557 ms
    lowPriority task 5
    lowPriority task 6
    lowPriority task 7
    lowPriority task 8
    lowPriority task 9
high priority @t=1607 ms
  Stop low prio isr
high priority @t=1657 ms
high priority @t=1707 ms
high priority @t=1757 ms
high priority @t=1807 ms
high priority @t=1857 ms
high priority @t=1907 ms
high priority @t=1957 ms
high priority @t=2007 ms
  Start low prio isr @t=2007 ms
    lowPriority task 0
    lowPriority task 1
    lowPriority task 2
    lowPriority task 3
    lowPriority task 4
high priority @t=2057 ms
    lowPriority task 5
    lowPriority task 6
    lowPriority task 7
    lowPriority task 8
    lowPriority task 9
high priority @t=2107 ms
  Stop low prio isr
high priority @t=2157 ms
high priority @t=2207 ms
high priority @t=2257 ms
high priority @t=2307 ms

This shows that the high priority timer (running at 50 ms interval) intercepts the low priority ISR which runs every 500 ms for about 100 ms.

Peter Mortensen
  • 435
  • 3
  • 12
luni64
  • 261
  • 2
  • 5