Wake from LLS

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Wake from LLS

1,605 Views
MagnusNilsson
Contributor II

I'm trying to wake a MKL17Z256Vxx4 from LLS on external pin, following the "bare metal" example in AN4503 ch 4.1.

Entering LLS works (i.e. code execution stops), but it won't wake up.

The code below is for port C3(LLWU_P7), since I have a simple push button connected to it, but I've also attempted port C5(LLWU_P9).

AN4503 says: "If interrupts are disabled, the execution resumes with the instruction after the WFI, or STOP instruction."

- so I assume I don't have to use a LLWU_IRQHandler (even though I've tried that too).

void main(void){

    for (uint8_t i = 0; i < HW_PORT_INSTANCE_COUNT; i++){

        CLOCK_SYS_EnablePortClock(i);

    }

    SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK;

    PORTC_PCR3 =(PORT_PCR_ISF_MASK |

    PORT_PCR_MUX(01) |

    PORT_PCR_IRQC(0x0B) | //either edge interrupt enable

    PORT_PCR_PE_MASK |

    PORT_PCR_PS_MASK);

    //SIM_SCGC4 = SIM_SCGC4_LLWU_MASK; // does not exist in Kinetis L ?

    LLWU_PE2 = 0xC0; //WPU07 either edge

    //MCG_C6 &= ~MCG_C6_CME0_MASK; // not for Kinetis L ?

    SMC_PMPROT = 0x08;

    SMC_PMCTRL |= 0x03;

    volatile unsigned int dummyread = SMC_PMCTRL;

    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

    asm("WFI");

    //now in LLS - does however not wake up when PC3 is toggled

    //snip some code that lights an LED to show that the MCU woke up

    while(1){}

}

I would be very grateful for a sniplet of code that successfully enters and exits LLS on Kinetis L.

Labels (1)
Tags (2)
0 Kudos
8 Replies

1,241 Views
bennygoodman
Contributor I

Hi, check if you have this at SystemInit()

PMC->REGSC |= PMC_REGSC_ACKISO_MASK;
0 Kudos

1,241 Views
mjbcswitzerland
Specialist V

Hi Magnus

There are additional details concerning the LLWU operation at:

http://www.utasker.com/kinetis/LLWU.html

If you continue having problems you can get a complete solution for the KL27 which includes low leakage management (and automatic dynamic switching between lower power modes to optimise power) at the links below.

I have attached two binaries for the FRDM-KL27Z (with USB disabled) which may operate on your KL17 board if you use the same UART as its virtual COM one. In the administrator menu the low power modes can be tested and LLS wakeup is falling-edge on SW3 (PTC1) or PTC3 (as you require).

Looking at your code I suspect that the problem may be that there is also an interrupt enabled on the port (this is not required), or that you don't have an interrupt handler for the LLWU:

- it may be that it is waking from the LLWU mode but immediately taking one of these interrupts (if not handled corretly it will end up in a default interrupt handler) and then also not reach your following code that lights LEDs.

- although I don't think that thsi is the case in your code, PTC3 defaults to being a disabled mux function and LLWU will not operate on such a pin if left in that state (it can be set to GPIO or any other mux position and then does operate as expected).

Regards

Mark

Kinetis: http://www.utasker.com/kinetis.html

KL27: http://www.utasker.com/kinetis/FRDM-KL27Z.html / http://www.utasker.com/kinetis/Capuccino-KL27/Capuccino-KL27.html

For the complete "out-of-the-box" Kinetis experience and faster time to market

:smileyinfo: Out-of-the-box support for 47 Kinetis boards and 10 IDEs (470 combinations from a single code source with no porting required)

0 Kudos

1,241 Views
MagnusNilsson
Contributor II

I've tried enabling both LLWU and PORTCD interrupts, but that doesn't seem to make any difference in waking the MCU.

So I'm trying the simplest case for waking from LLS described in AN4503, i.e. not using interrupts at all.

AN4503 states that:

"Interrupts do not need to be enabled nor does the LLWU interrupt vector need to be enabled for the MCU to

wake from LLS or VLLSx low-power modes."

"If interrupts are disabled, the execution resumes with the instruction after the WFI, or STOP instruction"

Am I still missing some configuration of the LLWU?

