cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L152C6 LSE RTC WakeUp

kaloyan
Associate III
Posted on August 26, 2013 at 09:49

Hello. I'm trying to use the RTC WakeUp feature to as a countdown timer.

I've tried the code from the StdLib examples:


void
RTC_Config(
void
)

{

NVIC_InitTypeDef NVIC_InitStructure; 

EXTI_InitTypeDef EXTI_InitStructure;


/* Enable the PWR clock */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);


/* Allow access to RTC */

PWR_RTCAccessCmd(ENABLE);


/* LSI used as RTC source clock */

/* The RTC Clock may varies due to LSI frequency dispersion. */

/* Enable the LSI OSC */

RCC_LSICmd(ENABLE);


/* Wait till LSI is ready */

while
(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)

{

}


/* Select the RTC Clock Source */

RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);


/* Enable the RTC Clock */

RCC_RTCCLKCmd(ENABLE);


/* Wait for RTC APB registers synchronisation */

RTC_WaitForSynchro();


/* Calendar Configuration */

RTC_InitStructure.RTC_AsynchPrediv = 0x7F;

RTC_InitStructure.RTC_SynchPrediv = 0x120; 
/* (37KHz / 128) - 1 = 0x120*/

RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;

RTC_Init(&RTC_InitStructure); 


/* EXTI configuration *******************************************************/

EXTI_ClearITPendingBit(EXTI_Line20);

EXTI_InitStructure.EXTI_Line = EXTI_Line20;

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;

EXTI_InitStructure.EXTI_LineCmd = ENABLE;

EXTI_Init(&EXTI_InitStructure);


/* Enable the RTC Wakeup Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure); 


/* Configure the RTC WakeUp Clock source: CK_SPRE (1Hz) */

RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);

RTC_SetWakeUpCounter(0x0);


/* Enable the RTC Wakeup Interrupt */

RTC_ITConfig(RTC_IT_WUT, ENABLE);


/* Enable Wakeup Counter */

RTC_WakeUpCmd(ENABLE);

}

Here is the interrupt code:

1.
void
RTC_WKUP_IRQHandler(
void
)
2.
{
3.
if
(RTC_GetITStatus(RTC_IT_WUT) != RESET) {
4.
GPIO_ToggleBits( GPIOB, GPIO_Pin_6 );
5.
RTC_ClearITPendingBit(RTC_IT_WUT);
6.
EXTI_ClearITPendingBit(EXTI_Line20); 
//OK
7.
}
8.
}

The problem is that this usually doesn't work. I've also changed the LSI to LSE with no success. Later I decided to modify the registers by hand:


RTC->CR = ( 0 << 14 );

RTC->WPR = 0xCA;

RTC->WPR = 0x53;

RTC->CR = ( 0 << 10 ); 
// 6.3 from manual

while
( ! (RTC->ISR && (1 << 10)) );

RTC->WUTR = 0x0;

RTC->CR |= (0x4 << 0);

RTC->CR |= ( 1 << 10 );

RTC->CR |= ( 1 << 14 );

RTC->WPR = 0xFF;

Actually the code above is doing right that:

1.
RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);
2.
RTC_SetWakeUpCounter(0x0);
3.
4.
/* Enable the RTC Wakeup Interrupt */
5.
RTC_ITConfig(RTC_IT_WUT, ENABLE);
6.
7.
/* Enable Wakeup Counter */
8.
RTC_WakeUpCmd(ENABLE);

When I ran this code, the MCU enters the interrupt immediately, then it enters again after the period programmed (for example 5 seconds) and after that it doesn't execute the interrupt code. Please, can you point me to the right way to initialize and run the LSE WakeUp timer, so I can execute arbitrary code in the interrupt's handler function AND to wakeup the MCU from standby mode (in this case I should re-initialize the MCU). When the MCU is externally powered, then I need to use the WakeUp timer just as a countdown timer, but if the user runs it w/o external power, then it should use the WakeUp timer both to start the MCU and to execute some code.
4 REPLIES 4
kaloyan
Associate III
Posted on August 26, 2013 at 18:19

Okay. I've solved it.

When all is set properly, in the IRQ Handler function you have to enable access to the RTC registers (just the same way as if you configure the RTC time and date) to be able to clear the RTC_IT flag. The EXTI flag is cleared w/o this special access requirement. Also it seems a good idea to clear the flag at the WakeUp timer initialization too. Here is the code:


void
RTC_Config(
void
)

{

NVIC_InitTypeDef NVIC_InitStructure; 

EXTI_InitTypeDef EXTI_InitStructure;


/* Enable the PWR clock */

RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);


/* Allow access to RTC */

PWR_RTCAccessCmd(ENABLE);


/* LSI used as RTC source clock */

/* The RTC Clock may varies due to LSI frequency dispersion. */

/* Enable the LSI OSC */

//RCC_LSICmd(ENABLE);

RCC_LSEConfig(RCC_LSE_ON);


/* Wait till LSI is ready */

while
(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)

{

}


/* Select the RTC Clock Source */

RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);


/* Enable the RTC Clock */

RCC_RTCCLKCmd(ENABLE);


/* Wait for RTC APB registers synchronisation */

RTC_WaitForSynchro();


/* Calendar Configuration */

RTC_InitStructure.RTC_AsynchPrediv = 0x7F;

