cancel
Showing results for 
Search instead for 
Did you mean: 

RTC wake up time counter limit

HDaji.1
Senior

In my app, I need MCU to go to stop mode and then wake up by RTC timer.

I follow this RTC wake up example and manage to make MCU go to stop mode for a few seconds and then wake up.

Because in my app, we want MCU to wake up once in a few hours instead of a few seconds. The problem occurs when I try to increase the counter by 1000 times, the stop mode duration is still a few seconds.

Can someone enlighten me what the issue is? Does the time counter have limit? It is an unsigned 32 bit integer, which can be very large. Or is it constrained by hardware?

1 ACCEPTED SOLUTION

Accepted Solutions
Peter BENSCH
ST Employee

If you are using CubeMX, you can set the Wake Up Clock to RTCCLK / 16 ... / 2, but also to 1 Hz and 1 Hz with 1 bit added to Wake Up Counter.

However, I see in your code that you call HAL_RTCEx_SetWakeUpTimer_IT manually in USER CODE 3, which is not really necessary. If you want this to remain manual, you would have to use

 

HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WAKEUP_COUNTER, RTC_WAKEUPCLOCK_CK_SPRE_16BITS); // 1Hz

 

instead of

 

HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WAKEUP_COUNTER, RTC_WAKEUPCLOCK_RTCCLK_DIV16); // 2kHz

 

The wakeup timer is not a variable, but a hardware resource and defined uint32_t, because 17bit can also be set for 0.5Hz: 

 

HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock);

 

 

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

View solution in original post

4 REPLIES 4
Peter BENSCH
ST Employee

Although you have not inserted any code that would allow us to see what you have set incorrectly, you have probably encountered an overflow.

Background: the wake-up timer of the RTC not only has a prescaler of 16, but can usually be set in a wide range. In the given example, LSE is used as the clock, so that the prescaler of 16 results in an input frequency at the wake-up timer of 32kHz/16 = 2kHz. Incidentally, the wake-up timer does not have 32 bits, but only 16 bits, so that a maximum wake-up time of 32,768 seconds results at 2kHz.

Solution to your problem: instead of the prescaler of 16, simply use the option of 1Hz or 0.5Hz. At 1Hz you then get ~18.25h with 1s resolution, at 0.5Hz (1Hz with an additional bit) ~36.5h with 2s resolution.

[edit] Forgot to add that you can achieve ~9h wakeup time with the 32768 seconds when using the prescaler of 16, but larger values for the wakeup timer are truncated to 16bit. [/edit]

Does it answer your question?

Regards
/Peter

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Hi @Peter BENSCH 

 

Below are my code. I bet you have solved my problem. Let me give it a try and then Accept it. Many thanks!

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};

  /* 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.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 WakeUp
  */
  if (HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WAKEUP_COUNTER, RTC_WAKEUPCLOCK_RTCCLK_DIV16) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN RTC_Init 2 */

  /* USER CODE END RTC_Init 2 */

}
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_USART2_UART_Init();
  MX_RTC_Init();
  /* USER CODE BEGIN 2 */
  sprintf(uart2_str, "\tRTC Timer Wakeup ...\n");
  HAL_UART_Transmit(&huart2, (uint8_t *)uart2_str, strlen(uart2_str), 999);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	Blink_Led(250, 8);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
      HAL_SuspendTick();
	  HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WAKEUP_COUNTER, RTC_WAKEUPCLOCK_RTCCLK_DIV16);

	  /* Enter STOP 2 mode */
		memset(uart2_str, 0, 64);
	    sprintf(uart2_str, "\n\t\t *** OK Before Stop/Standby Mode\n");
	    HAL_UART_Transmit(&huart2, (uint8_t*)uart2_str, strlen(uart2_str), 999);

	  HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
	  HAL_RTCEx_DeactivateWakeUpTimer(&hrtc);

	  SystemClock_Config();
	  HAL_ResumeTick();

		memset(uart2_str, 0, 64);
	    sprintf(uart2_str, "\t\t *** OK Wake Up\n");
	    HAL_UART_Transmit(&huart2, (uint8_t*)uart2_str, strlen(uart2_str), 999);

	  Blink_Led(1000, 4);
  }
  /* USER CODE END 3 */
}

 

Hi @Peter BENSCH 

Two more questions:

  1. Using pre-scaler of 16, we can get 2kHz. I wonder how I can get 1Hz? the options for pre-scaler are only 16, 8, 4, and 2.
  2. Is the wake-up timer a signed variable? Otherwise the max values should be 65535, isn't it?.

 

Peter BENSCH
ST Employee

If you are using CubeMX, you can set the Wake Up Clock to RTCCLK / 16 ... / 2, but also to 1 Hz and 1 Hz with 1 bit added to Wake Up Counter.

However, I see in your code that you call HAL_RTCEx_SetWakeUpTimer_IT manually in USER CODE 3, which is not really necessary. If you want this to remain manual, you would have to use

 

HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WAKEUP_COUNTER, RTC_WAKEUPCLOCK_CK_SPRE_16BITS); // 1Hz

 

instead of

 

HAL_RTCEx_SetWakeUpTimer_IT(&hrtc, WAKEUP_COUNTER, RTC_WAKEUPCLOCK_RTCCLK_DIV16); // 2kHz

 

The wakeup timer is not a variable, but a hardware resource and defined uint32_t, because 17bit can also be set for 0.5Hz: 

 

HAL_RTCEx_SetWakeUpTimer_IT(RTC_HandleTypeDef *hrtc, uint32_t WakeUpCounter, uint32_t WakeUpClock);

 

 

In order to give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.