cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L031 RTC Wake up interrupt service routine never entered

JakubFranek
Associate II

TL;DR: I see that the WUTF bit in RTC ISR register is correctly set after the RTC wake up timer period elapses, but the interrupt service routine is never entered. RTC interrupt is enabled in NVIC though, and the interrupt service routine function name matches the one in the startup file. What's stopping the MCU from entering the interrupt routine?

 

Hello,

I am trying to periodically enter an RTC wake up timer interrupt service routine on my NUCLEO-L031K6. I don't actually go to any low power mode yet, so I do not actually "wake up", I just want to respond to the interrupt for now. I managed to do this very easily with HAL driver, but I am completely stumped with the Low-Layer (LL) driver, which is the one I intend to use in my application.

This is what I did:

1) Set CubeMX: activate RTC clock source, enable internal wake up, set wake up clock to 1 Hz clock, set wake up timer to 2 (just a random value, don't care), output 1 Hz signal to verify on oscilloscope the RTC is running (and I can confirm I see 1 Hz waveform on my scope at the corresponding pin)

JakubFranek_0-1730920549545.png

2) Enable RTC interrupt in NVIC settings

JakubFranek_1-1730920582491.png

3) Set all drivers to LL

4) This is the generated content of rtc.c

  • Also note that this generated function does not actually set Wake up timer preload number to 2 at all, I think this is a bug but I will solve it in my main function
  • As you can see NVIC functions to activate the RTC interrupt have been generated, they seem correct to me

 

void MX_RTC_Init(void)
{

  /* USER CODE BEGIN RTC_Init 0 */

  /* USER CODE END RTC_Init 0 */

  LL_RTC_InitTypeDef RTC_InitStruct = {0};

  LL_GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* Peripheral clock enable */
  LL_RCC_EnableRTC();

  LL_IOP_GRP1_EnableClock(LL_IOP_GRP1_PERIPH_GPIOA);
  /**RTC GPIO Configuration
  PA2   ------> RTC_OUT_CALIB
  */
  LL_GPIO_Init(GPIOA, &GPIO_InitStruct);

  /* RTC interrupt Init */
  NVIC_SetPriority(RTC_IRQn, 0);
  NVIC_EnableIRQ(RTC_IRQn);

  /* USER CODE BEGIN RTC_Init 1 */

  /* USER CODE END RTC_Init 1 */

  /** Initialize RTC and set the Time and Date
  */
  RTC_InitStruct.HourFormat = LL_RTC_HOURFORMAT_24HOUR;
  RTC_InitStruct.AsynchPrescaler = 127;
  RTC_InitStruct.SynchPrescaler = 255;
  LL_RTC_Init(RTC, &RTC_InitStruct);

  /** Initialize RTC and set the Time and Date
  */

  /** Enable the WakeUp
  */
  LL_RTC_WAKEUP_SetClock(RTC, LL_RTC_WAKEUPCLOCK_CKSPRE);

  /** Initialize RTC and set the Time and Date
  */
  /* USER CODE BEGIN RTC_Init 2 */

  /* USER CODE END RTC_Init 2 */

}

 

5) This is the RTC interrupt handler generated within stm32l0xx_it.c

  • ***'s name matches what I see in the startup_stm32l031k6tx.s script, see below
    JakubFranek_2-1730921032577.png
  • I am not sure if it is necessary to clear the EXTI flag within the ISR, but since this routine is never actually entered (checked with debugger, and checked by the fact that USER LED never blinks) it does not matter

 

/**
  * @brief This function handles RTC global interrupt through EXTI lines 17, 19 and 20 and LSE CSS interrupt through EXTI line 19.
  */
void RTC_IRQHandler(void)
{
  /* USER CODE BEGIN RTC_IRQn 0 */
	// Check if the wakeup timer interrupt is pending
	if (LL_RTC_IsActiveFlag_WUT(RTC) != 0) {
		// Clear the wakeup timer interrupt flag
		LL_RTC_ClearFlag_WUT(RTC);

		LL_GPIO_TogglePin(USER_LED_PORT, USER_LED_PIN);
	}
	// Clear the EXTI line 20 pending flag (RTC wakeup interrupt)
	LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_20);
  /* USER CODE END RTC_IRQn 0 */
}

 

6) This is my main function.

  • In my main function, I just try to set all the necessary settings for the RTC to wake up within the specified amount of time and enter infinite loop, hoping to enter ISR every 3 seconds or so
  • Using debugging I can confirm that after the setup part is done, WUTE and WUTIE are set, WUTF is cleared, WUCKSEL is set correctly to 1 Hz clock and WUTR value is 2
  • I can also confirm WUTF is set around 3 seconds after entering the infinite loop, but the interrupt routine never fires

 

int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

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

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);

  /* 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_RTC_Init();
  /* USER CODE BEGIN 2 */

  LL_RTC_DisableWriteProtection(RTC);
  //LL_RTC_EnableInitMode(RTC);
  LL_RTC_WAKEUP_Disable(RTC);
  while(!LL_RTC_IsActiveFlag_WUTW(RTC));
  LL_RTC_WAKEUP_SetAutoReload(RTC, 2);
  LL_RTC_WAKEUP_SetClock(RTC, LL_RTC_WAKEUPCLOCK_CKSPRE);
  LL_RTC_EnableIT_WUT(RTC);
  LL_RTC_WAKEUP_Enable(RTC);
  LL_RTC_ClearFlag_WUT(RTC);
  //LL_RTC_DisableInitMode(RTC);
  LL_RTC_EnableWriteProtection(RTC);

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

 

 What I tried to solve this:

1) I went back to my HAL solution, which worked as expected, and displayed the register values using debugger to make sure all the important RTC registers are set the same way. I can confirm my LL code sets RTC CR, ISR and WUTR registers exactly the same as the HAL code. The RTC itself seems to be set the same way in both examples.

2) I wrote code into the infinite loop within main to check for WUTF flag, and if set, toggle an LED and clear the WUTF flag. In that case, the LED is toggled periodically. The toggle occurs every WUTR + 1 seconds, as expected. This way I can confirm the RTC timer is capable of setting WUTF periodically as expected.

The way I see it, the RTC works perfectly fine but the interrupt never fires. Either the NVIC does not react to the WUTF flag being set, or it enters some empty interrupt routine, which is not the RTC_IRQHandler autogenerated routine. But why? NVIC is set. RTC_IRQHandler matches the startup script function name.

I must be missing something, but I have no idea how to progress from here.

Thanks a lot for any assistance.

Kind regards

Jakub

1 ACCEPTED SOLUTION

Accepted Solutions
JakubFranek
Associate II

As a hail Mary effort I pasted my post into Chat GPT, which provided me the two lines which I was missing.

LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_20);  			// Enable interrupt for EXTI line 20 (RTC)
LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_20);  	// Trigger on rising edge for line 20 (RTC)

This issue is therefore solved.

View solution in original post

1 REPLY 1
JakubFranek
Associate II

As a hail Mary effort I pasted my post into Chat GPT, which provided me the two lines which I was missing.

LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_20);  			// Enable interrupt for EXTI line 20 (RTC)
LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_20);  	// Trigger on rising edge for line 20 (RTC)

This issue is therefore solved.