cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L433 - RTC alarm whilst also using a periodic wake

freeflyer
Senior

I am trying to get the RTC alarm working whilst also using a periodic wake, I can get each working independently but not both together.

If I DON'T shutdown for RTC wakeup, the RTC alarm DOES work.

If I DO shutdown for RTC wakeup, the RTC alarm DOES NOT work.

To summarize:

  • I am trying to use RTC Alarm for a shutdown in 1 minute
  • But I've also configured an RTC Wakeup Timer to wake every 5 seconds
  • After shutdown, RTC Wakeup Timer works — but RTC Alarm doesn't
  • When I re-call MX_RTC_Init(), the Alarm is lost

Below is the function I call to shutdown the mcu for 5 seconds, before waking up again...

void shutdownRun (void){
	/* The Following Wakeup sequence is highly recommended prior to each Standby mode entry
	    mainly  when using more than one wakeup source this is to not miss any wakeup event.
	    - Disable all used wakeup sources,
	    - Clear all related wakeup flags,
	    - Re-enable all used wakeup sources,
	    - Enter the shutdown mode.
	 */

	// Save pressure before shutdwon
	HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, *(uint32_t*)&pressure_bak);

	/* Disable all used wakeup sources*/
	HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
	HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);

	/* Clear all related wakeup flags */
	__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

	ampPowerDown();

	/* Enter the shutdown mode */
	HAL_PWREx_EnterSHUTDOWNMode();
}

 

Below is the RTC initialization (note I have commented where hours/minutes/seconds is set to zero, otherwise it would be reset each time the RTC wakes the mcu and would never trigger the alarm)...

 

static void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */

  /* USER CODE END RTC_Init 0 */

  RTC_TimeTypeDef sTime = {0};
  RTC_DateTypeDef sDate = {0};
  RTC_AlarmTypeDef sAlarm = {0};

  /* USER CODE BEGIN RTC_Init 1 */

  /* USER CODE END RTC_Init 1 */

  /** Initialize RTC Only
  */
  hrtc.Instance = RTC;
  hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
  hrtc.Init.AsynchPrediv = 127;
  hrtc.Init.SynchPrediv = 255;
  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */

  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */
 // sTime.Hours = 0x0;
 // sTime.Minutes = 0x0;
 // sTime.Seconds = 0x0;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  sDate.Month = RTC_MONTH_JANUARY;
  sDate.Date = 0x1;
  sDate.Year = 0x0;

  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }

  /** Enable the Alarm A
  */
  sAlarm.AlarmTime.Hours = 0x0;
  sAlarm.AlarmTime.Minutes = 0x1;
  sAlarm.AlarmTime.Seconds = 0x0;
  sAlarm.AlarmTime.SubSeconds = 0x0;
  sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
  sAlarm.AlarmMask = RTC_ALARMMASK_NONE;
  sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
  sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
  sAlarm.AlarmDateWeekDay = 0x1;
  sAlarm.Alarm = RTC_ALARM_A;
  if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */

  /* USER CODE END RTC_Init 2 */

}

 Below is my alarm interrupt, which is only triggered if I never call the 'shutdownRun' function ...

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) {
	shutdownFull();
}

 

10 REPLIES 10
TDK
Super User

Don't shut down within the RTC interrupt. It will not pre-empt itself.

Instead, set a flag within the interrupt and shut down within the main thread itself.

If you feel a post has answered your question, please click "Accept as Solution".

I changed the interrupt and main as you suggested but its still not working.

Interrupt is now....

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) {
	flgReqShudownFull = 1;
}

And main is now...

	while (1) {
		if (flgReqShudownFull){
			shutdownFull();
		}
}

 

Going into shutdown and using the RTC to wake after 5 seconds prevents the alarm interrupt from working, but I cant find the issue 

If I dont go into shutdown and wake every 5 seconds, the alarm interrupt works.

 

Can you show the full code? Doesn't seem to be any issues with the code you've presented.

If you feel a post has answered your question, please click "Accept as Solution".

Thanks TDK, please find a zip of the core folder attached

freeflyer
Senior

Is the problem caused because sAlarm.AlarmTime.Seconds is reset when shutdown ? 

For test purposes, I am using the following settings:

  • RTC Wakeup Timer set to 5 seconds
  • RTC Alarm set to 30 seconds

