# WDT brain breaker

#### Picbuster

Joined Dec 2, 2013
1,026
Hi,

A real WDT brain breaker
I want to use the WDT with a Pic 18f8722. No problem however, I want an extra function!
Each function will carry an unique number like Function_Number.

When the WDT runs out it will reset the pic. >> no problem working.

The function number indicate which function hangs.
But!
That information is set to zero during the reset (should be).

The RCONbits.To is set to zero after reset. ( if(!RCONbits.TO) { Report_Hang();} // working

How to remember the Function_Number without using flash or external memory?

I want to produce Function_Number after the reset caused by the WDT.

Whom knows?

Picbuster

#### nsaspook

Joined Aug 27, 2009
8,241
Not sure why you need this but if you maintain power, data in SRAM is intact between reboots unless some runtime code zeros or initializes it out. So one way is to tell the runtime not to zero it out. Note: If it's stored in SRAM the data will NOT survive a power cycle.

You can try this.

XC8 manual
Variables whose contents should be preserved over a reset, or even power off, should be qualified with the persistent qualifier, see Section 3.4.8.1 “Persistent Type Qualifier”. Such variables are linked at a different area of memory and are not altered by the runtime startup code in any way.
...
3.4.8.1 PERSISTENT TYPE QUALIFIER By default, any C variables that are not explicitly initialized are cleared on startup. This is consistent with the definition of the C language. However, there are occasions where it is desired for some data to be preserved across a reset. The persistent type qualifier is used to qualify variables that should not be cleared by the runtime startup code. In addition, any persistent variables will be stored in a different area of memory to other variables. Different psects are used to hold these objects. See 3.15.2 “Compiler-Generated Psects” for more information. This type qualifier may not be used on variables of class auto; however, statically defined local variables may be qualified persistent. For example, you should write: void test(void) { static persistent int intvar; /* must be static */ // ... } If the XC8 option, --STRICT is used, this type qualifier is changed to __persistent.
The "persistent" keyword preserves values across reboots, not power cycles.

Store the info in a Function_Number "persistent" data structure at assigned block location X. Update the structure with a 32-bit timer count as a hash and a CRC check value for the Function_Number data structure. After a reboot read and check the data structure at assigned block location X.

I just checked some old C18 code for how I checked 8722 boot codes.
C:
#ifdef    __18F8722
if (STKPTRbits.STKFUL) {
STKPTRbits.STKFUL = 0;
putrs2USART("\r\n");
term_time();
putrs2USART("\x1b[7m Restart from Stack Full. \x1b[0m\r\n");
}
if (STKPTRbits.STKUNF) {
STKPTRbits.STKUNF = 0;
putrs2USART("\r\n");
term_time();
putrs2USART("\x1b[7m Restart from Stack Underflow. \x1b[0m\r\n");
}
#endif

if (WDT_TO) {
putrs2USART("\r\n");
term_time();
putrs2USART("\x1b[7m Restart from Watchdog Timer. \x1b[0m\r\n");
}

if (EEP_ER) {
putrs2USART("\r\n");
term_time();
putrs2USART("\x1b[7m Possible EEPROM write error. \x1b[0m\r\n");
}
https://microchipdeveloper.com/8bit:wdt

#### peterdeco

Joined Oct 8, 2019
343
When the function number changes, write it to eeprom. When it resets and goes to the beginning of the program, read the eeprom location.

#### John P

Joined Oct 14, 2008
1,890
Writing to EEPROM every time a function is called would lead to a lot of writes to EEPROM! And each one ties up the memory for a few msec, so you can't be doing it very rapidly anyway.

You could use some external pins to all you to tell what the chip is doing, using a scope or logic analyzer.

Otherwise, I can't see an alternative to relying on some area of internal RAM which won't get changed during a reset, or overwritten when the chip starts up again. I suppose you'd need to have a lock-unlock process to allow you to interrogate the processor for the results of the last run, and then allow data for the present run to be stored in its place.

#### Sensacell

Joined Jun 19, 2012
2,774
Define an area in RAM to be a small revolving buffer- with a pointer at the first location.

Whenever you call a function, write its "function number" to this buffer and increment the pointer.

As long as you dont clear RAM or kill the power, there will be a list of the last few funtions called sitting there in RAM.

#### JohnInTX

Joined Jun 26, 2012
4,380
You could emulate the hardware WDT using a timer interrupt. Clear the timer periodically like you would the hardware WDT. If the timer ever runs to overflow, it interrupts and the offending address is on the top of the stack. Save that somewhere persistent, set a flag and execute the 'reset' instruction. If you want a 'trace' pop the stack until the stack pointer is 0, saving each top of stack in order. Use those return addresses to trace back through the call levels.

If you invoke the clearing of the timer as a macro, you could redefine it as the hardware 'clrwdt' for normal use without changing the source.

I have used a similar technique for logging fatal errors. The system called FATAL and logged the return address from TOPSTACK then restarted. When RESTART detected a saved log, it printed it out and continued. A look at the listfile showed where the problem was. Nice.

Just my .02

#### Picbuster

Joined Dec 2, 2013
1,026
You could emulate the hardware WDT using a timer interrupt. Clear the timer periodically like you would the hardware WDT. If the timer ever runs to overflow, it interrupts and the offending address is on the top of the stack. Save that somewhere persistent, set a flag and execute the 'reset' instruction. If you want a 'trace' pop the stack until the stack pointer is 0, saving each top of stack in order. Use those return addresses to trace back through the call levels.

If you invoke the clearing of the timer as a macro, you could redefine it as the hardware 'clrwdt' for normal use without changing the source.

I have used a similar technique for logging fatal errors. The system called FATAL and logged the return address from TOPSTACK then restarted. When RESTART detected a saved log, it printed it out and continued. A look at the listfile showed where the problem was. Nice.

Just my .02
Thank to all for inputs provided. A timer interrupt could do the trick but I have to investigate like:
setup timer
reset in main loop
put a while(1){} in a routine and see if the interrupt keeps working.
Tested with the keep alive led 1 sec timer one.
And Yes it is.
Conclusion your solution is working!! And will be used in future.
//***********************************************************************//

But I do like to do the same with the WDT just to bully my brains.

The Reset is clearing all despite C's persistent type . ( power remains connected)
In the manual are some timer setting and other registers with a remarks like 'not affected by reset' however no luck it runs to zero.
I am sitting in the corner and crying my little head off.
Anyway it's just an exercise to keep my limited, old overworked and slow brains in shape.

Picbuster