2024-11-06 11:51 AM - edited 2024-11-06 11:52 AM
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)
2) Enable RTC interrupt in NVIC settings
3) Set all drivers to LL
4) This is the generated content of rtc.c
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
/**
* @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.
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
Solved! Go to Solution.
2024-11-07 07:44 AM
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.
2024-11-07 07:44 AM
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.