I'm having trouble getting the KL17 to enter VLPS mode. I'm wanting to enter VLPS and wake on interrupt from a gpio pin...
I do SMC->PMPROT = SMC_PMPROT_AVLP_MASK; in my initialization code.
Also I disable the following before sleep (and re enable after):
-- the clock disables I figured would be enough for all pins and stuff on those ports.
/* Port B Clock Gate Control: Clock enabled */
/* Port C Clock Gate Control: Clock enabled */
/* Port E Clock Gate Control: Clock enabled */
/* PORTA1 (pin 11) is configured as LPUART0_RX */
PORT_SetPinMux(PORTA, 1U, kPORT_PinDisabledOrAnalog);
/* PORTA2 (pin 12) is configured as LPUART0_TX */
PORT_SetPinMux(PORTA, 2U, kPORT_PinDisabledOrAnalog);
Code I call to try to go to sleep:
static void gotosleep(void)
static void prepsleep(void)
volatile unsigned int dummyread;
/* Set the STOPM field to 0b010 for VLPS mode */
SMC->PMCTRL &= ~SMC_PMCTRL_STOPM_MASK;
SMC->PMCTRL |= SMC_PMCTRL_STOPM(0x2);
/*wait for write to complete to SMC before stopping core */
dummyread = SMC->PMCTRL;
dummyread = dummyread;
void deepsleep (void)
/* Set the SLEEPDEEP bit to enable deep sleep mode (STOP) */
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
/* WFI instruction will start entry into STOP mode */
The behavior is that the code just steps past WFI and keeps running. I'd appreciate any times (other than the inevitable suggestion from that one user to use uTasker).
When using low power modes it is generally advisable to perform the following after each reset:
PMC_REGSC = PMC_REGSC_ACKISO; // acknowledge the isolation mode to set certain peripherals and I/O pads back to normal run state
It is correct to perform
SMC->PMPROT = SMC_PMPROT_AVLP_MASK;
so that the VLPS mode will be accepted. Beware that you should power cycle the HW after making this change in a new code version since it is a write once register and sticks across warm resets.
In VLPS clocks to the modules are disabled so there is no reason to expressly disable them via the clock gate - VLPS allows asynchronous wake up (not needing clocks).
You should disable global interrupts 'before' executing the wfi instruction (the Cortex M0+ wakes from low power modes via a "pending" interrupt and not an interrupt). After the wfi you then need to re-enable the global interrupt, which allows the pending interrupt to be correctly taken.
Otherwise all code is correct so if you immediately are hitting code after the wfi it presumably means that there is a pending interrupt (not necessarily from a GPIO) that has woken the processor. Just before the wfi instruction set a port output high and clear it again after the wfi. Then monitor the pin so that you can see how long the processor was in the VLPS, which will give a clear indication of whether it is immediately waking or whether there is an interrupt source waking it after a certain time.
P.S. Don't use the uTasker project - but read its code (its comments explain all that needs to be known and considered when developing low power applications with Kinetis parts) and copy whatever is needed, or correct other code based on it.
Just search for SUPPORT_LOW_POWER to find all relevant low power code and see fnSetLowPowerMode() [to choose the mode to be used] and fnDoLowPower() [to move to the mode]
Also watch some videos to get see what levels of current can be obtained (for comparisons with your own for confidence that you are in the mode that you expect]
For VLPS operation see also this reference (discussing using UART asynchronous wake-up and effects of clocking) https://community.nxp.com/message/421247#421247