How to feed the dog during stm32 hibernation and hibernation

Publisher:huanguuLatest update time:2018-05-14 Source: eefocus Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

Independent watchdog (IWDG) and low power mode are often used in STM32 development. The watchdog is to detect and solve faults caused by software errors, and the low power mode is to enter sleep mode to save power when the CPU does not need to continue running. The clock of the independent watchdog is provided by an independent RC oscillator (generally 40kHz for STM32F10x), which is still valid even when the main clock fails, so it can work in stop and standby mode. And once the independent watchdog is started, it can no longer be stopped except for system reset. But one problem caused by this is that when the MCU enters low power mode, the CPU stops running and cannot feed the dog, which will cause the system to reset frequently. So how to solve this problem, can't the independent watchdog and low power mode be used at the same time?

A good way is to feed the watchdog by waking up the RTC regularly in sleep mode, and then enter sleep mode again after feeding. For example, the watchdog reset interval is 10s. Then set the RTC alarm interrupt time to 5s before entering sleep mode. In this way, the watchdog is woken up and fed every 5s. This can solve the problem well.


while(1)  

  {  

    // Execute the task  

    Task1();  

    Task2();  

    // ..  

  

    // Feed the dog  

    dev_iwdg_feed();  

  

    // Enter standby mode switch  

    if(m_bEnterStandByMode)  

    {     

        // Enable external interrupt, GPIOB3, to wake up the MCU from standby mode  

        dev_exti_enable(TRUE);  

ENTERSTOPMODE:    

        // Set the RTC alarm to generate an RTC alarm interrupt every 5 seconds*/  

        dev_rtc_setAlarm(5);  

      

        // Enter stop mode (low power consumption) until awakened by an external interrupt  

        PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);  

      

        // Is it the RTC alarm interrupt wakeup?  

        if(dev_rtc_isAlarm())  

        {  

            // Feed the dog  

            dev_iwdg_feed();  

            // After feeding the dog, continue to enter stop mode  

            goto ENTERSTOPMODE;   

        }  

        // Disable external interrupts   

        dev_exti_enable(FALSE);  

        // Restore system clock after waking up from stop mode  

        dev_clk_restore();  

    }               

  }  

Here is the complete code:


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

// STM32F10x StopMode RTC Feed Dog   

// compiler: Keil UV3       

// 2013-01-04 , By friehood       

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

#include "stm32f10x_lib.h"  

#include "platform_config.h"  

static Boolean g_bRTCAlarm = FALSE;  

  

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

* Function Name: RCC_Configuration  

* Description: Configures the different system clocks.  

* Input : None  

* Output : None  

* Return : None  

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

void RCC_Configuration(void)  

{  

    /* RCC system reset(for debug purpose) */  

    RCC_DeInit();  

  

    /* Enable HSE */  

    RCC_HSEConfig(RCC_HSE_ON);  

  

    /* Wait till HSE is ready */  

    if(RCC_WaitForHSESTartUp() == SUCCESS)  

    {  

        /* Enable Prefetch Buffer */  

        FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);  

  

        //FLASH timing control   

        //Recommended value: SYSCLK = 0~24MHz Latency=0   

        // SYSCLK = 24~48MHz Latency=1   

        // SYSCLK = 48~72MHz Latency=2  

        //FLASH_SetLatency(FLASH_Latency_1); //Warning: Changing to 1 will affect the DMA value (such as ADC acquisition value will be misplaced)  

        FLASH_SetLatency(FLASH_Latency_2);  

  

        /* HCLK = SYSCLK */  

        RCC_HCLKConfig(RCC_SYSCLK_Div1);   

  

        /* PCLK2 = HCLK */  

        RCC_PCLK2Config(RCC_HCLK_Div1);   

  

        /* PCLK1 = HCLK/2 */  

        RCC_PCLK1Config(RCC_HCLK_Div2);  

  

        /* PLLCLK = 12MHz * 3 = 36 MHz */  

        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_3);  

  

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

        {  

        }  

    }  

    /* Enable PWR and BKP clock */  

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);  

  

    /* Enable AFIO clock */  

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  

}  

  

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

