Interrupt priority !!

Hi, Does arduino uno's interrupt pins have priority? If yes, may i know which one will execute first? For example, i am using two interrupt pins(interrupt 0 & interrupt 1), if interrupt 0's handler is still executing when interrupt 1 is triggered, what will happen? Additionally , how do i stop the interrupt 0 when interrupt 1 is triggered.

Thanks.

Simple Google search yielded this: http://courses.cs.washington.edu/courses/csep567/10wi/lectures/Lecture7.pdf

A higher priority interrupt will always interrupt a lower priority one. To ensure you process to conclusion you need to disable interrupts while you are in the interrupt. This means you need to make the interrupt handler a lot shorter.

AFAIK the UNO only has one level of interrupt and interrupts are turned off during an ISR. If the ISR for interrupt 0 is executing and interrupt 1 occurs, it will be held until interrupts are turned on again after I0 has finished.

Pete

if interrupt 0's handler is still executing when interrupt 1 is triggered, what will happen?

Interrupts are off during the handling of interrupt 0. Once that handler terminates, interrupt 1 will occur and interrupts will again be off while that handler executes.

how do i stop the interrupt 0 when interrupt 1 is triggered.

You don't need to. Interrupts are off while interrupt 1 is handled.

Pete

uncleeee:
Hi, Does arduino uno's interrupt pins have priority? If yes, may i know which one will execute first? For example, i am using two interrupt pins(interrupt 0 & interrupt 1), if interrupt 0's handler is still executing when interrupt 1 is triggered, what will happen? Additionally , how do i stop the interrupt 0 when interrupt 1 is triggered.

Thanks.

If you have events so close that decently written ISR's colliding makes a real difference then you should probably rethink how you are trying to achieve your goal.

Thanks for replies, may i know which pin has higher priority, which has lower priority? How to disable the higher priority when lower priority is triggered? Or how to disable an Interrupt?

If you are having difficulties relating with more than one interrupt happening at the same time, then you almost certainly have an interrupt service routine (ISR) that takes too long to execute.

Your ISR should set some volatile variables, maybe put info in a buffer somewhere, and then return as quick as possible. Dealing with doing whatever needs doing in response to the interrupt is something your loop() should be doing.

the general pattern is:

void ISR() {
  enqueue the data;
}

void loop() {
  noInterrupts();
  if(any data is enqued) {
    put one enqued item into some local variables;
    dequeue the item;
  }
  interrupts();

  if(we dequeued an item) {
    deal with it;
  }
}

Now as to what 'enqueue' and 'dequeue' means, in the simplest case this just means that you set and reset a volatile flag. In effect, you have a 'queue' with a length of 1. More complex cases might involve incrementing and decrementing a counter, or using a circular buffer with stuff in it.

But your ISR should be fast and then finish. Ideally, you don't do any digital writes or any sort of "work" in the ISR itself.

uncleeee:
Thanks for replies, may i know which pin has higher priority, which has lower priority? How to disable the higher priority when lower priority is triggered? Or how to disable an Interrupt?

People are trying to show and tell, there is no interrupt priority that you can set or probably count on.
The timing involved is sub-60ns for two interrupts to be "at the same time". A difference in wires to the inputs will make more difference than that.

The first one to trigger OWNS the machine and only after does the next one run. Keep the ISR's short and you will have both run and done in perhaps 10 microseconds or less. If your code has to "know" closer than that, perhaps run additional circuits to a comparator that sets a pin to tell which was first.

You can detachInterrupt() to shut one ISR off.

You can disable ALL interrupts which is what every ISR does before the ISR code runs (and enables ALL interrupts on exit),

BUT there are no interrupts able to interrupt an ISR. There are no settable priorities.
You can turn specific interrupts on and off by attachInterrupt() and detachInterrupt().

I hope you know what you want to do. Ask yourself how close the timing has to be in your sketch.

As my design teacher used to say; just because it's possible to cut to very close tolerances, don't design to those where it's not needed.

So, what do you really need?

