2016-07-05 12:35 AM
Hello, I'm trying to put my STM32F105 device into stop mode and it's important for me to keep calculating time. I'm trying to put system time into backup registers but then it somehow messes up my system. It seems like somewhere in the middle of stop mode the prescaler gets lost and RTC->CNT value starts increment extremely fast. To be more specific I'll give some details about my RTC configuration and entrance to stop mode code.
void RTC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure; // Configure the interrupt handler
/* Enable PWR and BKP clock */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
/* Enable WKUP pin */
//PWR_WakeUpPinCmd(ENABLE);
/* Allow access to BKP Domain */
PWR_BackupAccessCmd(ENABLE);
//SystemTime = BKP_ReadBackupRegister(BKP_DR1);
//SystemTime <<= 16;
//SystemTime |= BKP_ReadBackupRegister(BKP_DR2);
/* RTC clock source configuration ----------------------------------------*/
/* Reset Backup Domain */
BKP_DeInit();
/* Enable LSE OSC */
RCC_LSEConfig(RCC_LSE_ON);
/* Wait till LSE is ready */
osDelay(1000);
if ( RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET )
{
//nepasileido
DeviceState.WorkingLSI40KHZ = 1;
//isjungiam isorini kvarca
RCC_LSEConfig(RCC_LSE_OFF);
//ijungiam vidini 40KHz RC rezonatoriu
RCC_LSICmd(ENABLE);
while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET )
{
osDelay(100);
}
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
/* Enable the RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* RTC configuration -----------------------------------------------------*/
/* Wait for RTC APB registers synchronisation */
RTC_WaitForSynchro();
/* Set the RTC time base to 2s */
lastPrescaler = 79999;
RTC_SetPrescaler(lastPrescaler);
RTC_WaitForLastTask();
}
else
{
//pasileido
/* Select the RTC Clock Source */
RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
/* Enable the RTC Clock */
RCC_RTCCLKCmd(ENABLE);
/* RTC configuration -----------------------------------------------------*/
/* Wait for RTC APB registers synchronisation */
RTC_WaitForSynchro();
/* Set the RTC time base to 2s */
lastPrescaler = 65535;
RTC_SetPrescaler(lastPrescaler);
RTC_WaitForLastTask();
}
RTC_ClearITPendingBit(RTC_IT_OW);
RTC_ITConfig(RTC_IT_SEC, ENABLE); // Enables overflow interrupt
RTC_WaitForLastTask(); // Wait until last write operation on RTC registers has finished
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);
}
I'm currently using external crystal oscillator for RTC clocking and I'm not sure how it works while my device goes into stop mode. Shall I change RTC's oscillator from LSE to LSI before going to low power mode? In order to synchronize time every hour I update RTC->CNT value with time from NTP servers using RTC_SetCounter(time); commands but for some reason it seems like my code works better without SetCounter commands, maybe there's a must to use commands like RTC_WaitForLastTask(); after storing time value into RTC registers ?
To give you a better view of where I struggle I'm also giving my code of where I go into stop mode and RTC interrupt handler part
void RTC_IRQHandler(void)
{
// @todo RTC interrupt handler
if (RTC_GetITStatus(RTC_IT_SEC) != RESET)
{
RTC_ClearITPendingBit(RTC_IT_SEC);
TickFromReset++;
if ( SystemTime > 0) SystemTime++;
//BKP_WriteBackupRegister(BKP_DR2, SystemTime & 0xFFFF);
//BKP_WriteBackupRegister(BKP_DR1, SystemTime >> 16 );
GPS_Coord_Sync_05Hz();
if (Sleep.SleepingThread.IsSleeping > 0)
{
// if ((FixedInputs & 0x10) > 0)
// {
//// osSemaphoreRelease(wakeUpSemaphore);
// Sleep.WakeUp = 1;
// Sleep.TimeTillSleep = 15;
// }
// // patikrinti
#ifdef NODEBUG
IWDG_ReloadCounter();
#endif
}
else if ((FixedInputs & 0x10) == 0 && !Sleep.SleepEnabled)
{
if (Sleep.TimeTillSleep > 0)
Sleep.TimeTillSleep--;
else
{
Sleep.SleepEnabled = 1;
}
}
}
}//I know that some of those might not make any sense to you so just stay with hardware configuration part
//There's my idle os task---->
void os_idle_demon (void) {
/* The idle demon is a system thread, running when no other thread is */
/* ready to run. */
for (;;)
{
/* HERE: include optional user code to be executed when no thread runs.*/
if (Sleep.SleepEnabled == 1)
{
if (Sleep.WakeUp == 1) //is sleeping and has to wake up now
{
SystemClocksInit(); //needed to configure system clocks after wake up from stop mode
SystemTime = RTC_GetCounter(); //i think this might break my system, but has to update system time variable from RTC registers
// RTC_WaitForLastTask(); //not sure if needed
flash_size(); //external flash configuration
Sleep.ADCnFlashSleep = 0; //this is basically used for ''last touch'' before going to stop mode
Sleep.TimeTillSleep = 30; //sort of a timer used in order to prevent fast toggle from stop to running power modes
Sleep.WakeUp = 0;
Sleep.SleepEnabled = 0;
osSemaphoreRelease(wakeUpSemaphore);
}
else if (Sleep.SleepingThread.IsSleeping == 0x3FF) //check if all threads have semaphores waiting for wake up event
{
// __wfi();
if (Sleep.ADCnFlashSleep == 0) //last system configuration before going to sleep
{
// adcmanager_deinit(); //this is supposed to turn of MCU's ADC1 clock and make ADC inputs go to IN_FLOATING_MODE
//but then for some reason after this MCU doesnt go into stop mode
//Not sure if RTC clock configuration is needed here
RTC_SetCounter(SystemTime);
// RTC_WaitForLastTask(); //not sure if needed
flash_deinit();
Sleep.ADCnFlashSleep = 1;
}
PWR_EnterSTOPMode(PWR_Regulator_ON, PWR_STOPEntry_WFI); //PWR_Regulator_LowPower
}
}
}
}
Would be grateful if you shared your experiences with time calculation in low power modes :)
#stmm32-stop-mode
2016-07-05 01:53 AM
Couple of observations.
The LSI isn't in the low power domain. The prescalers are only 16-bit, as I recall. The LSE can take more than a second to start.2016-07-05 02:08 AM
2016-07-05 07:42 AM
Hi daris.marius,
Try to creat a simple code one with rtos and one without , with enabling RTC counter and entering stop mode. Go step by step by adding your code parts , to identify what is causing the problem. -Hannibal-