Okay. I had added the disabling of interrupts and re-enable as you mentioned in your original post. This seemed to solve my issue as I was able to go in and out of VLPS for 90+ hours with 4 different devices and did not hang up. However, one of the devices did stop communicating over USB after that.
I have a few follow up questions:
1) When you say "check that there is no reason not to enter sleep mode", what do you mean?
2) For the Disable Interrupts, you mean asm("CPSID i"), right?
3) The conditional part of your code ( if (SYSTEM_CONTROL_REGISTER & SLEEPDEEP....) is that required? Is there really a case where I can wake from VLPS and I won't have SLEEPDEEP set?
4) Is it necessary to disable the clock monitor? I'm not set to handle any clock monitor interrupts, so I didn't bother to shut it off.
5) Do compiler optimizations matter here?
5) Anything else that might come to mind?
I've pasted my code below:
inline void EnterVeryLowPowerStopMode(void)
{
//Prepare for entry into Very Low Power Stop (VLPS) when Sleep-Now is entered with SLEEPDEEP=1
SMC_PMCTRL =SMC_PMCTRL_STOPM(0b010);
//SLEEPDEEP=1
SCB_SCR = SCB_SCR_SLEEPDEEP_MASK;
DisableInterrupts;
//WFI
asm("wfi");
//if ((SYSTEM_CONTROL_REGISTER & SLEEPDEEP) && (SMC_PMPROT & SMC_PMPROT_AVLP)) // VLPS sleep mode exit requires the PLL to be reconfigured
{
#ifdef HW_4 /*24 MHZ*/
/* MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=1,PRDIV=0x0B (24MHz / 12)*/
MCG_C5 = (uint8_t)0x2BU;
#else /*8MHZ*/
/* MCG_C5: ??=0,PLLCLKEN=0,PLLSTEN=1,PRDIV=0x03 (8MHZ / by 4) */
MCG_C5 = (uint8_t)0x23U;
#endif
/* MCG_C6: LOLIE=0,PLLS=1,CME=0,VDIV=0x18 */
MCG_C6 = (uint8_t)0x58U;
while ((MCG_S & MCG_S_PLLST_MASK) == 0) { // loop until the PLLS clock source becomes valid
}
while ((MCG_S & MCG_S_LOCK0_MASK) == 0) { // loop until PLL locks
}
/* MCG_C1: CLKS=0,FRDIV=3,IREFS=0,IRCLKEN=0,IREFSTEN=0 */
MCG_C1 = (uint8_t)0x18U;
while((MCG_S & 0x0CU) != 0x0CU) { /* Wait until output of the PLL is selected */
}
}
EnableInterrupts;
}