Kinetis MCU Crashes on restart from VLLS3 when Reset by RTC Alarm

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

Kinetis MCU Crashes on restart from VLLS3 when Reset by RTC Alarm

ソリューションへジャンプ
1,033件の閲覧回数
DG_PIPE
Contributor I

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.

0 件の賞賛
返信
1 解決策
693件の閲覧回数
bobpaddock
Senior Contributor III
See if this does anything for you. Probably not. Do note the comment that the port IRQ configuration must match the LLW configuration. How this would apply to RTC I am unsure. The macro configures a port pin and turns on LED.

void LLWU_IRQHandler( void ) __attribute__( ( used, interrupt( "IRQ" ) ) );
void LLWU_IRQHandler( void )
{
/* By virtue of being in this IRQ we know that we were powered off and asleep */

NVIC_DisableIRQ( LLWU_IRQn ); /* Don't get stuck here */

CPU_LED1_INIT_AND_ASSERT();

/*
* Clear the flags in llswakeup_src() so can know the wake up source
* in main() Using NO_INIT memory won't work as its contents are
* lost in the lowest power state.
*/

PORTC->PCR[ BTCRG_INT_bp ] = ( /* MCP23S18 Charger/Buttons */
PORT_PCR_ISF_MASK | /* Clear IRQ flag */
PORT_PCR_IRQC( 0x0U ) | /* 0x=None, 0x8=Low, 0x9=Rising-edge, 0xA=Falling-Edge, 0xB=Both-Edges, 0xC=High. Interrupt must match LLWU wake up even if not used per the data sheet */
PORT_PCR_MUX( 1U ) | /* GPIO */
( PORT_PCR_PFE_MASK | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK ) /* Passive Filter Enable, PullUp */
);
}

元の投稿で解決策を見る

0 件の賞賛
返信
13 返答(返信)
1,001件の閲覧回数
xiangjun_rong
NXP TechSupport
NXP TechSupport

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

 

0 件の賞賛
返信
995件の閲覧回数
DG_PIPE
Contributor I

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.

 

 

0 件の賞賛
返信
933件の閲覧回数
xiangjun_rong
NXP TechSupport
NXP TechSupport

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

 

0 件の賞賛
返信
848件の閲覧回数
DG_PIPE
Contributor I

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

0 件の賞賛
返信
824件の閲覧回数
bobpaddock
Senior Contributor III
Make sure that your IRQ functions are declared correctly. An example from my serial port that I had at hand:

void LPUART0_IRQHandler( void ) __attribute__( ( used, naked, interrupt( "IRQ" ) ) );
void LPUART0_IRQHandler( void )
{
LPUART_IRQHandler( 0U ); /* SERIALP_RADIO is on UART0 */
}

The attributes will depend on your needs and tool set. It is the IRQ one that is important to override the default 'weak' linkage to the default handler.
0 件の賞賛
返信
726件の閲覧回数
DG_PIPE
Contributor I

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.

 

 

 

 

 

 

 

0 件の賞賛
返信
684件の閲覧回数
bobpaddock
Senior Contributor III
This is my LL shutdown code for KL27, similar to K32L, maybe it helps?:

LLWU_PE3 = (LLWU_PE3_WUPE8( 3U ) | LLWU_PE3_WUPE9( 3U ) ); /* 0: No Wake, 1:Rising Edge, 2: Falling Edge, 3: Any Edge */



/* One time write - allow VLPR, LLS and VLLS modes */
/* Setup Power mode protection register */
SMC_PMPROT = SMC_PMPROT_AVLP_MASK | /* Allow Very-Low-Power Modes */
SMC_PMPROT_AVLLS_MASK | /* Allow Very-Low-Leakage Stop Mode */
SMC_PMPROT_ALLS_MASK; /* Allow Low-Leakage Stop Mode */

/* SIM_SCGC5 = Clocks left on and set in hardware_setup */
SIM_SCGC6 = SIM_SCGC6_FTF_MASK; /* Flash Clock must remain on, as we are running form Flash right here */
SIM_SCGC7 = 0UL;

SCB_SCR = SCB_SCR_SLEEPDEEP_MASK; /* Deep Sleep = 1, SLEEPONEXIT = 0 = do not sleep when returning to Thread mode */
SMC_PMCTRL = SMC_PMCTRL_STOPM( 4U ); /* 4 = Very Low Lekage Stop VLLSx */

