Debug Program Hangs using Watchdog Timer

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Am using Atmel Studio 7 with gcc toolchain on a ATmega328p (16MHz).

I get occasional hangs, 2-3 days inbetween - and reckon it is probably stack overflow, but am not sure.

When I know there is a hang in the ISR(WDT_vect), ee_EmergencyBoot is written to. So it would seem obvious to also write the return address to eeprom - after all that is where the hang occurred.

ISR(WDT_vect)
{
	if(LoopWDTResetCnt > 7){
		eeprom_write_byte(&ee_EmergencyBoot,1);
	}
	else{
		WDTCSR  = 1<<(WDIE);//this stops reset on next iteration of ISR(WDT_vect)
		LoopWDTResetCnt++;
	        ProcessWatchdog=true;
	}


}

But that must be obvious to everyone, yet I was able to find virtually nothing in the forums. Another thread suggests using the .naked attribute - but that does not help here. Therefore there is going to be a prologue/epilogue, and I guess my question is 'what is the best way to retrieve the return address from the stack?' 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

iBeta666 wrote:
'what is the best way to retrieve the return address from the stack?'
To know that you would need to know how many bytes back up the stack to look for it. That in turn will depend on how many registers are PUSHed in the prologue to the ISR(). You can look at a disassembly of the ISR to work this out but be wary because from one issue of the compiler to another the number may vary (a post yesterday shows it is DEFINITELY going to change in some future issue of the compiler).

 

But to actually access it then "SP" is defined as a valid symbol in C so *((uint8t *)(SP - 5)) or whatever is the valid contents of a byte that's 5 bytes up on the stack. The issue, as I say is knowing whether to look at -2, -5, -17 or whatever. (clearly a return address is wider than 8 bits - either 16 or 24 bits depending on model of AVR).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Does this help:

 

https://gcc.gnu.org/wiki/avr-gcc#Frame_Layout

 

(I googled "avr gcc stack frame")

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

iBeta666 wrote:
WDTCSR = 1<<(WDIE);//this stops reset on next iteration of ISR(WDT_vect)

I'm lost.  I could be wrong, but don't you need the timed sequence to change WD characteristics?

 

 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I wonder if the gcc function __builtin_return_address works in avr-gcc?

(found here: https://gcc.gnu.org/onlinedocs/gcc/Return-Address.html)

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 

I wonder if the gcc function __builtin_return_address works in avr-gcc?

(found here: https://gcc.gnuorg/onlinedocs/gcc/Return-Address.html)

Not sure, is an ISR() counted as a function() in this respect? A function() knows all the callee's beforehand. OnEditII: Shouldn't matter for the return address though so this might work.

Does this help:

 

https://gcc.gnu.org/wiki/avr-gcc#Frame_Layout

 

(I googled "avr gcc stack frame")

Yes, but it is pretty much what Cliff had already stated. There are no args, so it should be on top of the Pushed Regs. The graphic was nice though:-)

 

I've attached the disassembly, and so the return address should be at SP-16 and SP-17, as per Cliffs' instructions?  I am using c++, but SP seems to also be a valid symbol.

The ISR itself only seems to use R24/R25 yet it Pushes way more regs - maybe the eeprom_write_byte() uses the others?

 

In any case this doesn't look too difficult - just need to recheck if altering the code inside the ISR - or the Optimisation level changes etc.

Which comes back to - why isn't this used as an 'established' technique for debugging Hangs/Stack overflows? OnEdit: maybe just Hangs.

 

 

 

Attachment(s): 

Last Edited: Tue. Jul 11, 2017 - 08:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

iBeta666 wrote:

WDTCSR = 1<<(WDIE);//this stops reset on next iteration of ISR(WDT_vect)

 

I'm lost.  I could be wrong, but don't you need the timed sequence to change WD characteristics?

I'm not really changing characteristics, just the WDIE. When WDIE is 0, the next wdt prescaler pulse will pass through the Reset AND gate while being blocked through the Interrupt AND. Vice versa when WDIE is 1. The timed sequence is needed to alter prescaler etc and if the 4 cycle prescaler setting is not done correctly afterwards - eg if the -OO optimisation is used - then it might start resetting, even when in Interrupt mode. In that case the code line above has to be called in every ISR().

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

iBeta666 wrote:
I'm not really changing characteristics, just the WDIE.

Perhaps.  I guess this part of the datasheet doesn't always apply, then?

. To further ensure program security, alterations to the Watchdog set-up must follow timed
sequences. The sequence for clearing WDE and changing time-out configuration is as follows:
1. In the same operation, write a logic one to the Watchdog change enable bit (WDCE) and WDE. A logic
one must be written to WDE regardless of the previous value of the WDE bit.
2. Within the next four clock cycles, write the WDE and Watchdog prescaler bits (WDP) as desired, but with
the WDCE bit cleared. This must be done in one operation.
 

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

 theusch wrote:

Perhaps.  I guess this part of the datasheet doesn't always apply, then?

 . To further ensure program security, alterations to the Watchdog set-up must follow timed
sequences. The sequence for clearing WDE and changing time-out configuration is as follows:
1. In the same operation, write a logic one to the Watchdog change enable bit (WDCE) and WDE. A logic
one must be written to WDE regardless of the previous value of the WDE bit.
2. Within the next four clock cycles, write the WDE and Watchdog prescaler bits (WDP) as desired, but with
the WDCE bit cleared. This must be done in one operation.

It does always apply. However not once in the above extract is WDIE mentioned, because WDIE is irrelevant to the Timing Sequence.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Am getting the return address using:

	ReturnAddMSB=*((uint8_t *)(SP + 16));
	ReturnAddLSB=*((uint8_t *)(SP + 17));

So that is great.

 

The only thing left is to actually use this in debugging. A possible problem is version changes- I'm using AS7 with Subversion/TortoiseSVN and can imagine it might not be easy to go back to a previous version for ROM debugging (without messing up the Working copy). Have never tried to do this with Subversion but have not had much luck with other SVNs.

Worst case scenario, maybe I could keep a copy of the AS Solution on the Virtual Machine?