EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

STM32 RTC wakeup interrupt not working

Started by SuhaibSyd 1 year ago2 replieslatest reply 1 year ago770 views
I was trying baremetal programming for STM32L412T6 controller. I got stuck at RTC wakeup interrupt. My code is jumping to for loop without going to the interrupt handler, Below mentioning my code.

int main(void)
{

//LedConfig();
rtc_domain_access();
rtc_init();

initialize_rtc_wakeup();
NVIC_EnableIRQ(RTC_WKUP_IRQn);

/* Loop forever */
for(;;)
{
flag = 1;
}
}

void rtc_domain_access(void)
{
/* Enable Clock for Power interface.*/
RCC->APB1ENR1 |= (1U<<28);

/*Disable backup domain write protection*/
PWR->CR1 |= (1U<<8);
while((PWR->CR1 & (1U<<8))==0);

/*Reset the Backup domain*/
RCC->BDCR |= (1U<<16);
RCC->BDCR &= ~(1U<<16);

/*Enable LSE Clock source and wait until LSERDY bit to set*/
RCC->BDCR |= (1U<<0);
while ((RCC->BDCR & (1U<<1)) == 0);

/*Select LSE as RTC Clock*/
RCC->BDCR |= (1U<<8);
RCC->BDCR &= ~(1U<<9);

/*Enable RTC Clock*/
RCC->BDCR |= (1U<<15);

/*Disable access to RTC registers*/
RCC->APB1ENR1 &= ~(1U<<28);

}

void rtc_init(void)
{
/* Disable the write protection for RTC registers */
RTC->WPR = 0xCA;
RTC->WPR = 0x53;

/* Check if the Initialization mode is set */
if((RTC->ICSR & (1U<<6))==0)
{
/* Set the Initialization mode */
RTC->ICSR |= (1U<<7);

/* Wait till RTC is in INIT state*/
while((RTC->ICSR & (1U<<6))==0);
}

/* Clear RTC_CR FMT, OSEL, POL and TAMPOE Bits */
RTC->CR &= ~(1U<<6); //FMT
RTC->CR &= ~(1U<<20); //POL
RTC->CR &= ~(1U<<21); //OSEL
RTC->CR &= ~(1U<<22); //OSEL
RTC->CR &= ~(1U<<26); //TAMPOE

/* Set RTC_CR register */
RTC->CR &= ~(1U<<6); //FMT bit set as Zero,Hour Format Selected as 24
RTC->CR &= ~(1U<<20); //POL bit set as Zero, Output polarity selected as high.
RTC->CR &= ~(1U<<21); //OSEL[22:21] set as zero, output selection disabled.
RTC->CR &= ~(1U<<22);

/* Configure the RTC PRER */
RTC->PRER = 0xFF; // Synchronus value set as 255
RTC->PRER |= (0x7F<<16); // Asynchronus value set as 127.

/* Exit Initialization mode */
RTC->ICSR &= ~(1U<<7); // Clear INIT bit.

/* If CR_BYPSHAD bit = 0, wait for synchro */
if((RTC->CR & (1U<<5))==0)
{
/* Clear RSF flag */
RTC->ICSR &= ~(1U<<5);

/* Wait the registers to be synchronised */
while((RTC->ICSR & (1U<<5))==0);
}

/* Clear RTC_CR TAMPALRM_PU, TAMPALRM_TYPE and OUT2EN Bits */
RTC->CR &= ~(1U<<29);
RTC->CR &= ~(1U<<30);
RTC->CR &= ~(1U<<31);

/*Set Output type as open drain pullup*/
RTC->CR |= (1U<<30);

/* Enable the write protection for RTC registers */
RTC->WPR = 0xFF;

}


void Pwr_Clear_Flag(void)
{
PWR->SCR = 0x1F;
}

void RTCEx_DeactivateWakeUpTimer(void)
{
/*Disable Write protection for RTC Registers*/
RTC->WPR = 0xCA;
RTC->WPR = 0x53;

/*Disable the Wakeup Timer*/
RTC->CR &= ~(1U<<10);

/*In case of interrupt mode is used, the interrupt source must disabled*/
RTC->CR &= ~(1U<<14);

/* Wait till RTC WUTWF flag is set */
while ((RTC->ICSR & (1U<<2)) == 0);

/* Enable the write protection for RTC registers */
RTC->WPR = 0xFF;
}

void RTCEx_SetWakeUpTimer_IT(uint32_t RTC_WAKEUP_TIME_IN_SECONDS,uint32_t WakeUpAutoClr)
{
/* Disable the write protection for RTC registers */
RTC->WPR = 0xCA;
RTC->WPR = 0x53;

/* Clear WUTE in RTC_CR to disable the wakeup timer */
RTC->CR &= ~(1U<<10);

/* Clear flag Wake-Up */
RTC->SCR = (1U<<2);

/* Poll WUTWF until it is set in RTC_ICSR to make sure the access to wakeup autoreload
counter and to WUCKSEL[2:0] bits is allowed. */
if((RTC->ICSR & (1U<<6))==0)
{
while((RTC->ICSR & (1U<<2))==0);
}


/* Configure the Wakeup Timer counter and auto clear value */
RTC->WUTR |= (RTC_WAKEUP_TIME_IN_SECONDS-1);
RTC->WUTR |= (WakeUpAutoClr<<16);

/* Configure the clock source */
RTC->CR &= ~(1U<<0);
RTC->CR &= ~(1U<<1);
RTC->CR |= (1U<<2);

/* RTC WakeUpTimer EXTI Configuration: Interrupt configuration */
EXTI->IMR1 |= (1U<<20);
EXTI->RTSR1 |= (1U<<20);

/* Configure the Interrupt in the RTC_CR register */
RTC->CR |= (1U<<14);

/* Enable the Wakeup Timer */
RTC->CR |= (1U<<10);

/* Enable the write protection for RTC registers */
RTC->WPR = 0xFF;
}

void initialize_rtc_wakeup(void)
{
RTCEx_DeactivateWakeUpTimer();
Pwr_Clear_Flag();
RTCEx_SetWakeUpTimer_IT(RTC_WAKEUP_TIME_IN_SECONDS,WakeUpAutoClr);
}

void RTC_WKUP_IRQHandler(void)
{
EXTI->PR1 = (1U<<20);
if((RTC->MISR & (1U<<2))!=0)
{
//GPIOB->ODR |= 1<<13;
RTC->SCR |= (1U<<2);
count++ ;

}

}

I tried to make a RTC wakeup interrupt in every 3 seconds, when it occurs I tried to increase the value of variable count, instead of that it goes to the infinite loop and changes the flag value.
[ - ]
Reply by hodgecJanuary 24, 2023

Review your startup code. Make sure the the interrupt vector table is setup correctly with the RTC_WKUP_IRQn vector is pointing to RTC_WKUP_IRQHandler and not some generic empty handler.

Additionally I would make sure that RTC_WKUP_IRQn is defined to be the correct vector number.

[ - ]
Reply by jmford94January 24, 2023

Don't you have to be sleeping to wake up?

 Something like this:

                /* Enter STOP 2 mode */
                HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
The 2024 Embedded Online Conference