SMC_STOPCTRL = SMC_STOPCTRL_VLLSM( 3U ); /* 3 = VLLS3 LPTMR runs, SRAM Preserved, 1 = VLLS1 SRAM Powered Off, 0 = VLLS0 LPO disabled, SRAM Powered Off! */
( volatile uint8_t ) SMC_STOPCTRL; /* Dummy read to ensure the register is written before entering low power mode */
/*
* Before executing the WFI instruction, the last register
* written to must be read back. This ensures that all register
* writes associated with setting up the low power mode being
* entered have completed before the MCU enters the low power
* mode. Failure to do this may result in the low power mode
* not being entered correctly.
*/

watchdog_service();
sync_barrier_data();
wait4irq();
/* The wake-up flow from VLLSx is always through reset */

reset_mcu(); /* Will never get here in VLLSx modes, but if we do... */
}
0 件の賞賛
返信
691件の閲覧回数
bobpaddock
Senior Contributor III
From my notes, take from the 2013 URL I posted:

* Another little tidbit of information it took some experimentation
* to figure out, is that when waking the MCU from VLLSx modes with
* the RTC_SECONDS interrupt, you need to enable the clock gate to the
* RTC before the the NVIC clear pending interrupt flag will be
* cleared. The reason for this is that the RTC has a handshake that
* is occurring with the NVIC and trying the clear the NVIC clear
* pending interrupt flag from the LLWU interrupt function of the
* RTC_SECONDS interrupt function will not complete if the RTC clock
* gate is not written.

0 件の賞賛
返信
694件の閲覧回数
bobpaddock
Senior Contributor III
See if this does anything for you. Probably not. Do note the comment that the port IRQ configuration must match the LLW configuration. How this would apply to RTC I am unsure. The macro configures a port pin and turns on LED.

void LLWU_IRQHandler( void ) __attribute__( ( used, interrupt( "IRQ" ) ) );
void LLWU_IRQHandler( void )
{
/* By virtue of being in this IRQ we know that we were powered off and asleep */

NVIC_DisableIRQ( LLWU_IRQn ); /* Don't get stuck here */

CPU_LED1_INIT_AND_ASSERT();

/*
* Clear the flags in llswakeup_src() so can know the wake up source
* in main() Using NO_INIT memory won't work as its contents are
* lost in the lowest power state.
*/

PORTC->PCR[ BTCRG_INT_bp ] = ( /* MCP23S18 Charger/Buttons */
PORT_PCR_ISF_MASK | /* Clear IRQ flag */
PORT_PCR_IRQC( 0x0U ) | /* 0x=None, 0x8=Low, 0x9=Rising-edge, 0xA=Falling-Edge, 0xB=Both-Edges, 0xC=High. Interrupt must match LLWU wake up even if not used per the data sheet */
PORT_PCR_MUX( 1U ) | /* GPIO */
( PORT_PCR_PFE_MASK | PORT_PCR_PE_MASK | PORT_PCR_PS_MASK ) /* Passive Filter Enable, PullUp */
);
}

0 件の賞賛
返信
451件の閲覧回数
DG_PIPE
Contributor I

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.

 

 

0 件の賞賛
返信
694件の閲覧回数
bobpaddock
Senior Contributor III
0 件の賞賛
返信
695件の閲覧回数
bobpaddock
Senior Contributor III
The IRQ attribute makes sure the compiler generates function entry and exit sequences suitable for use in an interrupt handler when this attribute is present.
Has to do with stack frames.

The NAKED attribute means the IRQ function will handle its own registers. If you are not sure if you need it, then you don't.

The USED attribute keeps Link Level Optimization and/or GCC's aggressive 'Small' Model [-0s] don't optimize away the code because it has no apparent side effects, at the level of the compilers Abstract Machine.

I'd always use IRQ and USED on a IRQ function. NAKED is not used often.

Look at the .lss listing to see the differences using them make.
0 件の賞賛
返信
827件の閲覧回数
bobpaddock
Senior Contributor III
In vectors.c or its equivalent name all vectors have a 'weak' linkage to the unused-IRQ trap. Usually this has a breakpoint instruction in the hopes that there is some debugger 'out there' to catch it. By looking at the stack it can be figured out which IRQ triggered.

When a real handler is defined this 'weak' linkage gets overridden.

Some of the low power modes can only be exited via RESET. The RTC IRQ is likely lost. Check the data sheet and see what it says about the RESET state of them. Some hold a state so they can be used through RESET. Most get set to a default value.
0 件の賞賛
返信