AnsweredAssumed Answered

S32K148 - switching between RUN and VLPS

Question asked by Tomas Frcek on Feb 10, 2020
Latest reply on Feb 19, 2020 by Tomas Frcek

Hello,

 

I'm trying to switch the S32K148 to VLPS mode to conserve power and wake it back up to RUN mode when the button is pressed. The SCG module is configured to run in Normal RUN mode with SOSC and SPLL clocks configured. In the initial configuration, the current firmware runs without complications.

 

I was trying to use reference manual as much as I could, as well as information from here https://www.nxp.com/docs/en/application-note/AN5425.pdf  and here changing State From VLPS to RUN and RUN to VLPS S32K148 .

 

After I try to enter the VLPS, I see the consumption fall as the peripherals are disabled, but the MCU does not switch to VLPS (consumption stays at ~10mA, SMC_PMCTRL.VLPSA also set, in NVIC, only pending IRQ is RTC, which is not enabled however)

 

Here is my simplified code:

 

int main (void)

{

   WDOG_Disable();

   SetupClocks();

 

   // FlexCAN0, FTM1 and LPSPI1 also used in this project.

   InitPeripherals();

 

   // Init Button input. PTB15 with internal pull-up and interrupt on falling edge.

   PCC->PCCn[PCC_PORTB_INDEX] = PCC_PCCn_CGC(1U);

   PORTB->PCR[15] = PORT_PCR_PS(1) | PORT_PCR_PE(1) | PORT_PCR_MUX(1) | PORT_PCR_IRQC(10);

 

   NVIC_SetPriority(LPSPI1_IRQn, 1U);

   NVIC_SetPriority(CAN0_ORed_0_15_MB_IRQn, 2U);
   NVIC_SetPriority(FTM1_Ch0_Ch1_IRQn, 3U);
   NVIC_SetPriority(PORTB_IRQn, 4U);

   NVIC_EnableIRQ(LPSPI1_IRQn);

   NVIC_EnableIRQ(CAN0_ORed_0_15_MB_IRQn);
   NVIC_EnableIRQ(FTM1_Ch0_Ch1_IRQn);
   NVIC_EnableIRQ(PORTB_IRQn);

 

   while (1)

   {

      if (some conditions are met)

      {

         // Switch to VLPS.

 

         // 1. Disable peripherals.

         FTM1->SC &= ~FTM_SC_CLKS_MASK;
         PCC->PCCn[PCC_FTM1_INDEX] &= ~PCC_PCCn_CGC_MASK;

         LPSPI1->CR &= ~LPSPI_CR_MEN_MASK;
         PCC->PCCn[PCC_LPSPI1_INDEX] &= ~PCC_PCCn_CGC_MASK;

         CAN0->MCR |= CAN_MCR_MDIS(0x1);

         PCC->PCCn[PCC_FlexCAN0_INDEX] &= ~PCC_PCCn_CGC_MASK;

         

         // 1. Enable SIRC and set it as system clock source.

         while((SCG->SIRCCSR & SCG_SIRCCSR_LK_MASK) != 0x0) { ; }

         SCG->SIRCCSR |= SCG_SIRCCSR_SIRCEN(1U);
         while ((SCG->SIRCCSR & SCG_SIRCCSR_SIRCVLD_MASK) == 0x0) { ; }

         SCG->RCCR = SCG_RCCR_SCS(2);

 

         // 2. Deactivate SOSC, SPLL and FIRC.

         SCG->SOSCCSR &= ~SCG_SOSCCSR_SOSCEN_MASK;
         while ((SCG->SOSCCSR & SCG_SOSCCSR_SOSCVLD_MASK) != 0x0) { ; }

         SCG->SPLLCSR &= ~SCG_SPLLCSR_SPLLEN_MASK;
         while ((SCG->SPLLCSR & SCG_SPLLCSR_SPLLVLD_MASK) != 0x0) { ; }

         SCG->FIRCCSR &= ~SCG_FIRCCSR_FIRCEN_MASK;
         while((SCG->FIRCCSR & SCG_FIRCCSR_FIRCVLD_MASK) != 0x0) { ; }

 

         SystemCoreClockUpdate();

 

         // 3. VLPS entry from the Application Note.

         // Enable SLEEPDEEP bit in the Core (Allow deep sleep modes)
         S32_SCB->SCR |= S32_SCB_SCR_SLEEPDEEP_MASK;
         // Allow very low power run mode
         SMC->PMPROT |= SMC_PMPROT_AVLP_MASK;
         // Select VLPS Mode
         SMC->PMCTRL = SMC_PMCTRL_STOPM(0b10);
         PMC->REGSC |= PMC_REGSC_BIASEN_MASK;
         // Check if current mode is RUN mode
         if(SMC->PMSTAT == 0x01)
         {
            // Go to deep sleep mode
            asm("WFI");
         }

      }

   }

}

 

void PORTB_IRQHandler(void)
{
   if ((PORTB->ISFR & (0x1 << 15) != 0x0)
   {
      if ((SMC->PMSTAT & SMC_PMSTAT_PMSTAT_MASK) >> SMC_PMSTAT_PMSTAT_SHIFT == 0x10)
      {
         // MCU in VLPS mode. Wake-up.
         NormalRUNmode_SPLL_MaxSpeed();
      }  

   } 
    PORTB->ISFR |= 0x1 << 15;   
}

 

EDIT1:

 

I think I managed to enter the VLPS mode by adding some code from this example: Example S32K144 RTC VLPS S32DS.R1 . Current falls from 10mA to 6mA (drawn by UJA113 in our PCB I assume, I cannot confirm by debugger). Waking up however does not work.

Attachments

Outcomes