/* independent watchdog support */ #include "hal.h" #include "watchdog.h" #include "stm32_util.h" #ifndef IWDG_BASE #if defined(STM32H7) #define IWDG_BASE 0x58004800 #elif defined(STM32F7) || defined(STM32F4) #define IWDG_BASE 0x40003000 #elif defined(STM32F1) #define IWDG_BASE 0x40003000 #else #error "Unsupported IWDG MCU config" #endif #endif #ifndef RCC_BASE #error "Unsupported IWDG RCC MCU config" #endif /* defines for working out if the reset was from the watchdog */ #if defined(STM32H7) #define WDG_RESET_STATUS (*(__IO uint32_t *)(RCC_BASE + 0xD0)) #define WDG_RESET_CLEAR (1U<<16) #define WDG_RESET_IS_IWDG (1U<<26) #elif defined(STM32F7) || defined(STM32F4) #define WDG_RESET_STATUS (*(__IO uint32_t *)(RCC_BASE + 0x74)) #define WDG_RESET_CLEAR (1U<<24) #define WDG_RESET_IS_IWDG (1U<<29) #elif defined(STM32F1) #define WDG_RESET_STATUS (*(__IO uint32_t *)(RCC_BASE + 0x24)) #define WDG_RESET_CLEAR (1U<<24) #define WDG_RESET_IS_IWDG (1U<<29) #else #error "Unsupported IWDG MCU config" #endif #define WDG_SAFETY_BIT 0x01 #define WDG_ARMED_BIT 0x02 #define BKP_IDX_FLAGS 0x01 #define BKP_IDX_HOME 0x02 #define BKP_IDX_RPY 0x05 typedef struct { __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */ __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */ __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */ __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */ __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */ } IWDG_Regs; #define IWDGD (*(IWDG_Regs *)(IWDG_BASE)) static bool was_watchdog_reset; static bool watchdog_enabled; static uint32_t boot_backup_state[8]; /* setup the watchdog */ void stm32_watchdog_init(void) { // setup for 2s reset IWDGD.KR = 0x5555; IWDGD.PR = 2; // div16 IWDGD.RLR = 0xFFF; IWDGD.KR = 0xCCCC; watchdog_enabled = true; } /* pat the dog, to prevent a reset. If not called for 1s after stm32_watchdog_init() then MCU will reset */ void stm32_watchdog_pat(void) { if (watchdog_enabled) { IWDGD.KR = 0xAAAA; } } /* save reason code for reset */ void stm32_watchdog_save_reason(void) { if (WDG_RESET_STATUS & WDG_RESET_IS_IWDG) { was_watchdog_reset = true; uint8_t i; for (i=0; i