cancel
Showing results for 
Search instead for 
Did you mean: 

RTC + Sleep-now mode = problem

skrzynka229
Associate
Posted on January 15, 2012 at 17:08

Hello.

In my application i'm using RTC second interrupt (clock/calendar features) and RTC alarm event. I want the system to go into sleep-now low power mode (with all interrupts enabled and running) and wake only on RTC alarm event. But it occurs that it wakes on RTC second interrupt. How to make it awake only on alarm event? Thx in advance. Code: Main program:

RCC_Conf();
NVIC_Conf();
GPIO_Conf();
RTC_Conf();
UART_Conf();
LED_Off();
RTC_SetAlarm(RTC_GetCounter()+5);
while(1)
{
NVIC_SystemLPConfig(NVIC_LP_SEVONPEND, DISABLE);
//NVIC_SystemLPConfig(NVIC_LP_SLEEPDEEP, DISABLE);
//NVIC_SystemLPConfig(NVIC_LP_SLEEPONEXIT, DISABLE);
GPIO_SetBits(LED_PORT, LED1_PIN);
__WFE();
GPIO_ResetBits(LED_PORT, LED1_PIN);
}
void RTC_Conf()
{
/*Allow access to Backup Registers*/
PWR_BackupAccessCmd(ENABLE);
if(BKP_ReadBackupRegister(BKP_DR1)==CONFIGURATION_RESET)
{
/*Enables the clock to Backup and power interface peripherals */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_BKP | RCC_APB1Periph_PWR,ENABLE);
/* Backup Domain Reset */
BKP_DeInit();
//RTCCLK = HSE = 8 MHz /128 = 62500 Hz
RCC_RTCCLKConfig(RCC_RTCCLKSource_HSE_Div128);
RCC_RTCCLKCmd(ENABLE);
RTC_WaitForSynchro();
RTC_WaitForLastTask();
RTC_SetPrescaler(62499);
RTC_WaitForLastTask();
RTC_ITConfig(RTC_IT_SEC, ENABLE);
}
else
{
/* PWR and BKP clocks selection */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
RTC_WaitForSynchro();
/* Wait until last write operation on RTC registers has finished */
RTC_WaitForLastTask();
RTC_ITConfig(RTC_IT_SEC, ENABLE);
RTC_WaitForLastTask();
}
 } 

void RCC_Conf(void)
{
ErrorStatus HSEStartUpStatus;
RCC_DeInit();
RCC_HSEConfig(RCC_HSE_ON);
HSEStartUpStatus = RCC_WaitForHSEStartUp();
if(HSEStartUpStatus == SUCCESS)
{
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
FLASH_SetLatency(FLASH_Latency_2);
// HCLK = SYSCLK
RCC_HCLKConfig(RCC_SYSCLK_Div1);
// PCLK2 = HCLK
RCC_PCLK2Config(RCC_HCLK_Div1);
// PCLK1 = HCLK/2
RCC_PCLK1Config(RCC_HCLK_Div2);
// PLLCLK = 8MHz * 9 = 72 MHz
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(RCC_GetSYSCLKSource() != 0x08);
}
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO, ENABLE);
}

void NVIC_Conf(void)
{
#ifdef VECT_TAB_RAM
// Jezeli tablica wektorow w RAM, to ustaw jej adres na 0x20000000
NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);
#else // VECT_TAB_FLASH
// W przeciwnym wypadku ustaw na 0x08000000
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
#endif
NVIC_InitTypeDef NVIC_InitStructure;
EXTI_InitTypeDef EXTI_InitStructure;
EXTI_DeInit();
/* Configure one bit for preemption priority */
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
/* Enable the RTC Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* Enable the USARTx Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// Linia 17 jako zdarzenie (RTC)
EXTI_StructInit(&EXTI_InitStructure);
EXTI_InitStructure.EXTI_Line = EXTI_Line17;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Event;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
}


1 REPLY 1
Posted on January 15, 2012 at 18:05

If you expect it to be servicing interrupts it's going to leave the sleep state to do that, and you're going to have to put it back to sleep.

Spinning in a idle loop, Sleep / WFI, would be an appropriate way to do that. If you don't want it restarting on the 1 second tick, then you'll need to disable that, and account for the passage of time by looking at the 32-bit counter, rather than managing it a second at a time.

Calendering can be handled by using the 32-bit counter directly, in much the same way as UNIX does, you compute the time/date on demand, it has a wrap time of 136 years. The common failure is to try and constrain the RTC to a 24 hour period.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..