RTC_InitStructure.RTC_SynchPrediv = 0x120; 
/* (37KHz / 128) - 1 = 0x120*/

RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;

RTC_Init(&RTC_InitStructure); 


/*

To enable the RTC Wakeup interrupt, the following sequence is required:

1. Configure and enable the EXTI Line 20 in interrupt mode and select the rising edge

sensitivity.

2. Configure and enable the RTC_WKUP IRQ channel in the NVIC.

3. Configure the RTC to generate the RTC wakeup timer event.


System reset, as well as low power modes (Sleep, Stop and Standby) have no influence on

the wakeup timer.

*/

/* EXTI configuration *******************************************************/

EXTI_ClearITPendingBit(EXTI_Line20);

EXTI_InitStructure.EXTI_Line = EXTI_Line20;

EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;

EXTI_InitStructure.EXTI_LineCmd = ENABLE;

EXTI_Init(&EXTI_InitStructure);


/* Enable the RTC Wakeup Interrupt */

NVIC_InitStructure.NVIC_IRQChannel = RTC_WKUP_IRQn;

NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

NVIC_Init(&NVIC_InitStructure);


RTC_WakeUpCmd(DISABLE);

PWR_RTCAccessCmd(ENABLE);

/* 3.1.3 from AN3371 using hardware RTC

RTC->CR

WUCKSEL -> (only when RTC->CR WUTE = 0; RTC->ISR WUTWF = 1)

000: RTC/16 clock is selected

001: RTC/8 clock is selected

010: RTC/4 clock is selected

011: RTC/2 clock is selected

10x: ck_spre (usually 1 Hz) clock is selected

11x: ck_spre (usually 1 Hz) clock is selected and 216 is added to the WUT counter value

from 1s to 18 hours when WUCKSEL [2:1] = 10

WUTE - Enable Control Bit

WUTIE - Interrupt enable bit

RTC->ISR

WUTF - efent flag

*/

RTC_WakeUpClockConfig(RTC_WakeUpClock_CK_SPRE_16bits);

RTC_SetWakeUpCounter(0x0);

//The WUTF flag must then be cleared by software.

RTC_ClearITPendingBit(RTC_IT_WUT); 
//ClearITPendingBit clears also the flag

//RTC_ClearFlag(RTC_FLAG_WUTF); //MANDATORY!

RTC_ITConfig(RTC_IT_WUT, ENABLE); 
//enable interrupt

RTC_WakeUpCmd(ENABLE);

PWR_RTCAccessCmd(DISABLE); 
//just in case

}

And the IRQ Handler function:


void
RTC_WKUP_IRQHandler(
void
)

{

if
(RTC_GetITStatus(RTC_IT_WUT) != RESET) {

EXTI_ClearITPendingBit(EXTI_Line20); 
//OK

PWR_RTCAccessCmd(ENABLE);

RTC_ClearITPendingBit(RTC_IT_WUT);

RTC_ClearFlag(RTC_FLAG_WUTF);

PWR_RTCAccessCmd(DISABLE);

GPIO_ToggleBits( GPIOB, GPIO_Pin_6 );

}

}

Good luck! Edit: With the code below, it does NOT work (the interrupt is executed only once):


void
RTC_WKUP_IRQHandler(
void
)

{

if
(RTC_GetITStatus(RTC_IT_WUT) != RESET) {

EXTI_ClearITPendingBit(EXTI_Line20); 
//OK

//PWR_RTCAccessCmd(ENABLE);

RTC->WPR = 0xCA;

RTC->WPR = 0x53;

RTC_ClearITPendingBit(RTC_IT_WUT);

RTC_ClearFlag(RTC_FLAG_WUTF);

RTC->WPR = 0xFF;

//PWR_RTCAccessCmd(DISABLE);

GPIO_ToggleBits( GPIOB, GPIO_Pin_6 );

}

}

In the reference manual, RM0038, 6.4 (RTC initialization and status register (RTC_ISR)), it is not clear which bit in the register require special access handling: Note: The ALRAF, ALRBF, WUTF and TSF bits are cleared 2 APB clock cycles after programmingthem to 0.This register is write protected (except for RTC_ISR[13:8] bits). The write access procedureis described in RTC register write protection on page 4 The method described on page 468 says: The following steps are required to unlock the write protection on all the RTC registersexcept for RTC_ISR[13:8], RTC_TAFCR, and RTC_BKPxR.
guillem2
Associate II
Posted on July 17, 2014 at 12:11

Thanks for posting that, I was struggling  with the ST example that wasn't working.

It's pretty awful that the example doesn't work, ST should make an effort to keep them updated.

Thanks again!

Ciavolino.Giuseppe
Associate II
Posted on July 23, 2014 at 23:48

THANK YOU SO MUCH...YOU SAVE ME!

shahmonil93
Associate II
Posted on August 21, 2014 at 11:21

Hey, what all header files have you included?

When i complile this code in CooCox IDE, I get the following errors :-

'RTC_WKUP_IRQn' was not declared in this scope

'RTC_Alarm_B' was not declared in this scope

'PWR_RTCAccessCmd' was not declared in this scope

Also, if you can post the method how you enter the sleep mode? using WFI() ?

Can you show the 'int main()' function as well?!

Thanks for the help!

Monil