* Function Name: NVIC_Configuration 

* Description: Configures the nested vectored interrupt controller. 

* Input : None 

* Output : None 

* Return : None 

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

void NVIC_Configuration(void)  

{  

  NVIC_InitTypeDef NVIC_InitStructure;  

  

#ifdef VECT_TAB_RAM  

  /* Set the Vector Table base location at 0x20000000 */  

  NVIC_SetVectorTable(NVIC_VectTab_RAM, 0x0);  

#else /* VECT_TAB_FLASH */  

  /* Set the Vector Table base location at 0x08000000 */  

  NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);  

#endif  

  

  /* Configure one bit for preemption priority */  

  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);  

}  

  

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

* Function Name: SysTick_Configuration 

* Description: Configures the SysTick to generate an interrupt each 1 millisecond. 

* Input : None 

* Output : None 

* Return : None 

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

void SysTick_Configuration(void)  

{  

  /* Select AHB clock(HCLK) as SysTick clock source */  

  SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);  

  

  /* Set SysTick Priority to 3 */  

  NVIC_SystemHandlerPriorityConfig(SystemHandler_SysTick, 3, 0);  

     

  /* SysTick interrupt each 1ms with HCLK equal to 72MHz */  

  SysTick_SetReload(72000);  

  

  /* Enable the SysTick Interrupt */  

  SysTick_ITConfig(ENABLE);  

}  

  

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

* Function Name : Delay 

* Description: Inserts a delay time. 

* Input: nTime: specifies the delay time length, in milliseconds. 

* Output : None 

* Return : None 

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

void Delay(u32 nTime)  

{  

  /* Enable the SysTick Counter */  

  SysTick_CounterCmd(SysTick_Counter_Enable);  

    

  TimingDelay = nTime;  

  

  while(TimingDelay != 0);  

  

  /* Disable the SysTick Counter */  

  SysTick_CounterCmd(SysTick_Counter_Disable);  

  /* Clear the SysTick Counter */  

  SysTick_CounterCmd(SysTick_Counter_Clear);  

}  

  

  

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

* Function Name: RTC_Configuration 

* Description: Configures RTC clock source and prescaler. 

* Input : None 

* Output : None 

* Return : None 

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

void RTC_Configuration(void)  

{  

    EXTI_InitTypeDef EXTI_InitStructure;  

    NVIC_InitTypeDef NVIC_InitStructure;  

      

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

    /* Allow access to BKP Domain */  

    PWR_BackupAccessCmd(ENABLE);  

  

    /* Reset Backup Domain */  

    BKP_DeInit();  

  

    /* Enable the LSI OSC */  

    RCC_LSICmd(ENABLE);  

  

    /* Wait till LSI is ready */  

    while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET){}  

      

    /* Select the RTC Clock Source */  

    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);  

  

    /* Enable the RTC Clock */  

    RCC_RTCCLKCmd(ENABLE);  

  

    /* RTC configuration -------------------------------------------------- ---------*/  

    /* Wait for RTC APB registers synchronization */  

    RTC_WaitForSynchro();  

  

    /* Set RTC prescaler: set RTC period to 1sec */  

    RTC_SetPrescaler(40000);  

      

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

    RTC_WaitForLastTask();  

  

    /* Enable the RTC Alarm interrupt */  

    RTC_ITConfig(RTC_IT_ALR, ENABLE);  

      

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

    RTC_WaitForLastTask();  

  

    /* Configure EXTI Line17(RTC Alarm) to generate an interrupt on rising edge */  

    EXTI_ClearITPendingBit(EXTI_Line17);  

    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);  

  

    /* Enable the RTC Interrupt */  

    NVIC_InitStructure.NVIC_IRQChannel = RTCAlarm_IRQChannel;  

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  

    NVIC_Init(&NVIC_InitStructure);  

}  

  

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