The MCU runs for 10 seconds, then shuts down for 5 seconds using the functions:

  • HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
  • HAL_PWREx_EnterSHUTDOWNMode)

When the MCU wakes, sAlarm.AlarmTime.Seconds is zero, so I have to set it back to 0x30 (should it be 0x30 or decimal 30, I'm not sure because its BCD ?).

The diagram below explains what I think might be happening, it should fully shut down and not wake again when the alarm is reached (30 seconds).  But maybe it doesn't because sAlarm.AlarmTime.Seconds is reset when shutdown. ?

 

Picture 1.jpg

 

 

The application is battery powered and once manually switched on, it is supposed to read a pressure sensor every few minutes then shutdown between each measurement.

After 12 hours of being switched on, it is supposed to permanently shutdown and not wake again until switched manually on again.

I am using shorter times for test purposed, the 5 second shutdown and wake for 10 seconds works.

But the permanent shutdown (set by sAlarm.AlarmTime) is not working.

I have either implemted this wrong or it is not possible ?

 

TDK
Super User

I suspect it's because, on startup, you're initializing RTC regardless of its current state. You should check to see if it's already initialized and, if so, don't touch it.

Implement code in the first user block within MX_RTC_Init that checks to see if it's initialized already.

If you feel a post has answered your question, please click "Accept as Solution".

I only initialize the RTC once, because I check if the MCU was woken by the RTC as follows...

	if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB)) {
		// Woke from standby
		__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
	}
	else
	{
		  MX_RTC_Init();
	}

 

I set a breakpoint on the line MX_RTC_Init() and the breakpoint is only hit on the first startup.  When the RTC wakes the MCU, the breakpoint is not hit.

The diagram below shows the behavior I expect...

Picture1.jpg

The diagram below shows what is actually happening, with the following observations made...

  • shutdownRun called at 25 seconds, but it does not shutdown and continues running
  • shutdownFull is not called at 30 seconds (sAlarm.AlarmTime.Seconds was set to 0x30)
  • sAlarm.AlarmTime.Seconds is reset when woken by the RTC
    • is this not to be expected as when the MCU is shutdown all variables are lost, so how is this supposed to be handled ?

Picture2.jpg

The diagram below shows the alarm works if I don't shutdown with RTC wake...

Picture3.jpg

 

Below is the main code...

 

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_DMA_Init();
  MX_DAC1_Init();
  MX_TIM6_Init();
  MX_SPI2_Init();
  MX_LPUART1_UART_Init();
  MX_SPI1_Init();
  MX_I2C1_Init();
  MX_USART3_UART_Init();
  MX_ADC1_Init();
  MX_TIM7_Init();
  /* USER CODE BEGIN 2 */

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */

	if (__HAL_PWR_GET_FLAG(PWR_FLAG_SB)) {
		// Woke from shutdown
		__HAL_PWR_CLEAR_FLAG(PWR_FLAG_SB);
	}
	else
	{
		  MX_RTC_Init();
	}


	Enable_PC13_EXTI();	// enable power switch wake up
	HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);  // enable RTC wake up

	while (1) {
		HAL_Delay(10000);
		shutdownRun();
		
		if (flgReqShudownFull){
			shutdownFull();
		}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

	}
  /* USER CODE END 3 */
}

 

Below is the RTC init function (only called once)...

