Electrical – How to wake STM32F103 by RTC using HAL libraries / Registers

hal-librarymicrocontrollerrtcsleepstm32

I've started digging into STM32F103 using HAL Libraries and raw registers. It's the first time to program at such low level.

Anyway following a video I've successfully implemented "Standby" mode.
https://www.youtube.com/watch?v=O82rj9qxkgs

I need an RTC to wake it up instead of a button. So I read the reference manual without really knowing how to start and finish it up.

RTC Simplified Block Diagram

Searching the internet, I found 2 main categories of sources: sources using Standard Peripheral Library (SPL), which is not my case. And sources using registers.

Anyway couldn't successfully implement the "RTC Wake Up" method.

I'm using this resource as my code starter.

Anyway, because I don't need RTC Calendar, I've removed any setting/reading date/time as I don't need them.

And I put a LED toggle to:

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) {
   HAL_GPIO_TogglePin(LED_GPIO_Port,LED_Pin);
}

What I observe now: the MCU toggles the LED At the start of sleeping (couldn't measure time), then continues sleeping without running main() again.

  • The MCU wakes up successfully using WAKEUP positive edge via a button.

Best Answer

I used an Alarm to generate a 1 hour sleep in STOP mode before automatically wake up to do some stuffs and then shut off. I configured 3 wake up conditions :

  • 2 external interrupts
  • The 59min timeout.

Here is the source for a STM32F072. The source must be really close for your STM32F103:

RTC_AlarmTypeDef sAlarm;
GPIO_InitTypeDef GPIO_InitStruct;

/* Enable 2 external interruptions and configure EXTI lines in interruption mode */
NVIC_EnableIRQ(EXTI4_15_IRQn);
HAL_NVIC_SetPriority(EXTI4_15_IRQn, 0, 0);
NVIC_EnableIRQ(EXTI2_3_IRQn);
HAL_NVIC_SetPriority(EXTI2_3_IRQn, 0, 0);
GPIO_InitStruct.Pin = Alertb_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(Alertb_GPIO_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = BPb_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(BPb_GPIO_Port, &GPIO_InitStruct);

/* Enable the Alarm A : mask only the minute and program a time in 59 minutes */
HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
sAlarm.AlarmTime.Minutes = (sTime.Minutes + 59)%60;
sAlarm.AlarmTime.TimeFormat = RTC_HOURFORMAT12_AM;
sAlarm.AlarmDateWeekDay = RTC_WEEKDAY_MONDAY;
sAlarm.AlarmMask = RTC_ALARMMASK_DATEWEEKDAY | RTC_ALARMMASK_HOURS | RTC_ALARMMASK_SECONDS;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.Alarm = RTC_ALARM_A;
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BIN) != HAL_OK)
{
    Error_Handler();
}

/* Go into stop mode + internal voltage regulator in low power mode :
 * System is awaken by :
 * - The 2 previous EXT interrupt
 * - The programmed ALARM */
HAL_SuspendTick();
__HAL_RCC_PWR_CLK_ENABLE();
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFE); // Here the uc is stuck during 59 min or until an EXTI event occurred
HAL_ResumeTick();

/* Re-init system clock configuration after STOP mode exit */
SystemClock_Config();

Here is how ST does the Alarm config in their demonstration projects :

/**
  * @brief  Configure the current time and date.
  * @param  None
  * @retval None
  */
static void RTC_AlarmConfig(void)
{
  RTC_DateTypeDef  sdatestructure;
  RTC_TimeTypeDef  stimestructure;
  RTC_AlarmTypeDef salarmstructure;

  /*##-1- Configure the Date #################################################*/
  /* Set Date: Tuesday February 18th 2014 */
  sdatestructure.Year = 0x14;
  sdatestructure.Month = RTC_MONTH_FEBRUARY;
  sdatestructure.Date = 0x18;
  sdatestructure.WeekDay = RTC_WEEKDAY_TUESDAY;

  if(HAL_RTC_SetDate(&RtcHandle,&sdatestructure,RTC_FORMAT_BCD) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler(); 
  } 

  /*##-2- Configure the Time #################################################*/
  /* Set Time: 02:20:00 */
  stimestructure.Hours = 0x02;
  stimestructure.Minutes = 0x20;
  stimestructure.Seconds = 0x00;

  if(HAL_RTC_SetTime(&RtcHandle,&stimestructure,RTC_FORMAT_BCD) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler(); 
  }  

  /*##-3- Configure the RTC Alarm peripheral #################################*/
  /* Set Alarm to 02:20:30 
     RTC Alarm Generation: Alarm on Hours, Minutes and Seconds */
  salarmstructure.Alarm = RTC_ALARM_A;
 salarmstructure.AlarmTime.Hours = 0x02;
  salarmstructure.AlarmTime.Minutes = 0x20;
  salarmstructure.AlarmTime.Seconds = 0x30;

  if(HAL_RTC_SetAlarm_IT(&RtcHandle,&salarmstructure,RTC_FORMAT_BCD) != HAL_OK)
  {
    /* Initialization Error */
    Error_Handler(); 
  }
}

Regards,