marco_c:
A higher priority interrupt will always interrupt a lower priority one.

No it won't. The priority only affects the order in which interrupt events are serviced, assuming we are not currently in an interrupt handler.

If yes, may i know which one will execute first?

See my page about interrupts: Gammon Forum : Electronics : Microprocessors : Interrupts

The order of servicing interrupts is listed there, fairly high on the page.

how do i stop the interrupt 0 when interrupt 1 is triggered.

Once an interrupt handler is entered, interrupts are disabled until it exits. Thus you don't need to worry about that.

1 Like

I am thinking of a way that using a slide switch to control the interrupt, is that possible?

@marco_c

A higher priority interrupt will always interrupt a lower priority one. To ensure you process to conclusion you need to disable interrupts while you are in the interrupt. This means you need to make the interrupt handler a lot shorter.

If you are correctly quoting that site then it is WRONG by default on all modern CPU's (and even the computers of the 1960's ) interrupts are turned off when a interrupt occurs.

@op

Does arduino uno's interrupt pins have priority?

Yes they have - but as this only matters if both happen at the same time who cares! You need to cope with A happens before B and B before A. It's just not an issue.

If yes, may i know which one will execute first? For example, i am using two interrupt pins(interrupt 0 & interrupt 1),

External interrupt 0 has priority. Reset beats all others!

if interrupt 0's handler is still executing when interrupt 1 is triggered, what will happen?

The second interrupt is stored and dealt with after you have finished with the first.

Additionally , how do i stop the interrupt 0 when interrupt 1 is triggered.

See above - It's done for you!

Mark

If I interrupt power, any ISR will stop.

@holmes4
I did not write the quote that you attributed to me.
[Edit: Just to clarify this comment. In msg#12, @holmes4 originally attributed the first quote to me. Sometime after I'd pointed out that I didn't make that statement, @holmes4 changed/corrected the attribution to @marco_c so that it now looks like I'm the one who's wrong]

Pete

@holmes4:

If you are correctly quoting that site then it is WRONG by default on all modern CPU's (and even the computers of the 1960's ) interrupts are turned off when a interrupt occurs.

No. You are WRONG. The first computer I programmed (back in the 1960's) had 8 levels of priority interrupt. While an interrupt was being serviced, interrupts at that level and lower were held. But higher level interrupts could occur immediately.

To go back to @marco_c's original comments:

A higher priority interrupt will always interrupt a lower priority one.

In general this is correct but on the 328-based processors there's only one level of interrupt so there are no higher priority interrupts and interrupts are turned off on entry to the ISR.

To ensure you process to conclusion you need to disable interrupts while you are in the interrupt.

No, this is not true. Interrupts are turned off on a 328-based processor during an ISR. On systems with multiple levels of priority interrupt, only interrupts at a higher level than the current one can interrupt and it would be very poor practice to turn off all interrupts (if that's what was meant) thereby blocking the higher levels.

This means you need to make the interrupt handler a lot shorter.

It is always a good idea to make the handler execute quickly but there's no need to obsess over getting it as short as possible. If your only source of interrupts is a 1kHz RTC, an interrupt routine that executes in 200 microseconds is certainly fast enough and there's no need to try to cut it down to less than that.

Pete

holmes4:
If you are correctly quoting that site then it is WRONG by default on all modern CPU's (and even the computers of the 1960's ) interrupts are turned off when a interrupt occurs.

There are exceedingly few statements you can make that would apply literally to ALL CPUs, and your statement, in particular, is simply wrong. MANY, if not MOST modern CPUs support multiple priority levels, and nesting of interrupts. Several support literally hundreds of levels. You have to look no further than the ARM CORTEX M3 used in the Due, which uses the ARM NVIC (Nested Vectored Interrupt Controller). It will not only respond to a higher priority interrupt DURING execution of the ISR for a lower-level interrupt, it will even interrupt the "stacking" of registers triggered by an interrupt request, if a higher-level request arrives before the stacking is complete. Nested prioritized interrupt handling is a VERY common feature of a great many CPUs, and has been for decades, going all the way back to at least the Intel 8259 interrupt controller used with the original 8080 CPU back in the '70s.

Regards,
Ray L.

1 Like

marco_c:
Simple Google search yielded this: http://courses.cs.washington.edu/courses/csep567/10wi/lectures/Lecture7.pdf

A higher priority interrupt will always interrupt a lower priority one. To ensure you process to conclusion you need to disable interrupts while you are in the interrupt. This means you need to make the interrupt handler a lot shorter.

According to the link that you provided, the global interrupt enable is cleared so you don't need to take action to disable them.

holmes4:
by default on all modern CPU's (and even the computers of the 1960's ) interrupts are turned off when a interrupt occurs.

