Hi,
I am using a Freescale FRDM-KL27Z development board and the short program listed below. I expected to enter the VLPS mode where the current should have dropped from several mAs to several uAs. Instead the current, when I expected to be in the VLPS mode, is 2.6mA! Am I in VLPS mode? Well, if you follow the code you will see that I flash the RGB LED different colors to indicate where I am. If I press SW3 I should exit VLPS and generate a green (in the PORTBCDE interrupt) then red (executing after the WFI code line) flash. And that does happen. If I press the reset button I should generate a white flash then enter VLPS (i.e. no red flash so execution did stop). And that happens. So code execution looks orderly. And I do wait when I hit the WFI code line.
Here's the part that really confuses me...
If I cycle the power to the KL27 processor, it all works!! When I expect to be in the VLPS mode I am drawing only 5.3uA. From here I can press SW3 and see a green then red flash then return to drawing only 5.3uA. Exactly what I expected. If I press reset I see a white flash then return to drawing only 5.3uA. Again, exactly what I expected.
What is going on? What could possibly be unaffected by a reset only to change on a power cycle. Why would programming / debugging the chip put it back into a mode where VLPS appears broken?
-thanks
// code start
// INCLUDES /////////////////////////////////////////////////////////
//-------------------------------------------------------------------
#include "MKL27Z644.h" // KL27 M0+ register definitions
// FUNCTION HEADERS /////////////////////////////////////////////////
//-------------------------------------------------------------------
void MCU_Init(void); // initializes MCU for Freedom Board
void MCU_Delay(uint32_t delay); // delay in multiples of 1ms
//---------------------------------------------------------------------
void RGB(uint8_t Red,uint8_t Green,uint8_t Blue); // RGB-LED Control: 1=on, 0=off, for each of the 3 colors
// *** MAIN *********************************************************
//-------------------------------------------------------------------
int main(void)
{
volatile int dummyread;
MCU_Init(); // MCU Initialization; has to be done prior to anything else
RGB(1,1,1); // Turn on white LED
MCU_Delay(200); // Delay 200ms
RGB(0,0,0);
__asm("CPSIE i"); // Enable all Interrupts
/***
// Set up interrupts.
NVIC->ICPR[0] = (uint32_t)(1 << (LLWU_IRQn & 0x1F)); // Clear LLUW Interrupt in NVIC Core register
NVIC->ISER[0] = (uint32_t)(1 << (LLWU_IRQn & 0x1F)); // Set LLUW Interrupt in NVIC Core register
// Set up low power mode.
SMC_PMPROT=SMC_PMPROT_ALLS_MASK;
SMC_PMCTRL=SMC_PMCTRL_STOPM(0x3);
***/
// Set up interrupts.
PORTC->PCR[1]|= PORT_PCR_ISF_MASK; // Clear interrupt flag
NVIC->ICPR[0] = (uint32_t)(1 << (PORTBCDE_IRQn & 0x1F));
NVIC->ISER[0] = (uint32_t)(1 << (PORTBCDE_IRQn & 0x1F));
// Set up low power mode.
SMC_PMPROT=SMC_PMPROT_AVLP_MASK;
SMC_PMCTRL=SMC_PMCTRL_STOPM(0x2);
// Enable hi to lo transition for LLWU_P6 / pin-C1.
LLWU_PE2 = 0x20;
// Set the SLEEPDEEP bit to enable deep sleep mode.
// (W/o this we only drop to about 3.1mA down from 4.6mA.)
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
for(;;)
{
__asm("WFI"); // Enter low power mode
dummyread = PMC_REGSC;
RGB(1,0,0); // Turn on RED LED
MCU_Delay(200); // Delay 200ms
RGB(0,0,0);
}
}
//-------------------------------------------------------------------
// ******************************************************************
// FUNCTION BODIES //////////////////////////////////////////////////
//-------------------------------------------------------------------
void MCU_Init(void)
{
// Crucial
__asm("CPSID i"); // Disable interrupts
//Disable Watchdog
SIM_COPC=0x00; // Disable COP watchdog
//System Registers
SIM_SCGC5|=SIM_SCGC5_PORTA_MASK; // Enable PortA clock
SIM_SCGC5|=SIM_SCGC5_PORTB_MASK; // Enable PortB clock
SIM_SCGC5|=SIM_SCGC5_PORTC_MASK; // Enable PortC clock
SIM_SCGC5|=SIM_SCGC5_PORTD_MASK; // Enable PortD clock
SIM_SCGC5|=SIM_SCGC5_PORTE_MASK; // Enable PortE clock
// System clock initialization
MCG_MC|=MCG_MC_HIRCEN_MASK; // Enable 48MHz HIRC
MCG_C1=MCG_C1_CLKS(0); // Enable Main Clock Source of the 48MHz HIRC
SIM_CLKDIV1&=~(SIM_CLKDIV1_OUTDIV1(1)); // Set Core Clock/1=48MHz
SIM_CLKDIV1|=(SIM_CLKDIV1_OUTDIV4(1)); // Set Bus Clock/2=24MHz
// System Tick Init
SysTick->CTRL=0; // Disable the SysTick Timer
SysTick->LOAD=48000; // Core Clock/1=48MHz, Period=1ms/(1/48000000Hz)=48000
SysTick->VAL=0; // Clear the current counter value to 0
SysTick->CTRL=(SysTick_CTRL_ENABLE_Msk
|SysTick_CTRL_CLKSOURCE_Msk); // Enable SYS TICK timer and set clock source to processor clock (core clock)
// GPIO Init
PORTC->PCR[1] |= PORT_PCR_MUX(1)| // Enable Port Pin PTC1 as GPIO
PORT_PCR_PE_MASK| // Select the resistor to pull up or down on port pin
PORT_PCR_PS_MASK| // Select a pull up resistor
PORT_PCR_IRQC(0x08); // Configure interrupt pin to trigger on a logic low (0)
GPIOC->PDDR&=~(1<<1); // make sure GPIO PTC1 pin is configured as an input
PORTB_PCR18=PORT_PCR_MUX(1); // Set Pin B18 to GPIO function
PORTB_PCR19=PORT_PCR_MUX(1); // Set Pin B19 to GPIO function
PORTA_PCR13=PORT_PCR_MUX(1); // Set Pin A13 to GPIO function
GPIOB_PDDR|=(1<<18); // Set Pin B18 as output
GPIOB_PDDR|=(1<<19); // Set Pin B19 as output
GPIOA_PDDR|=(1<<13); // Set Pin A13 as output
}
//---------------------------------------------------------------------
void MCU_Delay (uint32_t delay) // Delay in multiples of 1ms (e.g. use 1000 for 1 second)
{
uint32_t delw;
for (delw=0;delw<delay;delw++)
{
while (!(SysTick->CTRL&SysTick_CTRL_COUNTFLAG_Msk));
}
}
//---------------------------------------------------------------------
void RGB(uint8_t Red,uint8_t Green,uint8_t Blue) // RGB-LED Control: 1=on, 0=off, for each of the 3 colors
{
if (Red ==1) GPIOB_PCOR|=(1<<18); else GPIOB_PSOR|=(1<<18);
if (Green ==1) GPIOB_PCOR|=(1<<19); else GPIOB_PSOR|=(1<<19);
if (Blue ==1) GPIOA_PCOR|=(1<<13); else GPIOA_PSOR|=(1<<13);
}
//---------------------------------------------------------------------
// INTERRUPT BODIES /////////////////////////////////////////////////
//-------------------------------------------------------------------
void LLWU_IRQHandler (void)
{
// Clear WUF6 (aka LLWU_P6) by writing a 1 to the flag bit.
LLWU_F1 = 0x40; // Clear interrupt flag
RGB(0,0,1); // Turn on BLUE LED
MCU_Delay(200); // Delay 200ms
RGB(0,0,0);
}
void PORTBCDE_IRQHandler(void)
{
// Clear flag.
PORTC->PCR[1]|= PORT_PCR_ISF_MASK; // Clear interrupt flag
RGB(0,1,0); // Turn on green LED
MCU_Delay(200); // Delay 200ms
RGB(0,0,0);
}
// code end
I have been told that VLPS may behave unexpectedly until the debugger has been physically removed and power restored to the KL27. I found interrupting the power just to the KL27 adequate for returning the KL27 to the expected low power behavior.