AnsweredAssumed Answered

Wake from LLS (Low Leakage Stop) using falling edge on O/I pin. (Current demand returns but code is not executed?)

Question asked by rick stuart on Mar 17, 2015
Latest reply on Mar 19, 2015 by rick stuart

Trying to get a KL27 Freescale processor to wake up from a low power (LLS) state on a I/O pin's falling edge. However, as best as I can tell, the processor current demand returns, but the processor does not continue to execute the program.

 

If I leave the debugger connected (which draws about 80uA of additional current) I can run the program into LLS mode, then press a switch which drops the voltage on I/O pin C1.  The processor current demand returns to several mAs.  But the LED flashing behavior indicating the processor has continued executing code never occurs.  If I break the program using the debugger, I see it has stopped on the line of code following the WFI (Wait For Interrupt) line of code.  (I can repeat this test with the same results with the debugger not operating.  Of course I then have no way to know for sure where the program is hung.)

 

I was expecting the interrupt service routine for the LLWU (Low Leakage Wake Up) feature to execute.  This should have flashed the blue LED.  Then for the execution of the code to continue in the main() routine flashing the red LED.  Then for the KL27 processor to return to low power mode waiting for the next button press which would have dropped the voltage on I/O pin C1.  Instead the (as stated above) the processor current demand returns and subsequent button presses changes nothing.  No LED activity and no current changes.

 

So additional code to detect activity on ports B, C, D or E was added.  The service routine for this feature flashes a green LED.  Now the behavior is very different.  Upon the first button press the current raises from 2.3uA to 1.9mA.  But there is no LED activity.  Upon the second button press the green LED flashes then the red LED flashes then the current drops to 2.3uA.  Guessing, the processor exits the LLS state after the first button press but does not execute any code.  Then, the second button press causes the PORTBCDE_IRQHandler to be called.  This flashes the green LED.  Then execution continues in the main routine flashing the red LED.  And finally the processor returns to LLS mode.

 

Why?

 

Why does the processor demand much more current but apparently not execute any code after first I/O pin C1 transitions from high to low?

 

(All tests and code were executed on a Freescale FRDM-KL27Z development board.)

 

-thanks

 

Code:

 

// start of code

 

// 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)

{

  MCU_Init();                                  // MCU Initialization; has to be done prior to anything else

  RGB(0,0,0);                                  // Start with all LEDs off

 

  __asm("CPSIE i");                            // Enable all Interrupts

 

  NVIC->ICPR[0] = (uint32_t)(1 << (PORTBCDE_IRQn & 0x1F));     // Clear PORTBCDE Interrupt in NVIC Core register

  NVIC->ISER[0] = (uint32_t)(1 << (PORTBCDE_IRQn & 0x1F));     // Set PORTBCDE Interrupt in NVIC Core register

 

  volatile int dummyread;

 

  RGB(0,0,0);

 

  SMC_PMPROT = SMC_PMPROT_ALLS_MASK;

  SMC_PMCTRL = SMC_PMCTRL_STOPM(3); // (MC2) Set STOPM = 0b11

 

  // 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(;;) 

  {

    // Clear WUF6 (aka LLWU_P6) by writing a 1 to the flag bit.

    // (Need to do this to get the uC down from drawing ~2-3mA to <5uA.

    LLWU_F1 = 0x40;

  

    RGB(0,0,0);

    __asm("WFI");                                                       // Enter low power mode

  

    dummyread = PMC_REGSC;

  

    GPIOB_PTOR|=(1<<18);                       // Toggle RED LED

    MCU_Delay(200);  

  }

}

//-------------------------------------------------------------------

// ******************************************************************

 

 

// 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 PORTBCDE_IRQHandler (void)

{

  PORTC->PCR[1]|= PORT_PCR_ISF_MASK;         // Clear interrupt flag

  GPIOB_PTOR|=(1<<19);                       // Toggle GREEN LED

  MCU_Delay(200);                            // Delay 200ms

}

 

void LLWU_IRQHandler (void)

{

  GPIOB_PTOR|=(1<<13);                       // Toggle BLUE LED

  MCU_Delay(200);                            // Delay 200ms

}

 

// end of code

Outcomes