Skip to main content
Vu.Andy
Associate III
December 5, 2017
Question

Is there a way to save a flag or memory location before going to StandBy or StopMode

  • December 5, 2017
  • 6 replies
  • 1071 views
Posted on December 06, 2017 at 00:39

Hi,

I was wondering if there is a way to save a few flags or CPU condition before I put the CPU either to SandBy or Stop Mode?

Are there any memory locations that I can write to, then retrieve after woken up from either StandBy or Stop mode?

Thanks,

-Andy

    This topic has been closed for replies.

    6 replies

    Andrew Neil
    Super User
    December 6, 2017
    Posted on December 06, 2017 at 01:56

    RTC backup registers?

    EEPROM Emulation?

    A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
    Vu.Andy
    Vu.AndyAuthor
    Associate III
    December 6, 2017
    Posted on December 06, 2017 at 02:18

    Thank you.  I think RTC backup registers are my best option.

    Vu.Andy
    Vu.AndyAuthor
    Associate III
    December 6, 2017
    Posted on December 06, 2017 at 20:02

    I've run in a bit of a potential problem.  In order to use the RTC backup register, I have to execute this function

    at the beginning of the program to select the RTC clock source:

    HAL_RCCEx_PeriphCLKConfig();

    But based on the STM documentation, if this function is executed, all the RTC backup registers are reset to their default

    state, which does present a problem.

    After the the uProcessor has woken up from StandBy Mode, I assume I have to initialize all my clock, INCLUDING

    the RTC clock which means I have to execute this function: HAL_RCCEx_PeriphCLKConfig().  But if I execute

    this function, then all the value in the RTC registers are lost.

    So could you provide some feeback how to resolve this issue?

    Thanks.

    Tesla DeLorean
    Guru
    December 6, 2017
    Posted on December 06, 2017 at 21:50

    Just enable the clocks in the PWR domain, and unlock the PWR/RTC.

      /* Enable the PWR clock */

      RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

      /* Allow access to Backup Domain */

      PWR_BackupAccessCmd(ENABLE);

    Some of the parts also have 4KB of BKPRAM

    In the SPL this is done to get the RTC working, and not stomp on everything if starting via STANDBY

    STM32F0xx_StdPeriph_Lib_V1.5.0\Projects\STM32F0xx_StdPeriph_Examples\PWR\PWR_Standby\main.c

    static void RTC_Config(void)

    {

      RTC_InitTypeDef   RTC_InitStructure;

      RTC_TimeTypeDef   RTC_TimeStructure;

      uint32_t LSIFreq = 0;

      /* Enable the PWR clock */

      RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

      /* Allow access to Backup Domain */

      PWR_BackupAccessCmd(ENABLE);

      /* Disable wake-up source(ALARM) to guarantee free access to WUT level-OR input */

      RTC_ITConfig(RTC_IT_ALRA, DISABLE);

      /* Clear Wakeup flag */

      PWR_ClearFlag(PWR_FLAG_WU);

      /* Enable wake-up source(ALARM) to guarantee free access to WUT level-OR input */

      RTC_ITConfig(RTC_IT_ALRA, ENABLE);

      /* Enable the LSI OSC */

      RCC_LSICmd(ENABLE);

      /* Wait till LSI is ready */

      while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)

      {}

      /* Check if the StandBy flag is set */

      if (PWR_GetFlagStatus(PWR_FLAG_SB) != RESET)

      {

        /* Clear StandBy flag */

        PWR_ClearFlag(PWR_FLAG_SB);

        /* Check if the StandBy flag is cleared */

        if (PWR_GetFlagStatus(PWR_FLAG_SB) != RESET)

        {

          while(1);

        }

        RTC_WaitForSynchro();

        /* No need to configure the RTC as the RTC config(clock source, enable,

        prescaler,...) are kept after wake-up from STANDBY */

      }

      else

      {

        /* RTC Configuration ******************************************************/

        /* Reset Backup Domain */

        RCC_BackupResetCmd(ENABLE);

        RCC_BackupResetCmd(DISABLE);

        /* 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();

        /* Get the LSI frequency:  TIM14 is used to measure the LSI frequency */

        LSIFreq = GetLSIFrequency();

        RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;

        RTC_InitStructure.RTC_AsynchPrediv = 99;

        RTC_InitStructure.RTC_SynchPrediv =  (LSIFreq/100) - 1;

        RTC_Init(&RTC_InitStructure);

        /* Set the time to 01h 00mn 00s AM */

        RTC_TimeStructure.RTC_H12     = RTC_H12_AM;

        RTC_TimeStructure.RTC_Hours   = 0x01;

        RTC_TimeStructure.RTC_Minutes = 0x00;

        RTC_TimeStructure.RTC_Seconds = 0x00;

        RTC_SetTime(RTC_Format_BIN, &RTC_TimeStructure);

      }

    }
    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    Vu.Andy
    Vu.AndyAuthor
    Associate III
    December 11, 2017
    Posted on December 11, 2017 at 23:19

    Hi Clive,

    Thanks for the info very much.  Here is what I plan to do, could you comment if this is correct?

    I am trying to preserve the HAL structure as much as possible and do not change too much.  Thanks.

    The function used to setup RTC is : HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef  *PeriphClkInit)

    Within this function, it checks to see if the RTC clock is selected:

    if(((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == (RCC_PERIPHCLK_RTC))

    {

    }

    If RCC_PERIPHCLK_RTC is not part of the RCC_PeriphCLKInitTypeDef, then it will not initialize the RTC clock.

    So, in the main(), I would check if the uController was from a reset state,

    then go ahead and initialize the RTC.

       

    if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) == RESET)

       PeriphClkInit.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;

      if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)

      {

    _Error_Handler(__FILE__, __LINE__);

      }

    But if the uController was from a StandBy wake up mode, then just enable the Power clock and allow access to RTC:

    if (__HAL_RCC_GET_FLAG(RCC_FLAG_IWDGRST) != RESET)

    {

         /* Enable Power Clock*/

      __HAL_RCC_PWR_CLK_ENABLE();       

      /* Allow access to Backup */

       HAL_PWR_EnableBkUpAccess(); 

    }