cancel
Showing results for 
Search instead for 
Did you mean: 

alarm interrupt missing (sporadic)

bruzzim
Associate II
Posted on January 11, 2011 at 12:48

alarm interrupt missing (sporadic)

15 REPLIES 15
Posted on May 17, 2011 at 14:21

Your RTC_Configuration() code is totally wrong for handling the exit from a STANDBY condition. You need to examine the PWR_FLAG_SB, and do minimal initialization, not tear down the whole RTC/LSE, etc.

Go look at the code in STM32F10xFWLib\Examples\PWR\STANDBY\main.c for a better solution. Also look at the STM32F10xFWLib\Examples\PWR\STOP\main.c code. You will likely need to make a mashup of both to achieve what you want. And you should probably also examine the type of reset that starts your system. Working with the RTC on the STM32 can get rather ugly, and the examples are woefully incomplete. (ie only demonstrate a very narrow mode of operation).

/*******************************************************************************

* Function Name  : RTC_Configuration

* Description    : Configures RTC clock source and prescaler.

* Input          : None

* Output         : None

* Return         : None

*******************************************************************************/

void RTC_Configuration(void)

{

  /* Check if the StandBy flag is set */

  if(PWR_GetFlagStatus(PWR_FLAG_SB) != RESET)

  {/* System resumed from STANDBY mode */

    /* Turn on led connected to GPIO_LED Pin7 */

    GPIO_SetBits(GPIO_LED, GPIO_Pin_7);

    /* Clear StandBy flag */

    PWR_ClearFlag(PWR_FLAG_SB);

    /* Wait for RTC APB registers synchronisation */

    RTC_WaitForSynchro();

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

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

  }

  else

  {/* StandBy flag is not set */

    /* RTC clock source configuration ----------------------------------------*/

    /* Reset Backup Domain */

    BKP_DeInit();

    /* Enable LSE OSC */

    RCC_LSEConfig(RCC_LSE_ON);

    /* Wait till LSE is ready */

    while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)

    {

    }

    /* 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 1s */

    RTC_SetPrescaler(32767);

    /* Wait until last write operation on RTC registers has finished */

    RTC_WaitForLastTask();

  }

}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
bruzzim
Associate II
Posted on May 17, 2011 at 14:21

Hello Clive,

I don't use RTC_Configuration() for reset the clock after the exit from stop mode. If look at attached code (the actual rtc.c file I use):

void SYSCLKConfig_STOP(void)

{

  /* Enable HSE */

  RCC_HSEConfig(RCC_HSE_ON);

  /* Wait till HSE is ready */

  HSEStartUpStatus = RCC_WaitForHSEStartUp();

  if(HSEStartUpStatus == SUCCESS)

    {

#ifdef STM32F10X_CL

      /* Enable PLL2 */

      RCC_PLL2Cmd(ENABLE);

      /* Wait till PLL2 is ready */

      while(RCC_GetFlagStatus(RCC_FLAG_PLL2RDY) == RESET)

 {

 }

#endif

      /* Enable PLL */

      RCC_PLLCmd(ENABLE);

      /* Wait till PLL is ready */

      while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET)

 {

 }

      /* Select PLL as system clock source */

      RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

      /* Wait till PLL is used as system clock source */

      while(RCC_GetSYSCLKSource() != 0x08)

 {

 }

    }

} I got this from ST example, anyway. Do you see any problem with this.

The reason for reboot is that sometimes the alarm routine doesn't run and since it is the service routine to update the next alarm the board stuck in stop mode (until WFI reset)

Thank you very much.

Posted on May 17, 2011 at 14:21

I'm going to have to revisit the STOP stuff, my application was using close to an order of magnitude less power in STANDBY, plus I'm going off for longer than a second. In my usage tearing the whole system up and down every second was not workable as some of the attached hardware takes significantly longer to power up than that. I'd push the idle task to loop on WFI. Bringing up clocks, PLLs and peripherals is quite time consuming. I'd be worried about doing a 1 second alarm unless I had a clear understanding of the worst-case startup time. There are a lot of unbounded while() loops in the code provided by ST. Case in point the RTC_WaitForLastTask() and RTC_WaitForSynchro().

However to avoid a race condition with the RTC ticking and the RTC alarm, I had been waiting for the RTC top of second before programming the alarm.Thus with a sleep time of 4 seconds here the period was 5 seconds.

A quick test harness is ticking away now for about 15 minutes without missing an alarm. I'll let it run overnight and see if it's still ticking in the morning.

#if 1 // RTC Alarm

  if (SleepTime) // Out of STANDBY

    {

    RTC_ClearFlag(RTC_FLAG_SEC); /* Wait till RTC Second event occurs */

        while(RTC_GetFlagStatus(RTC_FLAG_SEC) == RESET);

    RTC_SetAlarm(RTC_GetCounter() + SleepTime); /* Alarm in X second(s) */

    RTC_WaitForLastTask(); /* Wait until last write operation on RTC registers has finished */

    }

#endif

#if 1 // STANDBY

    while(1)

        PWR_EnterSTANDBYMode(); // xxx uA

#else // STOP

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
bruzzim
Associate II
Posted on May 17, 2011 at 14:21

Thank you for your hints, I will perform a such kind of analysis.

In my case I found something more:

I put the update of alarm into RTC routine since I found that I fall in a condition of RTC running but RTC_Alarm not running (overdue and not reset).

What I did is check into RTC routine if the alarm register is old (bad condition), in this case I update the alarm to new safe value (i.e. rtc+10). I can see that even the alarm register is set, the RTC_Alarm routine is not called at the time it should do.

Do you have any idea? I must investigate on this.

Posted on May 17, 2011 at 14:21

I guess you'll have to dig into it more deeply. The STANDBY test I started yesterday is still running 13+ Hours later (effective 5 second alarm period)

If you want it to be a second, you'll need to perhaps use an RTC tick of 500 or 250 ms, and see if you get any precession of the timestamp. If you are totally missing interrupts, that's a whole other matter, which you'll need to investigate.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
bruzzim
Associate II
Posted on May 17, 2011 at 14:21

I understood the cause for loosing alarms: for some reasons, sometimes, the EXTI->RTSR  for Exti line 17 (alarm) is reset. This lead to miss the alarm interrupts.

This is strange since I set that register at startup and never touch this. Also, this seems the only register bit affected by problem.

To workaround this problem I put this check into my RTC service routine

    if (IsAlarmInvalid())

    {

      EXTI_InitTypeDef EXTI_InitStructure;

      EXTI_InitStructure.EXTI_Line = EXTI_Line17;

      EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;

      EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;

      EXTI_InitStructure.EXTI_LineCmd = ENABLE;

      EXTI_Init(&EXTI_InitStructure);        

      SoftRtc_SetAlarm(SoftRtc_Get());

    }

bool IsAlarmInvalid(void)

{

  uint32_t rtc=0, alr=0;

  rtc = RTC->CNTL | (RTC->CNTH<<16);

  alr = RTC->ALRL | (RTC->ALRH<<16);

  if (alr < rtc) return TRUE;

  return FALSE;

} (I know it is not safe to check that volatile register this way)

I'm checking deeply into code to understand why that bit was reset. I'm pretty sure I don't change it.

Thanks and best regards