What if you are not sure interrupts are on or off?

Nick Gammon has written an excellent series of articles on using interrupts. See Gammon Forum : Electronics : Microprocessors : Interrupts

In one of his articles, he writes about turning interrupts off and on in situations when you are using a shared volatile variable. This is to prevent an interrupt changing a variable while the program has only read/written to part of the variable.

He writes in the section Critical sections ... accessing volatile variables

“What if you are not sure interrupts are on or off?

There is a final "gotcha" here. What if interrupts might be off already? Then turning them back on afterwards is a Bad Idea.

In that case you need to save the processor status register like this: …”

My question is – does the processor turn interrupts off and on as part of its general processing, i.e. not user requested? I am writing a very simple sketch which only uses one external interrupt, and I am not using any internal interrupts. Do I need to worry about saving the processor status register.? It’s simple to do – I’m just curious.

Why?

Set the state of a boolean variable at the point where you turn interrupts on or off, then you will always know

I assume because there is a reason they were off in the first place. I'm curious as to whether the processor switches interrupts off as part of its processing work. It too might not want things changed whie it does something.

The processor will only do what its told, however "user requested" may be on a higher abstraction level. e.g. when you use the Setup() and Loop() structure that's part of the Arduino environment, all sorts of initialization will happen. Even before your setup() is executed a Init() function will be called that turns on global interrupts.

During your program execution interrupts are turned off when your programs enters a interrupt service routine (ISR). When your program exits the ISR interrupts will be turned on again.

It doesn't. Interrupts are under the control of your code. Whatever the processor is doing it's doing it because you told it to with the code you fed it.

Suppose you have a common function that is called from both ISR and non-ISR code. Within that function you have a need for a critical section, so you turn off interrupts briefly (this doesn't hurt anything if interrupts are already off from being in ISR context). After the critical section you want to turn interrupts back on only if the function was called in non-ISR context. Otherwise you want to leave them off because you're still processing the ISR.

For AVR-type processors:

#include <util/atomic.h>

void commonFunction() {

	// Non Critical Section Stuff

	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
		// Critical Section Stuff
	}

	// Non Critical Section Stuff
}
2 Likes

Generally speaking, interrupts are disabled for you upon entry to the ISR. They are reenabled for you upon exit from the ISR. No active intervention required on your part.

1 Like

Well, since this is an Arduino forum, it's likely the interrupt that feeds millis() is ongoing in the background. That would be the Timer0 overflow interrupt at about 1ms frequency. So if your code is doing something that shouldn't be interrupted, like some critical timing situation, then you can temporarily disable interrupts. That won't bother the Timer0 interrupt except that it won't continue to count while you have it disabled.

Global interrupts are controlled by the status register. I've never tried it, but I assume the value of SREG can be read by your sketch. The high bit is the interrupt bit.

But below that, each interrupt source is controlled by it's own register setting. So even if interrupts are enabled globally, there may be no specific interrupts currently enabled. So you could for example leave interrupts enabled globally, but disable the Timer0 overflow interrupt, and no interrupts would be taking place.

See @PerryBebbington answer in post #6

See @gfvalvo's answer in #7.

It is the best way to be dumb about how to write a critical sections, like when we have to access variables used in interrupts safely.

It's a reasonable step beyond

  noInterrupts();

// whatever

  interrupts();

a7

Thanks to all who responded. I think I have a fairly clear idea of what's going on now.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.