static void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */

  /* USER CODE END RTC_Init 0 */


  /* USER CODE BEGIN RTC_Init 1 */

  /* USER CODE END RTC_Init 1 */

  /** Initialize RTC Only
  */
  hrtc.Instance = RTC;
  hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
  hrtc.Init.AsynchPrediv = 127;
  hrtc.Init.SynchPrediv = 255;
  hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
  hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
  hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
  hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
  if (HAL_RTC_Init(&hrtc) != HAL_OK)
  {
    Error_Handler();
  }

  /* USER CODE BEGIN Check_RTC_BKUP */

  /* USER CODE END Check_RTC_BKUP */

  /** Initialize RTC and set the Time and Date
  */
  sTime.Hours = 0x0;
  sTime.Minutes = 0x0;
  sTime.Seconds = 0x0;
  sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sTime.StoreOperation = RTC_STOREOPERATION_RESET;
  if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  sDate.WeekDay = RTC_WEEKDAY_MONDAY;
  sDate.Month = RTC_MONTH_JANUARY;
  sDate.Date = 0x1;
  sDate.Year = 0x0;

  if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }

  /** Enable the Alarm A
  */
  sAlarm.AlarmTime.Hours = 0x0;
  sAlarm.AlarmTime.Minutes = 0x0;
  sAlarm.AlarmTime.Seconds = 0x30;
  sAlarm.AlarmTime.SubSeconds = 0x0;
  sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
  sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
  sAlarm.AlarmMask = RTC_ALARMMASK_NONE;
  sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_ALL;
  sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
  sAlarm.AlarmDateWeekDay = 0x1;
  sAlarm.Alarm = RTC_ALARM_A;
  if (HAL_RTC_SetAlarm(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */

  /* USER CODE END RTC_Init 2 */

}

 

Below is the shutdownRun function...

void shutdownRun (void){
	/* Disable all used wakeup sources*/
	HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
	HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 5, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);

	/* Clear all related wakeup flags */
	__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);

	/* Enter the shutdown mode */
	HAL_PWREx_EnterSHUTDOWNMode();
}

 

Below is the shutdownFull function...

 

void shutdownFull (void){
	HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);  // disable RTC wakeup
	Enable_PC13_Wakeup();
	HAL_PWREx_EnterSHUTDOWNMode();
}

 

Below is the RTC alarm interrupt, I set a breakpoint here but it never hits...

void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) {
	flgReqShudownFull = 1;
}

 

freeflyer
Senior

I am going around in circles with this issue, so I had to resort to ChatGPT.

If ChatGPT is correct, then it is not possible to implement the functionality I require and I need to use a different approach.

ChatGPT said...

Summary of Key Concepts

 
Wake SourceEXTI Line Wake from ShutdownWake from Standby Notes
RTC Wakeup TimerEXTI Line 22YesYes16-bit counter, limited max duration
RTC Alarm AEXTI Line 17YesYesOne-shot alarm, precise
 

The problem is you cannot use both at the same time for wakeup from Shutdown or Standby without reconfiguring the EXTI line.


Why Your Alarm Doesn’t Work After Wakeup Timer

When you set HAL_RTCEx_SetWakeUpTimer_IT, it configures EXTI line 22.

Then, if you later configure HAL_RTC_SetAlarm_IT, it sets EXTI line 17.
But the STM32 only supports one EXTI wakeup at a time in Shutdown.
So the last one you configure takes precedence, and the other is ignored.

 

The suggested fix is

1. On Initial Power-Up:

  • Read current RTC time

  • Store the UNIX timestamp or RTC_TimeTypeDef + RTC_DateTypeDef in RTC_BKP_DRx0

RTC_TimeTypeDef time;
RTC_DateTypeDef date;
HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);

uint32_t startSeconds = RTC_to_unix(&time, &date);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR1, (startSeconds >> 16) & 0xFFFF);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, startSeconds & 0xFFFF);

On Every Wake-Up (or after active mode exits):

  • Read current time and compute elapsed seconds:

HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BIN);
HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BIN);
uint32_t currentSeconds = RTC_to_unix(&time, &date);

uint32_t startHigh = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1);
uint32_t startLow  = HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);
uint32_t startSeconds = (startHigh << 16) | startLow;

if ((currentSeconds - startSeconds) >= (14UL * 60 * 60)) {
    HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);
    HAL_PWREx_EnterSHUTDOWNMode();
}

 

Martí
Associate

Hey there! Can you send your HAL_RTC_MspInit ? Just want to check you have NVIC  lines properly enabled. Just to calm you down, the setup you intend is perfectly doable irl, i have multiple projects where i used that rtc management. 

Also beforehand for acquiring good practises i recommend you always clear flags before setting interrupts, example:

HAL_NVIC_DisableIRQ(RTC_WKUP_IRQn);

HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);

__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(hrtc, RTC_FLAG_WUTF);

NVIC_ClearPendingIRQ(RTC_WKUP_IRQn);

HAL_NVIC_EnableIRQ(RTC_WKUP_IRQn);

HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, 599, RTC_WAKEUPCLOCK_CK_SPRE_16BITS, 0);


Although from your graphic i guess the first wakeup from wakuptimer is happening, isn't it? Make sure the wakup flag is getting cleared properly, usually generated automatically in stm32xx_it.c file. Can you sum up the current issue in 3 lines max clearly please?