AnsweredAssumed Answered

RTC on STM8L going fast forward

Question asked by Javor Markov on Apr 12, 2018

Hello,

 

I'm using a custom board with STM8L151K4 MCU on batteries. Everything works awesome, power consumption is minimal, state is active-halt (MCU is woken via a button) with RTC on. RTC is used with LSE, but trouble is that for several days in real time, RTC moves fast forward (seems to be accelerated somehow) with several days. For example: I set up the clock on 06.04.2018, checking it on 12.04.2018, it's already 19.04.2018... 

In my algorithm, I often have to change clock frequency when MCU is awaken from LSI to HSI (need some computational power for a short time) and then back to LSI. I couldn't find any information of whether it affects the RTC clock source which should be LSE all the time. Here are parts of my code:

void setSpeed(bool HighSpeed)
{
     ReadyToSleep = FALSE;
     
     tmrSet(FALSE);
     if (HighSpeed)
     {
          if (CLK_GetSYSCLKSource() == CLK_SYSCLKSource_HSI)
          {
               tmrSet(TRUE);
               return;
          }
          //CLK_MainRegulatorCmd(ENABLE);
          //FLASH_PowerRunModeConfig(FLASH_Power_On);
          
          
          //enable HSI
          CLK_HSICmd(ENABLE);
          //wait till hardware sets the flag
          while (CLK_GetFlagStatus(CLK_FLAG_HSIRDY) == 0) ;
          
          CLK_SYSCLKSourceSwitchCmd(ENABLE);
          CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_HSI);
          CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);
          while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_HSI) ;
          CLK_SYSCLKSourceSwitchCmd(DISABLE);
     
          //disable LSI as we don't need it anymore
          CLK_LSICmd(DISABLE);
          //10 ms interrupt on HSI
          TIM4_TimeBaseInit(TIM4_Prescaler_2048, 77);
          //10 ms interrupt on HSI /**/
     }
     else
     {
          if (CLK_GetSYSCLKSource() == CLK_SYSCLKSource_LSI)
          {
               //LED_RED_OFF;
               tmrSet(TRUE);
               return;
          }
          //enable HSI
          CLK_LSICmd(ENABLE);
          //wait till hardware sets the flag
          while (CLK_GetFlagStatus(CLK_FLAG_LSIRDY) == 0) ;
          
          CLK_SYSCLKSourceSwitchCmd(ENABLE);
          CLK_SYSCLKSourceConfig(CLK_SYSCLKSource_LSI);
          CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1);
          while (CLK_GetSYSCLKSource() != CLK_SYSCLKSource_LSI) ;
          CLK_SYSCLKSourceSwitchCmd(DISABLE);
     
          //disable HSI as we don't need it anymore
          CLK_HSICmd(DISABLE);

          //10 ms interrupt on LSI
          TIM4_TimeBaseInit(TIM4_Prescaler_32, 10);
          //10 ms interrupt on LSI /**/
     }

     tmrSet(TRUE);
     //LED_RED_OFF;
}



void setup_clock(void)
{
     //CLK_HSECmd(DISABLE);
     TIM4_DeInit();
     CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, ENABLE);

//disable all the peripherals, trying to achieve as low power consumption as possible
     CLK_PeripheralClockConfig(CLK_Peripheral_LCD, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_ADC1, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_USART1, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_USART2, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_USART3, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_SPI1, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_SPI2, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_BEEP, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_DAC, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_I2C1, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_DMA1, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_COMP, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_AES, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_CSSLSE, DISABLE);
     //CLK_PeripheralClockConfig(CLK_Peripheral_RTC, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_BOOTROM, DISABLE);
     
     CLK_PeripheralClockConfig(CLK_Peripheral_TIM1, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_TIM2, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_TIM3, DISABLE);
//     CLK_PeripheralClockConfig(CLK_Peripheral_TIM4, DISABLE);
     CLK_PeripheralClockConfig(CLK_Peripheral_TIM5, DISABLE);
     TIM1->CR1 &= (uint8_t)(~TIM1_CR1_CEN);
     TIM2->CR1 &= (uint8_t)(~TIM_CR1_CEN);
     TIM3->CR1 &= (uint8_t)(~TIM_CR1_CEN);
//     TIM4->CR1 &= (uint8_t)(~TIM_CR1_CEN);
     TIM5->CR1 &= (uint8_t)(~TIM_CR1_CEN);
     //disable all the peripherals, trying to achieve as low power consumption as possible

     PWR_PVDCmd(DISABLE);
 
     setSpeed(SPEED_LOW);
     
     /* Set STM8 in low power */
     //start the low speed external crystal
     CLK_LSEConfig(CLK_LSE_ON);
     //and wait till it's stable
     while (CLK_GetFlagStatus(CLK_FLAG_LSERDY) == RESET) ;
     //set RTC divider to 1, i.e. RTS is running on 32.767 kHz
  CLK_RTCClockConfig(CLK_RTCCLKSource_LSE, CLK_RTCCLKDiv_1);
     //start the RTC itself
  CLK_PeripheralClockConfig(CLK_Peripheral_RTC, ENABLE); 
     PWR_UltraLowPowerCmd(ENABLE);
     
     //setup RTC
     //24-hour format. We myself don't like the 0-12 am/pm, so we always work with 0-24
     //RTC_DeInit();
     RTC_StructInit(&rtc);
     rtc.RTC_HourFormat = RTC_HourFormat_24;
     rtc.RTC_AsynchPrediv = 0x7F;
     rtc.RTC_SynchPrediv = 0x00FF;
     if (RTC_Init(&rtc) == ERROR)
     {
          //TODO:
          //blink RED LED several times
          SetLedRed(lmBlinkThree);
     }
     
     RTC_DateStructInit(&currentDateTime.date);
     RTC_TimeStructInit(&currentDateTime.time);
     
     RTC_ITConfig(RTC_IT_ALRA | RTC_IT_TAMP | RTC_IT_WUT, DISABLE);
     RTC_AlarmCmd(DISABLE);     
     //setup RTC
     
     TIM4_ITConfig(TIM4_IT_Update, ENABLE);
     TIM4_ClearFlag(TIM4_FLAG_Update);
     tmrSet(FALSE);
}

tmrSet is a function that starts or stops Timer 4 - nothing else. Setup_Clock() is called only once on MCU initialization (on start of the program), whereas setSpeed is called whenever I need to switch clock source.

Any suggestion will be highly appreciable.

 

Thanks in advance.

 

Regards,

Javor

Outcomes