I have a MKL27 that I want to put in to Very Low Leakage Stop mode 3 (VLLS3).
I am using the code below. The Power Mode Status register always indicates that the mode always remains 'Run'.
Does anyone see what I might have wrong with the code below?
SMC_PMPROT is a write once register and it is not being written anyplace else in the system.
/* One time write - allow VLPR, LLS and VLLS modes */ /* Setup Power mode protection register */ SMC_PMPROT = SMC_PMPROT_AVLP_MASK | /* Allow Very-Low-Power Modes */ SMC_PMPROT_AVLLS_MASK | /* Allow Very-Low-Leakage Stop Mode */ SMC_PMPROT_ALLS_MASK; /* Allow Low-Leakage Stop Mode */ SMC_PMCTRL = SMC_PMCTRL_STOPM(4); /* 4 = Very Low Lekage Stop VLLSx */ SMC_STOPCTRL = SMC_STOPCTRL_VLLSM(3); /* 3 = VLLS3 */ SCB_SCR = SCB_SCR_SLEEPDEEP_MASK; /* Deep Sleep = 1, SLEEPONEXIT = 0 = do not sleep when returning to Thread mode */ (volatile uint8_t) SMC_PMCTRL; /* Dummy read to ensure the register is written before entering low power mode */ while( 0U != (SMC_PMSTAT & 0x01) )/* Blink as long as remain in RUN mode */ { LED_HEAT_RED_TOGGLE(); delay_ms( 100U ); }
Hi Bob,
This code is the sample code from Kinetis KL25, it also the recommended code for KL series, this function can enter the VLLS3 mode successfuly, you can try to use it, whether your KL27 can enter the KL27 successfully? You need to check the MCU power consumption to verify the low power function.
SLEEPDEEP must be used, the ARM Cortex-M4 and M0+ cores uses the state of the SLEEPDEEP bit in the SCR to control which state the core platform enters when the WFI instruction is executed. If the SLEEPDEEP bit is set Deep Sleep or core Stop mode is entered.
Have a great day,
Jingjing
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Yes, it is the example code.
I still believe it is wrong based on my explanation above.
Hi BOB,
About the dummy read, your explanation is correct! That sample code is older version for kl series, in our KSDK for KL27, it is updated with SMC_PMCTRL.
This is the new code to enter VLLSx mode:
Thanks a lot for your explanation!
Have a great day,
Jingjing
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
Hi BOB PADDOCK,
You missed the "WFI" instruction:
You can refer to the following code:
void enter_vlls3(void)
{
volatile unsigned int dummyread;
/* Write to PMPROT to allow VLLS3 power modes */
SMC_PMPROT = SMC_PMPROT_AVLLS_MASK;
/* Set the STOPM field to 0b100 for VLLS3 mode */
SMC_PMCTRL &= ~SMC_PMCTRL_STOPM_MASK;
SMC_PMCTRL |= SMC_PMCTRL_STOPM(0x4);
/* set VLLSM = 0b11 */
SMC_STOPCTRL = SMC_STOPCTRL_VLLSM(3);
/*wait for write to complete to SMC before stopping core */
dummyread = SMC_STOPCTRL;
dummyread++;
/* Now execute the stop instruction to go into VLLS3 */
#ifdef CMSIS
/* Set the SLEEPDEEP bit to enable deep sleep mode (STOP) */
SCB_SCR |= SCB_SCR_SLEEPDEEP_MASK;
__wfi();
#else
stop();
#endif
}
void stop (void)
{
/* Set the SLEEPDEEP bit to enable deep sleep mode (STOP) */
SCB_SCR |= SCB_SCR_SLEEPDEEP_MASK;
/* WFI instruction will start entry into STOP mode */
#ifndef KEIL
// If not using KEIL's uVision use the standard assembly command
asm("WFI");
#else
// If using KEIL's uVision, use the CMSIS intrinsic
__wfi();
#endif
}
Wish it helps you!
Have a great day,
Jingjing
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
You can refer to the following code:
Isn't that code going to have issues with randomly not having SLEEPDEEP not being used?
The purpose of the dummy read of SMC_STOPCTRL is to is to make sure the bus write of STOPCTRL has completed before the part shuts down. If the write has not completed then the part will be in the wrong mode when the part shutsdown.
It is the last bus transaction before the WFI instruction that needs protected. So STOPCTRL is unneededly protected (it is not the last write before WFI) while SLEEPDEEP needs protected and is not.
Really it should be the Data Synchronization Barrier (DSB) instruction that should be used in addition to the dummy read (depends on the part, the M0(+) does not have a write buffer). See ARM Information Center on DSB also see the linked AppNote 321 at that page.
Perhaps there something that I am not understanding about SCB_SCR and SMC_STOPCTRL being on different internal buses maybe?
"... missed _WFI..."
Actually, no I didn't.
The _WFI is after the while() loop that I did not show.
My original question remains when are the bits in SMC_PMSTAT valid?
If _WFI is used then the clocks are stopped so it is impossible to read SMC_PMSTAT.
If the part wakes up via reset then the part is back in RUN Mode.
It really seams that the only two bits of SMC_PMSTAT that can be read are 0x01 for RUN and 0x04 for VLPR (the part is actually running for those two). So is the part setting the other bits that are impossible to read (the part is not running)???
See 14.4.4 Power Mode Status register (SMC_PMSTAT) in the data sheet.
Hi BOB,
Thank you for your more information.
SMC_PMSTAT will valid after the according power mode is entered!
The VLLSx mode should be entered when the "__WFI" instruction is executed, for details, you can refer to our application note AN4503:
http://cache.nxp.com/files/32bit/doc/app_note/AN4503.pdf?fsrch=1&sr=1&pageNum=1
If you add your following code before the "__WFI"
while( 0U != (SMC_PMSTAT & 0x01) )/* Blink as long as remain in RUN mode */
{
LED_HEAT_RED_TOGGLE();
delay_ms( 100U );
}
Your code won't enter in the VLLSx mode, it may always in the while.
I don't know how you test it, did you test in the debug mode? Normally, when do the Low power testing, you should download the code to the flash and leave the debug mode, just check the MCU current consumption is ok.
Have a great day,
Jingjing
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
" SMC_PMSTAT will valid after the according power mode is entered!"
Exactly how do I read PMSTAT in that low power VLLS mode once it has been entered (the clock is stopped, so nothing is going to read anything)?
The point here is there are documented bits to say what the current mode is, yet there is no way to read them while in that mode, and if not in that mode, the bit showing the mode won't be set. Or are you saying that all of the bits of PMSTAT are only valid when hooked up to a debugger?
I'll just write off PMSTAT as yet more bad documentation and move on.