Here is an extract of Section 9 supporting that approach
So attempting to follow example 9-2 and translate in to Pascal I came up the following code. It appears to do everything expected with a WDT in sleep or idle mode except resume the code after a WDTO. I have two loops one where the LED blinks slowly and a following loop with a Fast blink loop.9.4.2 Watchdog Timer NMI
When the WDT module expires in Sleep or Idle, a NMI is generated. The NMI causes the CPU
code execution to jump to the device reset vector. Although the NMI shares the same vector as
a device Reset, registers and peripherals are not reset.
To detect a wake from a power-saving mode by the WDT, the WDTO bit (RCON<4>), SLEEP bit
(RCON<3>) and IDLE bit (WDTCON<2>) must be tested. If the WDTO bit is a ‘1’, the event was
caused by a WDT time-out. The SLEEP and IDLE bits can then be tested to determine if the WDT
event occurred in Sleep or Idle modes.
To cause a WDT time-out in Sleep mode to act like an interrupt, a return from interrupt instruction
(RETFIE) may be used in the start-up code after the event was determined to be a WDT
wake-up. This will cause code execution to continue with the opcode following the
WAIT instruction that put the device into the power-saving mode. Refer to Example 9-2.]
The "Wait" command is inserted between the two loops. I would have expected that after a WDTO that the IF RCON code would return execution immediately after the "Wait" command there cause the fast blink loop to be executed, but that does not happen.
I do not know whether my code is flawed implementing this "return" or my example simply is not suitable to show it is actually occurring. Here is my code modeled after the example 9-2.
If anyone has a working example I would greatly appreciate it if you would share your approach or equally if you spot errors in the code I attempted to duplicate in pascal.
Code: Select all
program WatchDog_Timer;
// Based on Sample Code Example 9.2 page 9 Section 9. Watchdog Timer ands Power Up Timer
// for PIC32MX795f512L family
// With OSC in sleep or idle mode the WDT set for approx 8 sec should wake up and resume the code
// execution immediately after the "Wait" cmd in the main code IF the MCU was in "Sleep" or "Idle" mode
var i:byte;
begin //Main
AD1PCFG := 0xFFFF; // Configure AN pins as digital
TRISB.RB13 := 0 ; // output mode for LED
LATB.RB13 := 1; // Turn on LED
// Unlock OSCON Register
SYSKEY := 0x12345678;
SYSKEY := 0xAA996655;
SYSKEY := 0x556699AA;
//OSCON Now Unlocked
// OSCCONSET := 0x10; // set Power-Saving mode to Sleep mode when a "Wait" is encountered in main
// in sleep mode the LEDs will NOT blink because the Oscillator
// is turned off and no code is executing.
OSCCONSET := 0x00; // set Power-Saving mode to idle mode. When in "Idle" mode and with no "Wait"
// command in main code the slow LEDs loop will blink until the "wait" is encountered because Oscillator is still running and
// Program Counter is still stepping through the code causing the LEDs to blink
// OSCCON.SLPEN := 1; // enable sleep mode (SLPEN) Will enter sleep Mode when a "Wait" instruction
// is executed
SYSKEY := 0x12345678; // relock OSCCON
//WDTCONCLR := 0x0002; // Disable WDT window mode
WDTCONSET := 0x8000; // Enable WDT
while 1 do // endless while loop
begin
// Code restarts here but if in sleep or idle mode
// The IF RCON code should cause it to resume after a
// "Wait" in main loop - again IF in Sleep or Idle mode.
//Start Up Code Area with WDT interrupt check and return code
if (RCON AND 0x18) then // wake from sleep mode (both WDTO and SLEEP bits set
begin
asm
eret ; volatile
nop
end;
RCON := 0; // clear for next attempt
end;
if (RCON AND 0x14) then // if idle mode (both WDTO and IDLE bits set)
begin
asm
eret //; volatile
nop
end;
RCON := 0; // clear for next attempt
end;
if (RCON AND 0x10) then
begin
// WDT Time out - may have been in Sleep or Idle mode
RCON := 0; // clear for next attempt
end;
//. . . user code . . .
// Two LED blink loops (one slow and one fast) with "Wait" command between the two
// Should cause WDT to occur after Slow blink loop but before fast blink loop
// the IF RCON AND 0x..bit command should return execution after the WDTO to
// code right after the "Wait" Command and the fast blink should execute
LATB.RB13 := 1; // Turn LED ON
i := 0;
// SLOW BLINK LOOP
repeat // Slow Blink Loop LED blinks only if OSCCON.SLPEN = 0 (idle mode)
LATB.RB13 := NOT(LATB.RB13);
Delay_ms(250);
i := i + 1;
until i >= {11}21;
delay_ms(500);
WDTCONSET := 0x01; // Service the WDT - with this in loop WDT0 occurs after approx 16 sec with only
// SLOW BLINK begin executed as the code hits the "WAIT" command before the FAST BLINK loop.
// With WDTCSONSET commented out of the code
// SLOW BLINK occurs then WDTO after approx 8 seconds and FAST BLINK again does not execute
// This all occurs because after a WDTO code execution starts at the beginning.
// Now if in sleep or idle mode and with the IF RCON AND 0xNN set is at the code start up then
// according to the documentation, the code should jump to immediately after the "WAIT" commd, but
// does not do that for me.
// With Wait at this location fast blink loop should execute after a WDTO if in Sleep or Idle mode
asm
wait // without this "wait" cmd, LEDs blink in both loops if OSCCON <> 0x10 not in sleep mode
// with Wait 1st repeat loop blinks LED but not second loop
// when OSCCON is in idle mode
nop
end;
// . . . user Code . . .
delay_ms(500);
// code resumption should start here after interrupt from sleep or idle modes
// and fast blink LED loop should execute
// FAST BLINK LOOP
i:=0;
repeat // Fast Blink Loop
LATB.RB13 := NOT(LATB.RB13);
delay_ms(70);
i := i + 1;
until i = 12;
end; // while
end.