cancel
Showing results for 
Search instead for 
Did you mean: 

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

Vu.Andy
Associate III
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

6 REPLIES 6
Andrew Neil
Evangelist
Posted on December 06, 2017 at 01:56

RTC backup registers?

EEPROM Emulation?

Posted on December 06, 2017 at 02:18

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

Vu.Andy
Associate III
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.

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
Up vote any posts that you find helpful, it shows what's working..
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(); 

}

Posted on December 12, 2017 at 01:50

I've used this method and it works for Read but gives me an error when I tried to write to RTC backup registers.

I use this function to write to the registers:

void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data)

{

  uint32_t tmp = 0U;

  /* Check the parameters */

  assert_param(IS_RTC_BKP(BackupRegister));

  tmp = (uint32_t)&(hrtc->Instance->BKP0R);

  tmp += (BackupRegister * 4U);

  /* Write the specified register */

  *(__IO uint32_t *)tmp = (uint32_t)Data;

}

The last line *(__IO uint32_t *)tmp = (uint32_t)Data gives me a Hard_Fault error which ends up calling this function:

/**

* @brief This function handles Hard fault interrupt.

*/

void HardFault_Handler(void)

{

  while (1)

  {

  }

}

Do you know what could be the reason?

Thanks.