* Function Name: RTCAlarm_IRQHandler 

* Description: This function handles RTC Alarm interrupt request. 

* Input : None 

* Output : None 

* Return : None 

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

void RTCAlarm_IRQHandler(void)  

{  

    if(RTC_GetITStatus(RTC_IT_ALR) != RESET)  

    {  

        /* Set the RTC alarm flag */  

        g_bRTCAlarm = TRUE;  

  

        /* Clear EXTI line17 pending bit */  

        EXTI_ClearITPendingBit(EXTI_Line17);  

  

        /* Check if the Wake-Up flag is set */  

        if(PWR_GetFlagStatus(PWR_FLAG_WU) != RESET)  

        {  

            /* Clear Wake Up flag */  

            PWR_ClearFlag(PWR_FLAG_WU);  

        }                                                                         

                                                           

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

        RTC_WaitForLastTask();     

        /* Clear RTC Alarm interrupt pending bit */  

        RTC_ClearITPendingBit(RTC_IT_ALR);  

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

        RTC_WaitForLastTask();  

    }  

}  

  

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

* Function Name: dev_rtc_setAlarm 

* Description : Set the RTC alarm. 

* Input: alarm time 

* Output : None 

* Return : None 

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

void dev_rtc_setAlarm(u32 AlarmValue)  

{  

    /* Clear the RTC SEC flag */  

    RTC_ClearFlag(RTC_FLAG_SEC);  

    /* Wait clear RTC flag sccess */  

    while(RTC_GetFlagStatus(RTC_FLAG_SEC) == RESET);  

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

    RTC_WaitForLastTask();   

  

    /* Sets the RTC alarm value */  

    RTC_SetAlarm(RTC_GetCounter() + AlarmValue);  

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

    RTC_WaitForLastTask();   

}  

  

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

* Function Name: dev_rtc_isAlarm 

* Description: Whether the RTC alarm is triggered 

* Input : None 

* Output : None 

* Return : TRUE: triggered, FALSE: not triggered 

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

Boolean dev_rtc_isAlarm(void)  

{  

    if(g_bRTCAlarm)  

    {  

        /* Clear the RTC alarm flag */  

        g_bRTCAlarm = FALSE;  

        return TRUE;  

    }  

    return FALSE;             

}  

  

void dev_iwdg_init(void)  

{  

    /* Enable write access to IWDG_PR and IWDG_RLR registers */  

    IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);  

    /* IWDG counter clock: 40KHz(LSI) / 256 = 0.15625 KHz */  

    IWDG_SetPrescaler(IWDG_Prescaler_256);  

    /* Set counter reload value to 1562 */  

    IWDG_SetReload(1562); // 10s  

    /* Reload IWDG counter */  

    IWDG_ReloadCounter();  

    /* Enable IWDG (the LSI oscillator will be enabled by hardware) */  

    IWDG_Enable();  

}  

  

void dev_iwdg_feed(void)  

{  

    IWDG_ReloadCounter();  

}  

  

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

* Function Name: dev_clk_restore 

* Description: Restore system clock after wake-up from STOP: enable HSE, PLL 

* and select PLL as system clock source. 

* Input : None 

* Output : None 

* Return : None 

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

void dev_clk_restore(void)  

{  

  /* Enable HSE */  

  RCC_HSEConfig(RCC_HSE_ON);  

  

  /* Wait till HSE is ready */  

  HSEStartUpStatus = RCC_WaitForHSEStartUp();  

  

  if(HSESTartUpStatus == SUCCESS)  

  {  

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

    {  

    }  

  }  

}  

  

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

* Function Name: EXTI_Configuration 

* Description: Configures EXTI Line3. 

* Input : None 

* Output : None 

* Return : None 

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

void EXIT_Configuration(void)  