Maybe I misunderstand but on systems with a 6809, an IRQ or FIRQ will not disable the NMI interrupt. As far as I remember, a 68000 with 7 priorities works the same; a higher priority interrupt will not be blocked while a lower level interrupt is handled.

I'm loving these simple AVRs more all the time. But I'm like Bauhaus about code, less is more.

And 200 usec ISR... ouch!

@holmes4
I did not write the quote that you attributed to me.

Fixed

Mark

A higher priority interrupt will always interrupt a lower priority one. To ensure you process to conclusion you need to disable interrupts while you are in the interrupt.

If you are correctly quoting that site then it is WRONG by default on all modern CPU's (and even the computers of the 1960's ) interrupts are turned off when a interrupt occurs.

There are about three ways to think about "interrupt priorities."

  1. Two hardware events happen at exactly the same time - which ISR will execute first? The AVR has this, and the priorities are the same as the vector numbers - lower vectors have higher priority than higher vectors, so INT0 has higher priority than INT1. This essentially only controls which interrupt is "presented" to the CPU, which is completely separate from how the CPU handles it.

  2. If a new interrupt occurs while some other interrupt is already being processed, will the second interrupt cause a new interrupt in the middle of the currently-running ISR? Also known as "preemption." This is actually pretty common. It looks like ARM Cortex will do it, 68000 did it very explicitly (3bits of "interrupt level" input), PIC18s have "high" and "normal" priority interrupts, and it's VERY common for a chip to have a "non-maskable" interrupt pin in addition to their normal interrupts (to handle serious stuff like power-fail.) AVRs don't do this at all, though - when an AVR ISR is entered, ALL interrupts are disabled.

  3. Interrupt sources can be assigned a priority, and you can set which priority of interrupt the system will accept. You can say, in effect, "continue to allow the timer tick interrupt, but disable all communications interrupts." This is closely related to pre-emption, but not entirely. For example, you could implement this in separate interrupt controller logic, even if the CPU interrupt scheme doesn't enable preemption. ARM Cortex definitely has this. AVR doesn't (if you want to disable particular interrupts, you have to have "intimate knowledge" of the peripheral that generates that interrupt.)

So, WRT the OP question: AVR interrupts DO have priority, but it's pretty useless, and doesn't in any way impact the software. If you want to allow preemption, you have to do so explicitly, and it's tricky, annoying, and not recommended.

And it is perfectly alright, and not at all uncommon, for an ISR to re-enable interrupts WHILE executing, so that other interrupts CAN occur. Depending on the source of that first interrupt, it may be necessary to take steps to ensure another of those same interrupts does not re-occur before the first ISR is compete. In the case of a simple peripheral ike a UART, this typically means nothing more than either setting the mask bit (or clearing the enable bit) for that specific interrupt. Again, this is NOT uncommon.

Once again, the hard and fast rules commonly espoused here about "no prioritized interrupts", "no nested interrupts", "ALL interrupt handlers must be as short as possible" demonstrate a lack of real-world experience in complex embedded systems, and how things are VERY commonly done in the real-world. There are MANY valid reasons for using nested interrupts, and MANY valid reasons for handling even long-ish tasks in interrupt handlers, and there is absolutely nothing wrong with doing so, provided it is done properly.

Regards,
Ray L.