LLS deep sleep mode RTC wakeup

Status
Not open for further replies.

hplms

New member
Hi, im working on a project with Teensy 3.6 and im using Micro Sound Recorder (Walter Zimmer one). I've modified part of the code based on snooze library because MSR is programmed to wake up from deep sleep with RTC interruption. But it generates system reset and I don't want this.
After a k66 datasheet lecture I've concluded that I should use LLS over VLLS for the normal recovery method, but im not sure.
I've modified the MSR to use LLS instead of VLLS but when it puts to deep sleep, never wakes up.

Code:
void rtcSetup(void)
{
   SIM_SCGC6 |= SIM_SCGC6_RTC;// enable RTC clock
   RTC_CR |= RTC_CR_OSCE;// enable RTC
}

void rtcSetAlarm(uint32_t nsec)
{ // set alarm nsec seconds in the future
   RTC_TAR = RTC_TSR + nsec;
   RTC_IER |= RTC_IER_TAIE_MASK;
}

/********************LLWU**********************************/
#define LLWU_ME_WUME5_MASK       0x20u
#define LLWU_F3_MWUF5_MASK       0x20u
#define LLWU_MF5_MWUF5_MASK      0x20u

static void llwuISR(void)
{
    //
#if defined(HAS_KINETIS_LLWU_32CH)
    LLWU_MF5 |= LLWU_MF5_MWUF5_MASK; // clear source in LLWU Flag register
#else
    LLWU_F3 |= LLWU_F3_MWUF5_MASK; // clear source in LLWU Flag register
#endif
    //
    RTC_IER = 0;// clear RTC interrupts
}

static void llwuSetup(void)
{
  attachInterruptVector( IRQ_LLWU, llwuISR );
  NVIC_SET_PRIORITY( IRQ_LLWU, 2*16 );
//
  NVIC_CLEAR_PENDING( IRQ_LLWU );
  NVIC_ENABLE_IRQ( IRQ_LLWU );
//
  LLWU_PE1 = 0;
  LLWU_PE2 = 0;
  LLWU_PE3 = 0;
  LLWU_PE4 = 0;
#if defined(HAS_KINETIS_LLWU_32CH)
  LLWU_PE5 = 0;
  LLWU_PE6 = 0;
  LLWU_PE7 = 0;
  LLWU_PE8 = 0;
#endif
  LLWU_ME  = LLWU_ME_WUME5_MASK; //rtc alarm
//   
    SIM_SOPT1CFG |= SIM_SOPT1CFG_USSWE;
    SIM_SOPT1 |= SIM_SOPT1_USBSSTBY;
//
    PORTA_PCR0 = PORT_PCR_MUX(0);
    PORTA_PCR1 = PORT_PCR_MUX(0);
    PORTA_PCR2 = PORT_PCR_MUX(0);
    PORTA_PCR3 = PORT_PCR_MUX(0);

    PORTB_PCR2 = PORT_PCR_MUX(0);
    PORTB_PCR3 = PORT_PCR_MUX(0);
}

/********************* go to deep sleep *********************/
#define SMC_PMPROT_AVLLS_MASK   0x2u
#define SMC_PMCTRL_STOPM_MASK   0x7u
#define SCB_SCR_SLEEPDEEP_MASK  0x4u

#define SMC_PMPROT_ALLS_MASK    0x4u

// see SMC section (e.g. p 339 of K66) 
#define VLLS3 0x3 // RAM retained I/O states held
#define VLLS2 0x2 // RAM partially retained
#define VLLS1 0x1 // I/O states held
#define VLLS0 0x0 // all stop

#define VLLS_MODE VLLS0
static void gotoSleep(void)
{  
//  /* Make sure clock monitor is off so we don't get spurious reset */
   MCG_C6 &= ~MCG_C6_CME0;
   //

// if K66 is running in highspeed mode (>120 MHz) reduce speed
// is defined in kinetis.h and mk20dx128c
#if defined(HAS_KINETIS_HSRUN) && (F_CPU > 120000000)
    kinetis_hsrun_disable( );
#endif   
   /* Write to PMPROT to allow all possible power modes */
   //SMC_PMPROT = SMC_PMPROT_AVLLS_MASK;
   //SMC_PMPROT = SMC_PMPROT_ALLS_MASK;
   /* Set the STOPM field to 0b100 for VLLSx mode */
   SMC_PMCTRL &= ~SMC_PMCTRL_STOPM_MASK;
   //SMC_PMCTRL |= SMC_PMCTRL_STOPM(0x4); // VLLSx
   SMC_PMCTRL |= SMC_PMCTRL_STOPM(0x3); // LLSx
    
   //SMC_VLLSCTRL =  SMC_VLLSCTRL_VLLSM(VLLS_MODE);
    
   /*wait for write to complete to SMC before stopping core */
   (void) SMC_PMCTRL;

   SYST_CSR &= ~SYST_CSR_TICKINT;      // disable systick timer interrupt
   SCB_SCR |= SCB_SCR_SLEEPDEEP_MASK;  // Set the SLEEPDEEP bit to enable deep sleep mode (STOP)
   
   asm volatile( "wfi" );  // WFI instruction will start entry into STOP mode
   // will never return, but wake-up results in call to ResetHandler() in mk20dx128.c

   // Clear the SLEEPDEEP bit
   //SCB_SCR = 0;
   // renable systick timer interrupt
   //SYST_CSR |= SYST_CSR_TICKINT;
}

void setWakeupCallandSleep(uint32_t nsec)
{  // set alarm to nsec secods in future and go to hibernate
   rtcSetup();
   llwuSetup();  
   rtcSetAlarm(nsec);
   yield();
#if DO_DEBUG>0
   Serial.println(nsec);
   pinMode(13,OUTPUT); digitalWriteFast(13,HIGH); delay(1000); digitalWriteFast(13,LOW);
#endif
   gotoSleep();
}
 
Last edited:
I suggest you use the Snooze library. Except for the Teensy 4.0 it works quite well.
It does not however support the Teensy 4.1.

You should also bear in mind that the Snooze library KILLS EEPROM access.
This was reported in January but to date nothing has been done to alleviate the problem.
 
I suggest you use the Snooze library. Except for the Teensy 4.0 it works quite well.
It does not however support the Teensy 4.1.

You should also bear in mind that the Snooze library KILLS EEPROM access.
This was reported in January but to date nothing has been done to alleviate the problem.
Yes, I could use snooze library, but to be honest at this point I want to understand why this isn't working and if it's the right choice.
LLS snooze function does the same https://github.com/duff2013/Snooze/blob/master/src/hal/TEENSY_36/hal.c
Seems like an easy modification.
 
Status
Not open for further replies.
Back
Top