Page 1 of 1

RTC alarm / wakeup from Stop mode, STM32L4

Posted: Fri Jan 04, 2019 7:40 pm
by MiroslavLakota
Hello!

I am experiencing issues with waking up from the STOP MODE on STM32L476 with ChibiOS 18.2 and ChibiOS HAL. I would like to use RTC and an IMU (interrupt on a pin) to wake up the MCU from the STOP 2 Mode.

The general procedure seems to be:
- initialize the RTC, set the time if it's not available
- enable the RTC interrupt
- set up RTC Alarm/Wakeup
- go to the stop mode

We have already written the code for going to sleep and waking up using the IMU and it is working fine. However, we have troubles with enabling the interrupt of the RTC, and configuring the RTC Alarm/Wakeup.

I have read in other threads recommendations to use EXT driver to enable the RTC interrupt. However, ChibiOS 18.2. replaces the EXT driver with PAL driver and I have hard times finding the right function to enable it. Could you please help me?

Is it sufficient to set the Alarm using rtcSetAlarm() function?
Thank you very much!

Re: RTC alarm / wakeup from Stop mode, STM32L4

Posted: Fri Jan 04, 2019 8:53 pm
by Giovanni
Hi,

In 18.2 there is no immediate way to enable the RTC interrupt, you would need to operate on the EXTI registers and write your own ISR for that. PAL driver cannot help with RTC.

In next release, current trunk code, the RTC driver will have its own callback, much easier to use. You may:
- Use EXTI registers and write an ISR in 18.2.
- Wait for next release, probably next month.
- Use current trunk code while waiting for next release.

Giovanni

Re: RTC alarm / wakeup from Stop mode, STM32L4

Posted: Mon Jan 07, 2019 4:23 pm
by MiroslavLakota
Thank you for help!

i decided to use EXT registers and write my own ISR. It might be helpful for somebody:

Code: Select all


int main(void) {
   halInit();
   chSysInit();

    //Enable external RTC interrupt
    nvicEnableVector(RTC_WKUP_IRQn, STM32_IRQ_EXTI20_PRIORITY); //RTC External interrupt, priority 15
   
       //enable threads
       //...
 }

void go_to_sleep(void) {
   //sleep preparation, shutting down peripherals
   //...
   //RTC wake-up

   uint32_t WakeUpCounter = 5; // number of seconds asleep <= 0xFFFF
   uint32_t WakeUpClock = 0x00000004; //RTC_WAKEUPCLOCK_CK_SPRE_16BITS, 1HZ source

   /* Disable the write protection for RTC registers */
   do {
     RTCD1.rtc->WPR = 0xCA;
     RTCD1.rtc->WPR = 0x53;
   } while(0);

   RTCD1.rtc->ISR &= ~RTC_ISR_WUTF; // Clear Wakeup Flag

   /* Set the RTC registers*/
   RTCWakeup wakupspec;
   wakupspec.wutr = WakeUpCounter;
   wakupspec.wutr |= (WakeUpClock<<16);
   rtcSTM32SetPeriodicWakeup(&RTCD1, &wakupspec);

    /* Enable the write protection for RTC registers */
    do {
      RTCD1.rtc->WPR = 0xCA;
    } while(0);

    /* RTC WakeUpTimer Interrupt Configuration: EXTI configuration */
    EXTI->PR1 &= ~(1 << 22); // Clear the pending flag
    //Enable interrupt on the RTC WakeUp Timer associated Exti line.
    EXTI->IMR1 |= ((uint32_t)0x00100000);  /*!< External interrupt line 20 Connected to the RTC Wakeup event */
    //Enable rising edge trigger on the RTC WakeUp Timer associated Exti line.
    EXTI->RTSR1 |= ((uint32_t)0x00100000);  /*!< External interrupt line 20 Connected to the RTC Wakeup event */

   //going to deep sleep
   PWR->CR1 |= PWR_CR1_LPMS_STOP2;
   SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
   __WFI();
   SCB->SCR &= (uint32_t) ~((uint32_t) SCB_SCR_SLEEPDEEP_Msk);

   //disable RTC wakeup

    /* Disable the write protection for RTC registers */
    do {
      RTCD1.rtc->WPR = 0xCA;
      RTCD1.rtc->WPR = 0x53;
    } while(0);

   rtcSTM32SetPeriodicWakeup(&RTCD1, NULL);

   /* Enable the write protection for RTC registers */
   do {
     RTCD1.rtc->WPR = 0xCA;
   } while(0);
   
   //reinitialize peripherals
   //...
}

//RTC wakeup interrupt callback
CH_IRQ_HANDLER (Vector4C){

  CH_IRQ_PROLOGUE();

  /* ISR code.*/
  EXTI->PR1 &= ~(1 << 22); // Clear the pending flag

  CH_IRQ_EPILOGUE();
}