Handling a second ISR whilst in a WDT ISR routine

Firstly I am using an Uno as part of my project.
I have a WDT that is used as a long delay (10 minutes) by using an incremental counter every 8 seconds, operating from an ISR.

This reduces the quiescent current for the battery operated circuit, however I want to use a wake switch on pin 2 so that a second ISR wakes the MCU.

Individually both ISR's work fine, but I would like to know what the consequences would be if the second ISR is triggered when in the WDT routine.

Does the second ISR jump into the WDT function at the point where the counter is running ? or does it jump to the main loop after the WDT function call ?

What happens if the second ISR triggers whilst the first ISR has been triggered and is servicing its function ?

Would I have to disable all interrupts when entering an ISR function.

This is a hypothetical question so no code needed.

In general, interrupts are disabled while an interrupt is handled.

Off the top of my head, the first ISR will run to completion, interrupts will then be re-enabled, and the second ISR will run.

An added complication if you have several interrupts on the go is priority. The 328P datasheet lists all the interrupts (section 12 of my datasheet). I could be wrong here, but if you are inside an ISR and 2 or more interrupts occur from different sources, then when you come out of the ISR, the order the new interrupts are processed is determined by their position in the vector table - i.e. lowest vector numbers gets handled first, then the next lowest.

The datasheet says:

The lowest addresses in the program memory space are by default defined as the Reset and Interrupt Vectors. The complete list of vectors is shown in ”Interrupts” on page 66. The list also determines the priority levels of the different interrupts. The lower the address the higher is the priority level. RESET has the highest priority, and next is INT0 – the External Interrupt Request 0.

Thanks for the help. I only had a summary of the data sheet, so was unaware of the full one until I saw page 66 in you reply. :slight_smile:

I downloaded from Microchip and voila, interrupts levels as you said.

I now will be able to set volatile variables up in my ISR which causes the WDT to exit from its interrupt driven time loop.

Amazing when you don't use this stuff for many years, all it takes is a gentle reminder for the knowledge to come back.

An better solution than long watchdog sleep times and nested interrupts is the TPL5110 power timer. Cuts power consumption essentially to zero.

2 Likes

Thanks for the info, which I used to find the TPL5111, which has an enable out pin. This of course can be used as an interrupt for the 328P

Using the TPL5111 as a timer with interrupt would of course lower quiescent current a lot more than the WDT routine.

However at present I will stick with the WDT, until it is time to finalise the project. less hardware cost until later . :slight_smile:

Curious, how do you setup your WDT with an interrupt? I would think the WDT should be 100% independent of the controller proper.

An option on the 328P is to configure the WDT to generate an interrupt rather than a system reset. It's used in that configuration, mainly for battery operated setups, (with an 8 sec timeout) to bring the 328P out of sleep mode roughly every 8 seconds.

It is that very independence which is the crucial factor. The WDT has its own clock, so the rest of the MPU can be put into a deep sleep, thus saving power. The interrupt service routine generated from the WDT, with a maximum of 8 seconds, can be used to increment a counter in a while loop, waking the MPU after the count has finished.

I have seen figures of 25 - 30 uA for the WDT, including servicing the interrupt.
Great for battery or solar powered monitors.

If you really want to save on power, use a Sparkfun ProMini. No power hungry TTL-to-USB converter and you can remove the LED.

That's what I was thinking. I must have misunderstood your OP, it seemed like you were using a "regular" interrupt to extend the WDT time out time.

I will just be using an Atmega328P with the oscillator crystal and caps, with 10uF cap and 100nF decouplers on the analogue and digital supplies.

Bare minimum.

The WDT can be set up to generate its own interrupt

Snippet of code:


 set_sleep_mode(SLEEP_MODE_PWR_DOWN);
	sleep_enable();

  	while (uiSleepCounter < iPeriod) 
  {

		// Turn of Brown Out Detection (low voltage). This is automatically re-enabled upon timer interrupt
		sleep_bod_disable();

		noInterrupts(); // Make sure Interrupts are turned off

		// clear/set various flags
		MCUSR = 0; 	// disable reset
		WDTCSR = bit (WDCE) | bit(WDE); // set interrupt mode 
    // Now set the time out for the WDT
		WDTCSR = bit (WDIE) | bit(WDP3) | bit(WDP0); // set WDIE, and 8 second delay

		wdt_reset();

		// Allow interrupts now
		interrupts();

		// And enter sleep mode as set above
		sleep_cpu();
	}

The sleep counter is incremented in the ISR and the period is set externally for any period of time, multiplied by 8 seconds that is required.

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