int main(void){

    __asm("CPSID i"); //turn off all interrupts

    for (uint8_t i = 0; i < HW_PORT_INSTANCE_COUNT; i++){

            CLOCK_SYS_EnablePortClock(i);

    }

    //configure LEDs

    PORT_HAL_SetMuxMode(RED_LED_PORT, RED_LED_PIN_NBR, kPortMuxAsGpio);

    GPIO_DRV_ClearPinOutput(RED_LED_PIN);

    GPIO_DRV_SetPinDir(RED_LED_PIN, kGpioDigitalOutput);

    PORT_HAL_SetMuxMode(GREEN_LED_PORT, GREEN_LED_PIN_NBR, kPortMuxAsGpio);

    GPIO_DRV_ClearPinOutput(GREEN_LED_PIN);

    GPIO_DRV_SetPinDir(GREEN_LED_PIN, kGpioDigitalOutput);

  

    //light only GREEN LED

    GPIO_DRV_WritePinOutput(RED_LED_PIN, 0b00000000);

    GPIO_DRV_WritePinOutput(GREEN_LED_PIN, 0b00000001);

  

    SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK;

    PORTC_PCR3 =(PORT_PCR_ISF_MASK |

    PORT_PCR_MUX(01) |

    PORT_PCR_PE_MASK |

    PORT_PCR_PS_MASK);

    //wait until button PC3 is pressed - to ensure pin working and correctly configured as input

    while(GPIO_DRV_ReadPinInput(BUTTON_PIN)){};

  

    //light only RED LED

    GPIO_DRV_WritePinOutput(RED_LED_PIN, 0b00000001);

    GPIO_DRV_WritePinOutput(GREEN_LED_PIN, 0b00000000);

    SMC_PMPROT = 0x08;

    SMC_PMCTRL |= 0x03;

    volatile unsigned int dummyread = SMC_PMCTRL;

    LLWU_PE2 = 0xC0; //WPU07 either edge

    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

    asm("WFI");

    //Should sleep here (it does),

    //and wake up on button PC3 press (it does not)

  

    if (LLWU_F1 & LLWU_F1_WUF7_MASK) {

        LLWU_F1 |= LLWU_F1_WUF7_MASK;

        //light only GREEN LED

        GPIO_DRV_WritePinOutput(RED_LED_PIN, 0b00000000);

        GPIO_DRV_WritePinOutput(GREEN_LED_PIN, 0b00000001);

    } else {

        //light RED and GREEN LED

        GPIO_DRV_WritePinOutput(RED_LED_PIN, 0b00000001);

        GPIO_DRV_WritePinOutput(GREEN_LED_PIN, 0b00000001);

    }

    while(1){}

0 Kudos

1,241 Views
mjbcswitzerland
Specialist V

Hi Magnus

Unfortunately the AN is confusing and LLS will NOT wake when the LLWU's interrupt is masked.

Here's a quick fix (adjust to suit your headers and add it to your initialisation)

IRQ4_7_PRIORITY_REGISTER = 0x400000000; // set Int ID 7 (LLWU module) to priority 1

IRQ0_31_SER = 0x00000080; // enable Interrupt 7 (LLWU module) source

The code after the wake up is to clear the LLWU module's flag so that the interrupt vector is not actually taken (once the global interrupts are re-enabled, which would normally be done subsequently).

LLWU_F1 = LLWU_F1_WUF7_MASK; is adequate (the flag will always be set and the register is 'write-'1'-to-clear) so checking the flag and the OR are redundent.

Regards

Mark

Kinetis: http://www.utasker.com/kinetis.html

KL27: http://www.utasker.com/kinetis/FRDM-KL27Z.html / http://www.utasker.com/kinetis/Capuccino-KL27/Capuccino-KL27.html

For the complete "out-of-the-box" Kinetis experience and faster time to market

:smileyinfo: Out-of-the-box support for 47 Kinetis boards and 10 IDEs (470 combinations from a single code source with no porting required)

0 Kudos

1,241 Views
MagnusNilsson
Contributor II

Unfortunately adding those two lines ('translated' to the API I'm using) didn't do anything, as far as I can see.

  //IRQ4_7_PRIORITY_REGISTER = 0x400000000; // set Int ID 7 (LLWU module) to priority 1 ->

  NVIC_SetPriority(LLWU_IRQn, 1);

  //IRQ0_31_SER = 0x00000080; // enable Interrupt 7 (LLWU module) source ->

  NVIC_EnableIRQ(LLWU_IRQn);

It still hangs in LLS.

Doesn't anyone have a working code sniplet how to use the LLWU for KL17?

The full code I'm trying here:

---

int main(void)

{

  __asm("CPSID i"); //turn off all interrupts

  //IRQ4_7_PRIORITY_REGISTER = 0x400000000; // set Int ID 7 (LLWU module) to priority 1

  NVIC_SetPriority(LLWU_IRQn, 1);

  //IRQ0_31_SER = 0x00000080; // enable Interrupt 7 (LLWU module) source

  NVIC_EnableIRQ(LLWU_IRQn);

  for (uint8_t i = 0; i < HW_PORT_INSTANCE_COUNT; i++){

       CLOCK_SYS_EnablePortClock(i);

  }

  //configure LEDs

  PORT_HAL_SetMuxMode(RED_LED_PORT, RED_LED_PIN_NBR, kPortMuxAsGpio);

  GPIO_DRV_ClearPinOutput(RED_LED_PIN);

  GPIO_DRV_SetPinDir(RED_LED_PIN, kGpioDigitalOutput);

  PORT_HAL_SetMuxMode(GREEN_LED_PORT, GREEN_LED_PIN_NBR, kPortMuxAsGpio);

  GPIO_DRV_ClearPinOutput(GREEN_LED_PIN);

  GPIO_DRV_SetPinDir(GREEN_LED_PIN, kGpioDigitalOutput);

  //light only GREEN LED

  GPIO_DRV_WritePinOutput(RED_LED_PIN, 0b00000000);

  GPIO_DRV_WritePinOutput(GREEN_LED_PIN, 0b00000001);

  SIM_SCGC5 |= SIM_SCGC5_PORTC_MASK;

  PORTC_PCR3 =(PORT_PCR_ISF_MASK |

  PORT_PCR_MUX(01) |

  PORT_PCR_PE_MASK |

  PORT_PCR_PS_MASK);

  //wait until button PC3 is pressed - to ensure pin working and correctly configured as input

  while(GPIO_DRV_ReadPinInput(BUTTON_PIN)){};

  //light only RED LED

  GPIO_DRV_WritePinOutput(RED_LED_PIN, 0b00000001);

  GPIO_DRV_WritePinOutput(GREEN_LED_PIN, 0b00000000);

  SMC_PMPROT = 0x08;

  SMC_PMCTRL |= 0x03;

  volatile unsigned int dummyread = SMC_PMCTRL;

  LLWU_PE2 = 0xC0; //WPU07 either edge

  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

  asm("WFI");

  //Should sleep here (it does),

  //and wake up on button PC3 press (it does not)

  if (LLWU_F1 & LLWU_F1_WUF7_MASK) {

       LLWU_F1 |= LLWU_F1_WUF7_MASK;

       //light only GREEN LED

       GPIO_DRV_WritePinOutput(RED_LED_PIN, 0b00000000);

       GPIO_DRV_WritePinOutput(GREEN_LED_PIN, 0b00000001);

  } else {

       //light RED and GREEN LED

       GPIO_DRV_WritePinOutput(RED_LED_PIN, 0b00000001);

       GPIO_DRV_WritePinOutput(GREEN_LED_PIN, 0b00000001);

  }

  while(1){}

0 Kudos

1,241 Views
mjbcswitzerland
Specialist V

Hi

I don't notice any further problems in your code.

Did you try the KL27 binary that I sent because if that operates you can copy its register setup.

Regards

Mark

0 Kudos

1,241 Views
MagnusNilsson
Contributor II

Hi Mark,

No I haven't tried it - doesn't it require us to have a board similar to FRDM-KL27Z (with boot loader for mass storage and whatnot)? We have a custom board.

Or is it a stand-alone binary? In that case, how do I program it to target? We've so far only used Eclipse's own gdb plugins for PE Micro. I can run the server standalone and connect from gdb client, but that doesn't help much without flash programming routines.

Kind regards/Magnus

0 Kudos

1,241 Views
mjbcswitzerland
Specialist V

Magnus

The binary is standalone and I expect that it will run on any KLx7 HW since it uses the internal clock (UART command line menu is however only the same LPUART0 as the FRDM-K27Z - if you tell me which UART you have I can adjust this though).

Usually there is a Flash programming utility in the IDEs.

If you don't have a method with your Eclipse environment and can't find a plug-in I would install CodeWarrior and/or KDS since they include one.

Generally it is recommended to have a reference board available for comparisons and testing standard solutions (the FRDM boards tend to cost only about $12).

In case your work is for commerial product development you can also arrange support to solve problems in your own code at http://www.utasker.com/support.html which may be an alternative in case there are costs and deadlines involved.

Regards

Mark

0 Kudos