{  

    EXTI_InitTypeDef EXTI_InitStructure;  

  

    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource3);  

    EXTI_ClearITPendingBit(EXTI_Line3);  

    EXTI_InitStructure.EXTI_Line = EXTI_Line3;  

    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;                                         

    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;   

    EXTI_InitStructure.EXTI_LineCmd = ENABLE;  

    EXTI_Init(&EXTI_InitStructure);  

}  

  

void dev_exti_enable(Boolean bEnable)  

{  

    NVIC_InitTypeDef NVIC_InitStructure;  

  

    /* Clear the Key Button EXTI line pending bit */  

    EXTI_ClearITPendingBit(EXTI_Line3);  

  

    NVIC_ClearIRQChannelPendingBit(EXTI3_IRQChannel);  

    NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQChannel;  

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  

    NVIC_InitStructure.NVIC_IRQChannelCmd = bEnable ? ENABLE : DISABLE;  

    NVIC_Init(&NVIC_InitStructure);   

}  

  

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

* Function Name : main 

* Description: Main program. 

* Input : None 

* Output : None 

* Return : None 

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

int main(void)  

{  

  /* System Clocks Configuration */  

  RCC_Configuration();  

  

  /* NVIC configuration */  

  NVIC_Configuration();  

  

  /* Configure RTC clock source and prescaler */  

  RTC_Configuration();  

  

  /* Configure the SysTick to generate an interrupt each 1 millisecond */  

  SysTick_Configuration();  

  

  /* Configures EXTI Line3 */  

  EXIT_Configuration();  

  

  /* IWDG initialize*/  

  dev_iwdg_init();  

  

  while(1)  

  {  

    // Execute the task  

    Task1();  

    Task2();  

    // ..  

  

    // Feed the dog  

    dev_iwdg_feed();  

  

    // Enter standby mode switch  

    if(m_bEnterStandByMode)  

    {     

        // Enable external interrupt, GPIOB3, to wake up the MCU from standby mode  

        dev_exti_enable(TRUE);  

ENTERSTOPMODE:    

        // Set the RTC alarm to generate an RTC alarm interrupt every 5 seconds*/  

        dev_rtc_setAlarm(5);  

      

        // Enter stop mode (low power consumption) until awakened by an external interrupt  

        PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);  

      

        // Is it the RTC alarm interrupt wakeup?  

        if(dev_rtc_isAlarm())  

        {  

            // Feed the dog  

            dev_iwdg_feed();  

            // After feeding the dog, continue to enter stop mode  

            goto ENTERSTOPMODE;   

        }  

        // Disable external interrupts   

        dev_exti_enable(FALSE);  

        // Restore system clock after waking up from stop mode  

        dev_clk_restore();  

    }               

  }  

}  


Reference address:How to feed the dog during stm32 hibernation and hibernation

Previous article:Use of STM32 independent watchdog
Next article:Summary of the watchdog experiment of STM32F107

Latest Microcontroller Articles
  • Download from the Internet--ARM Getting Started Notes
    A brief introduction: From today on, the ARM notebook of the rookie is open, and it can be regarded as a place to store these notes. Why publish it? Maybe you are interested in it. In fact, the reason for these notes is ...
  • Learn ARM development(22)
    Turning off and on interrupts Interrupts are an efficient dialogue mechanism, but sometimes you don't want to interrupt the program while it is running. For example, when you are printing something, the program suddenly interrupts and another ...
  • Learn ARM development(21)
    First, declare the task pointer, because it will be used later. Task pointer volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • Learn ARM development(20)
    With the previous Tick interrupt, the basic task switching conditions are ready. However, this "easterly" is also difficult to understand. Only through continuous practice can we understand it. ...
  • Learn ARM development(19)
    After many days of hard work, I finally got the interrupt working. But in order to allow RTOS to use timer interrupts, what kind of interrupts can be implemented in S3C44B0? There are two methods in S3C44B0. ...
  • Learn ARM development(14)
  • Learn ARM development(15)
  • Learn ARM development(16)
  • Learn ARM development(17)
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号