Page 1 of 1

Binary mode/ watchdog interrupt for STM32U073 RTC Problems

Posted: Mon Sep 30, 2024 12:53 am
by doctek
I have looked at lots of STM32 Examples, but have found none for the U0 Series that explain using the RTC in Binary mode and use the LL functions with the wakeup timer.

STM seems to not realize that the RTC in the U0 series is different from that in the other families, even though it is supposedly an RTC3 version also. (Refer to App Note 4759.) The connection of EXTI is *not* the same. The RTC in the U0 is connected as a direct interrupt and uses line 28. In the L071 (for example), the RTC is connected to line 20 and is configurable, so the EXTI must be handled for the RTC to interrupt properly. (I have gotten the L071 RTC to work nicely with interrupts; but the same code does not work, and won't compile, for the U073.) The L0 RTC does not have binary or BCD modes to select either. The U0 RTC has 22 registers with different names and bit names than the 20 registers that the L0 has. It hardly seems like the same peripheral to me. Maybe I'm missing something.

My code is included below. Using digitalWrite to turn on an LED, I can prove that RTC_TAMP_IRQHandler, the interrupt service routine (ISR), is being entered, but the WUTF flag is not set when it does (the conditional fails). The ISR is entered once, but only once. The RTC also works as expeced if I just poll the WUTF flag and reset it when it sets. This code is shown commented out.

Further, I cannot set the bits to enable Binary only mode. As shown in my (Arduino) code, I have tried setting them in two places, but neither works. There is no example showing how to do this. An example showing how to set auto-clearing of the WUTF flag is nowhere to be found. Configuring the wakeup timer to interrupt is not shown either. I've searched through the STM code examples for the CUBE.

I am aware of the STM32RTC Arduino Library - But only BCD mode is supported! (You must read the code, this isn't stated. Look at STMRTC.cpp.) RTC_BINARY_NONE does not seem to be defined. There is no mention of the WakeUp interrupt either or how to set up the RTC in WakeUp mode.

Can any one point me to a useful example for the U0 RTC that uses interrupts, Binary mode and the LL functions? I would be most grateful!

Code: Select all

/*
  RTC - get the rtc to work with interrupts
  9/24/24 - Initial creation.                -jkl
*/
#include <stm32u0xx_ll_rcc.h>     // for RCC
#include <stm32u0xx_ll_bus.h>     // for IOP and APB1 calls
#pragma GCC optimize "O0"  // no optimization
#define LED_PIN LL_GPIO_PIN_8
#define LED_GPIO_PORT GPIOA
const int led = 8;
void setup() {
  pinMode(led, OUTPUT);
  Configure_RTC();
}
void loop() {
  // To test RTC interrupt, don't have to do anything. Just wait.
  /*
  // No interrupt method  -- Works fine!
  if (LL_RTC_IsActiveFlag_WUT(RTC) == 1) {  // wait for RTC wake up
    LL_RTC_ClearFlag_WUT(RTC);              // clear flag so it can signal again
    LL_GPIO_TogglePin(LED_GPIO_PORT, LED_PIN);
  }
 */
}
void Configure_RTC(void) {
  /*##-1- Enables the PWR Clock and Enables access to the backup domain #######*/
  /* To change the source clock of the RTC feature (LSE, LSI), you have to:
     - Enable the power clock
     - Enable write access to configure the RTC clock source (to be done once after reset).
     - Reset the Back up Domain 
     - Configure the needed RTC clock source */
  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
  LL_PWR_EnableBkUpAccess();
  /*##-2- Configure LSE/LSI as RTC clock source ###############################*/
  /* Enable LSI */
  LL_RCC_LSI_Enable();
  while (LL_RCC_LSI_IsReady() != 1) {
  }
  LL_RCC_ForceBackupDomainReset();
  LL_RCC_ReleaseBackupDomainReset();
  LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSI);
  /*##-3- Enable RTC peripheral Clocks #######################################*/
  /* Enable RTC Clock */
  LL_RCC_EnableRTC();
  /*##-4- Disable RTC registers write protection ##############################*/
  LL_RTC_DisableWriteProtection(RTC);
  /* Set prescaler according to source clock */
  LL_RTC_EnableInitMode(RTC);   // Set INIT bit to 1
  while (LL_RTC_IsActiveFlag_INIT(RTC) != 1) {  // Poll INITF until it = 1
  }
  MODIFY_REG(RTC->ICSR, 9, 0);
  MODIFY_REG(RTC->ICSR, 8, 1);
  LL_RTC_SetAsynchPrescaler(RTC, 127);  // Set the Asynch Prescaler
  LL_RTC_SetSynchPrescaler(RTC, 249);   // Set the Synch Prescaler
  //Tried selecting Binary only mode here also - didn't work
  //MODIFY_REG(RTC->ICSR, 9, 0);
  //MODIFY_REG(RTC->ICSR, 8, 1);
  LL_RTC_DisableInitMode(RTC);   // Now clear the INIT bit
  /* Disable wake up timer to modify it */
  LL_RTC_WAKEUP_Disable(RTC);
  /* Wait until it is allow to modify wake up reload value */
  while (LL_RTC_IsActiveFlag_WUTW(RTC) != 1) {
  }
  LL_RTC_WAKEUP_SetAutoReload(RTC, 3);  // set RTC for 3 seconds
  LL_RTC_WAKEUP_SetClock(RTC, LL_RTC_WAKEUPCLOCK_CKSPRE);
  // Select Binary mode here (no LL function) -- Doesn't seem to work here!
  //MODIFY_REG(RTC->ICSR, LL_RTC_ICSR_BIN_1, 0);
  //MODIFY_REG(RTC->ICSR, LL_RTC_ICSR_BIN_0, 1);
  LL_RTC_EnableIT_WUT(RTC);   // comment out for no interrupt
  LL_RTC_WAKEUP_Enable(RTC);
  /* Enable RTC registers write protection */
  LL_RTC_EnableWriteProtection(RTC);
  // comment out NVIC lines for no interrupt
  NVIC_SetPriority(RTC_TAMP_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
  NVIC_EnableIRQ(RTC_TAMP_IRQn);
}
extern "C" __attribute__((naked)) void RTC_TAMP_IRQHandler(void) {
  if (LL_RTC_IsActiveFlag_WUT(RTC) == 1) {  // this seems to never be true??
    LL_RTC_ClearFlag_WUT(RTC);   ///Reset Wake up flag
    LL_GPIO_TogglePin(LED_GPIO_PORT, LED_PIN);
  }
}

Re: Binary mode/ watchdog interrupt for STM32U073 RTC Problems

Posted: Sun Oct 06, 2024 5:30 pm
by doctek
Two minor changes made this work!
First, the NAKED attribute should be removed. Regardless of the post I read suggesting its use for interrupt service routines, it keeps things from working.
Second, the statement for setting the binary mode is incorrect. It should be

Code: Select all

MODIFY_REG(RTC->ICSR, RTC_ICSR_BIN, RTC_ICSR_BIN_0);
Replace both of the MODIFY_REG statements in my code with that and things should work.
Hope that helps someone else.