Hi,
I have a battery powered application, using a Kinetis MCU.
I'm trying to get the MCU to wake up from VLLS3 once per minute, to perform some checks on the environment, to then decide whether to stay active, or go back to VLLS3 for another minute.
Currently, I've been able to get it to start up every minute, but every time it re-starts, it needs to wait for the watchdog timer(COP) to be hit, at which point the COP will get reset, and my code will run, however the time that it's waiting for the COP, it's wasting power.
Currently, I have the following code (trimmed down for relevance) in place to shut down the MCU for 1 minute:
RTC_EnableInterrupts(RTC, kRTC_AlarmInterruptEnable);
RTC_EnableWakeUpPin(RTC, 1);
RTC->TAR = 60 + rtc_get_utc(); //this function returns the current RTC time
LLWU->ME |= 32;//enable rtc alarm wakeup
LLWU->F1 = 0xff;//clear existing LLWU flags
LLWU->F2 = 0xff;
vllsconfig.enablePorDetectInVlls0 = 1;
vllsconfig.subMode = kSMC_StopSub3 ;
SMC_PreEnterStopModes();
SMC_SetPowerModeVlls(SMC, &vllsconfig);
SMC_PostExitStopModes();
NVIC_SystemReset();//should never be hit
I then have a handler, that should be hit, to deal with the RTC alarm when it is hit:
void RTC_IRQHandler(void)
{
//clear the RTC alarm
if(RTC_GetStatusFlags(RTC)& RTC_SR_TAF_MASK)
{
RTC_ClearStatusFlags(RTC, RTC_SR_TAF_MASK);
}
RTC_ClearStatusFlags(RTC, RTC_SR_TAF_MASK);
LLWU->F1 = 0xff;
LLWU->F2 = 0xff;
//LLWU->FILT1 |= LLWU_FILT1_FILTF_MASK;
//LLWU->FILT2 |= LLWU_FILT2_FILTF_MASK;
NVIC_SystemReset();
}
I already (before this solution) have the MCU waking up from VLLS3 on hardware interrupt pins without issue.
I also have a “void LLWU_IRQHandler(void)” function defined from a previous feature, which deals with waking up from VLLS3 with the hardware interrupt pins.
If anyone has any useful information it would be greatly appreciated.
Solved! Go to Solution.
Hi,
Can you tell us the Kinetis part number?
Generally, the exiting VLLS3 follows up the reset procedure. Pls refer to the boot chapter and know if the start-up (booting mode)waits for the watchdog hitting event.
Because Reset procedure is followed up after exiting the VLLS3 mode, the RTC_IRQHandler() is not executed.
Can you clarify your issue more clearly?
BR
XiangJun Rong
Hi,
The Part Number is MKL27Z256VLH4
I'll spend today looking at the boot sequence, i noticed you mentioned "boot chapter", is this the code for the boot sequence, or is there any specific documentation for this area of operation?
Strangely, when LLWU pin interrupts are used to wake from VLLS3 to run mode, there isn't this delay, whereas there is this delay when waking on the RTC alarm.
Hi,
Because exiting VLLS3 follows up reset process, if there is delay difference for LLWU pin interrupt and RTC alarm interrupt, I suppose Reset process time is the same.
Maybe the RTC alarm time makes the time difference.
Pls try to reduce the RTC alarm time and have a try.
BR
XiangJun Rong
Hi,
I’ve spent more time looking into this,
I’ve tried reducing the sleep time to 5 seconds, and then to 2 seconds, but I still got the same issue on startup, with the MCU freezing until it was cleared from this state by the watchdog timer being hit.
While I would like to be able to get to the bottom of this problem, I'm aware that there are other ways to do this, the important part for me, is that I can make the MCU go to VLLS3 dormant mode, then wake itself up automatically, to check the environment, if there is another way to do this, then that would also be useful.
I’ve looked around the code, and in the .MAP file , that’s generated by the linker, I’ve seen that it looks like there is a load of handler functions that are being assigned to the same address, Is this relevant?
0x00000122 LPTMR0_DriverIRQHandler
0x00000122 Reserved42_DriverIRQHandler
0x00000122 PORTC_PORTD_DriverIRQHandler
0x00000122 Reserved43_DriverIRQHandler
0x00000122 PIT_DriverIRQHandler
0x00000122 CMP0_DriverIRQHandler
0x00000122 I2S0_DriverIRQHandler
0x00000122 ADC0_DriverIRQHandler
0x00000122 TPM2_DriverIRQHandler
0x00000122 PMC_DriverIRQHandler
0x00000122 RTC_DriverIRQHandler
0x00000122 RTC_Seconds_DriverIRQHandler
0x00000122 LLWU_DriverIRQHandler
0x00000122 TPM1_DriverIRQHandler
0x00000122 PORTA_DriverIRQHandler
0x00000122 UART2_FLEXIO_DriverIRQHandler
0x00000122 FTFA_DriverIRQHandler
0x00000122 IntDefaultHandler
0x00000122 USB0_DriverIRQHandler
0x00000122 DAC0_DriverIRQHandler
0x00000122 TPM0_DriverIRQHandler
0x00000122 Reserved45_DriverIRQHandler
0x00000122 Reserved20_DriverIRQHandler
It’s my understanding that the .MAP file is an “output” from the linker, so if I modified it, it would have little effect, but from my understanding, all of these functions being assigned the same address, means that each handler is over-writing the previous?
Another question that I’m wondering, given that it should be re-starting via the reset process, is the relevance of the RTC_IRQHandler() , will this ever be hit, or would I be chasing a dead end looking for problems there?
As always, any useful information would be appreciated
DG
Hi Bob,
Thanks for the reply,
I've looked, and as hoped, found the weak linkages, here's the one for the RTC:
WEAK_AV void RTC_IRQHandler(void)
{ RTC_DriverIRQHandler();
}
When I have my custom RTC_IRQ commented out , that function points towards:
WEAK_AV void IntDefaultHandler(void)
{
while(1) {}
}
I have over-ridden the RTC_IRQHandler, with my code, but I don't know either way, if it's being hit.
I noticed that your example had:
“void LPUART0_IRQHandler( void ) __attribute__( ( used, naked, interrupt( "IRQ" ) ) );”
Could you explain what this is meant to be doing, my IRQ’s don’t have this, could this be what is wrong?
I tried using the debugger to "catch" the code at the while(1) point of the code (with the RTC IRQ Disabled) , but it didn’t work, my guess is that when it's going to sleep it's "disconnecting" from the debugger, so not working.
I've tried using the debugger to pin-point likely issues, but when using the debugger around sleep, I find that I'm getting errors, my guess is that the debugger is trying to talk to an MCU that's asleep and having issues with that.
I've also tried running the code stand-alone, without the debugger connected, which didn’t fix it either.
In the reference manual, I've found the following :
"Going into a VLLSx mode causes all the debug controls and settings to be reset.
To give time to the debugger to sync up with the HW,
the MDM-AP Control register can be configured to hold the system in reset on recovery so that the debugger can regain control and reconfigure debug logic prior to the system exiting reset and resuming operation."
Do you think it's possible that this is the state that it's getting stuck in?
I've also looked at some of the VLLS documentation:
"18.5.2 VLLS modes"
"For any wakeup from VLLS, recovery is always via a reset flow and
RCM_SRS[WAKEUP] is set indicating the low-leakage mode was active. State retention
data is lost and I/O will be restored after PMC_REGSC[ACKISO] has been written.
A VLLS exit event due to RESET pin assertion causes an exit via a system reset. State
retention data is lost and the I/O states immediately return to their reset state. The
RCM_SRS[WAKEUP] and RCM_SRS[PIN] bits are set and the system executes a reset
flow before CPU operation begins with a reset vector fetch."
So, as we thought, it reckons it should reset on wakeup, like it already does for the LLWU trigger pins that wake up the MCU.
Another curious detail that I've found, is that when I comment out the "LLWU_IRQHandler" I get the same behaviour with the watchdog timer when waking up from sleep due to an external pin waking up the MCU. This led me to think that this might be the area of the code that needs work done to.
My LLWU_IRQHandler now looks like:
void LLWU_IRQHandler(void)
{
//If wakeup by external pin.
if (LLWU_GetExternalWakeupPinFlag(LLWU, 6))//external pin
{
PORT_SetPinInterruptConfig(PORTC, 1, kPORT_InterruptOrDMADisabled);
PORT_ClearPinsInterruptFlags(PORTC, (1U << 1));
LLWU_ClearExternalWakeupPinFlag(LLWU, 6);
}
if (LLWU_GetExternalWakeupPinFlag(LLWU, 7))//external pin
{
PORT_SetPinInterruptConfig(PORTC, 1, kPORT_InterruptOrDMADisabled);
PORT_ClearPinsInterruptFlags(PORTC, (1U << 3));
LLWU_ClearExternalWakeupPinFlag(LLWU, 7);
}
if (LLWU_GetExternalWakeupPinFlag(LLWU, 10))//external pin
{
PORT_SetPinInterruptConfig(PORTC, 1, kPORT_InterruptOrDMADisabled);
PORT_ClearPinsInterruptFlags(PORTC, (1U << 6));
LLWU_ClearExternalWakeupPinFlag(LLWU, 10);
}
//new code
//try to get RTC LLWU Working
if(LLWU_GetInternalWakeupModuleFlag(LLWU, 5))//RTC alarm from page 264 of the reference manual
{
RTC_DisableInterrupts(RTC,kRTC_AlarmInterruptEnable );
RTC_ClearStatusFlags(RTC, RTC_SR_TAF_MASK);
RTC_StopTimer(RTC);
//RTC->TAR += 60; //add a minute as a test
}
}
As always, if anyone has any information that might be useful, it’s greatly appreciated.
Hi,
Thankyou for your help, it was much appreciated, I've managed to get it working.
Some further information for anyone who finds themselves with this issue in the future.
in the end, I found that having:
NVIC_SystemReset();
NVIC_DisableIRQ( RTC_IRQn ); /* Don't get stuck here */
NVIC_DisableIRQ( LLWU_IRQn ); /* Don't get stuck here */
at the start of the RTC_IRQHandler
and :
NVIC_SystemReset();
NVIC_DisableIRQ( LLWU_IRQn ); /* Don't get stuck here */
at the start of the LLWU_IRQHandler
seems to have fixed the problems, I'll probably keep investigating the problem, to optimise the solution, but it's working fine now.