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.
Hi, check if you have this at SystemInit()
PMC->REGSC |= PMC_REGSC_ACKISO_MASK; |
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)
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){}
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)
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){}
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
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
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