I'm trying to put a PIC32MM0256GPM028 into sleep mode and have it woken up by the Sleep Mode Watchdog Timer (say 1/4 second later- adjustable by SWDTPS anyway). Once it goes to sleep (current drops), it just stays there.
This post seems the closest PIC32 sleep mode with watchdog wakeup failing, but that seems to deal with a reset occurring instead of a wakeup.
I've got this as a standalone function:
void sleep(uint32_t t){ //sleep for t WDT periods
static uint32_t oldRCON=0;
SYSKEY = 0x0;
SYSKEY = 0xAA996655; //unlock
SYSKEY = 0x556699AA;
//OSCCONbits.SLPEN=0; //enable idle
OSCCONbits.SLPEN=1; //enable sleep
SYSKEY = 0x0; //lock
while(t){
WDTCONbits.ON=1; //enable
WDTCONbits.WDTCLRKEY=0x5743; //magic sequence to reset WDT
oldRCON=RCON; //dummy read
RCONCLR=0xDF; //clear all reset reason flags
__builtin_disable_interrupts(); //disable interrupts
asm volatile( "wait" ); //sleep/idle as per SLPEN
Nop();
WDTCONbits.ON=0; //disable
t--;
}
}
WDT Fuses (PS4096 is 4096ms etc, slowed down so I can watch what it does):
// FWDT
//#pragma config SWDTPS = PS1024 // Sleep Mode Watchdog Timer Postscale Selection bits ~in milliseconds
#pragma config SWDTPS = PS4096 // Sleep Mode Watchdog Timer Postscale Selection bits ~in milliseconds
#pragma config FWDTWINSZ = PS25_0 // Watchdog Timer Window Size bits (Watchdog timer window size is 25%)
#pragma config WINDIS = OFF // Windowed Watchdog Timer Disable bit (Watchdog timer is in non-window mode)
#pragma config RWDTPS = PS1048576 // Run Mode Watchdog Timer Postscale Selection bits (1:1048576)
#pragma config RCLKSEL = LPRC // Run Mode Watchdog Timer Clock Source Selection bits (Clock source is LPRC (same as for sleep mode))
#pragma config FWDTEN = OFF // Watchdog Timer Enable bit
//#pragma config FWDTEN = ON // Watchdog Timer Enable bit
The Power Saving Modes section (61130) of the PIC32 manual gives a code snippet (example 10-1) which is even less than what I've got (eg this code deosn't do the syskey unlock):
// Code example to put the Device in sleep and then wake the device using
// the WDT
OSCCONSET = 0x10; // set Power-Saving mode to Sleep
WDTCONCLR = 0x0002; // Disable WDT window mode
WDTCONSET = 0x8000; // Enable WDT
// WDT time-out period is set in the device
// configuration
... user code ...
WDTCONSET = 0x01; // service the WDT
asm volatile( “wait” ); // put device in selected power-saving mode
// code execution will resume here after wake
... user code ...
// The following code fragment is at the beginning of the ‘C’ start-up code
// to find whether the wake from Sleep is due to the WDT
if ( RCON & 0x18 ) // The WDT caused a wake from Sleep
{
asm volatile( “eret” ); // return from interrupt
}
I've got the eret code in my reset and nmi handler and at the start of main, but it's not even getting to reset. I'm not setting window mode off as its disabled in the fuses, and it shouldn't stop the WDT from triggering anyway.
Most of examples etc seem to be for MX/MZ variants, so I wonder if there is a subtle difference I've missed.
How do I get the PIC32MM to go to sleep and resume on WDT?