2013-08-26 12:49 AM
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.
2013-08-26 09:19 AM
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.
2014-07-17 03:11 AM
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!2014-07-23 02:48 PM
THANK YOU SO MUCH...YOU SAVE ME!
2014-08-21 02:21 AM