MQX3.8 LPM on K60 - slow to enter WAIT mode - (why WFI going to VLPR?)

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

MQX3.8 LPM on K60 - slow to enter WAIT mode - (why WFI going to VLPR?)

790 Views
TugboatCaptain
Contributor III

In the LPM demo code (MQX3.8 - Basic Examples - lowpower) the code that changes low power mode works correctly and takes around 2 mSec to change from RUN to WAIT or from WAIT to RUN. (changing the clock config and operating mode).  When I port the code to my project, it works correctly however switching to LPM_OPERATION_MODE_WAIT (line 2) takes about 150mSec (way too long).  Narrowed it down to one line of assembly code within the Cpu_SetOperationMode function in cpu.c, that is the WFI (wait for interrupt instruction).  My project and the demo use the same BSP build and same hardware. Note: modes referred to here are MQX modes, i.e. using MQX_WAIT which means Kinetis_VLPR, not using MQX_SLEEP which corresponds to Kinetis_WAIT.


Below is an oversimplified view of code that runs at two speeds.


while (TRUE)

{

      // full speed code here

     _lpm_set_clock_configuration(BSP_CLOCK_CONFIGURATION_2MHZ);  // line 1, takes about 0.7msec

     _lpm_set_operation_mode2(LPM_OPERATION_MODE_WAIT);                 // line 2, takes 1.7msec in demo, 150mSec ported to my project    

     // low power slower code here

     _lpm_set_operation_mode(LPM_OPERATION_MODE_RUN));                   // line 3 , takes 0.7 msec

     _lpm_set_clock_configuration(BSP_CLOCK_CONFIGURATION_DEFAULT));  // line 4, takes 0.8msec

}

Why might the switch to LPM_OPERATION_MODE_WAIT take so long when it hits the WFI instruction, and what interrupt releases it in the demo code?

WFI is needed to invoke Kinetis_WAIT (=MQX_SLEEP) and Kinetis_STOP (=MQX_STOP) modes for the chip, but why does the MQX LPM call WFI when transitioning to Kinetis_VLPR (=MQX_WAIT)?  No need to hang around and wait for an interrupt.

Thanks.

0 Kudos
3 Replies

349 Views
TugboatCaptain
Contributor III

Partial Solution and Follow up question:

I got around the worst of the original problem by setting Clock Configurations - Clock Configuration 2 - Very Low Power Mode - VLP mode  to AUTO in the PE of the BSP.  This way, the round trip is back down to that of the demo code, around 4mSec.

The question is: how long should each line of code in the original question take?  i.e. how long to change clock modes and operation modes?  It seems 4msec is a long time round trip to go into a low power mode, especially if you want to sleep most of the time and wake at 100Hz to check I/O.  Is there a recommended better way?

Thanks.

0 Kudos

349 Views
c0170
Senior Contributor III

Hello TugboatCaptain,

how did you measure time periods? Where does MQX LPM call WFI then transitioning to VLPR?

Is this line of your interest, set WAIT mode, 496 line?

printf ("%s\n", _lpm_set_operation_mode (LPM_OPERATION_MODE_WAIT) == 0 ? "OK" : "ERROR");

This is the code snippet from lpm_mc.c with condition to execute WFI if flag was set to USE_WFI.

/* Go to sleep if required */
if (flags & LPM_CPU_POWER_MODE_FLAG_USE_WFI)
{
    _ASM_SLEEP();
}

It should not be true in WAIT mode (Very Low Power Run). Just enlighten us more.

Regards,

MartinK

0 Kudos

349 Views
TugboatCaptain
Contributor III

MartinK,

Thanks for your attention to this.  I measure the times by raising and lowering a GPIO line on each side of the code in question and measuring with an oscilloscope   It adds microseconds of overhead to measure a millisecond event.  Each change required building the BSP so it was not a quick process.

Yes, in the demo, the line of code you mention is the one of interest, though I broke it out of the printf to better measure the execution time.

result = _lpm_set_operation_mode (LPM_OPERATION_MODE_WAIT);


The second code snippet you refer to in lpm_smc.c is wrapped in a conditional

#ifndef PE_LDD_VERSION

which in my case is not compiled in because that macro is defined in PE_LDD.h on line 29

#define PE_LDD_VERSION                           0x0100U

so instead it runs the line of code on line 219 of lpm_smc.c

    return Cpu_SetOperationMode (LPM_PE_OPERATION_MODE_MAP[target_mode], NULL, NULL);


The function Cpu_SetOperationMode is defined on line 777 of cpu.c.  In that function there is a switch on OperationMode that has this case statement which has the WFI (though does not set SMC_PMCTRL as it seems it should)

    case DOM_WAIT:

      /* SCB_SCR: SLEEPDEEP=0 */

      SCB_SCR &= (uint32_t)~0x04UL;                    

      /* SCB_SCR: SLEEPONEXIT=0 */

      SCB_SCR &= (uint32_t)~0x02UL;                    

      PE_WFI();

      break;

The code you refer to (that does not appear to be compiled in to my build) does appear to do a better job with the mode change and would properly set SMC_PMCTRL and correctly would not call WFI.  When and why is PE_LDD.h included that causes this?

Thanks.

edit: I see that PE_LDD.h is the second include in bsp.h which is the second include in lpm_smc.c, where the mode change code resides.  I assume this happened when the BSP became PE based in MQX3.8.

0 Kudos