watchdog.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. /*
  2. independent watchdog support
  3. */
  4. #include "hal.h"
  5. #include "watchdog.h"
  6. #include "stm32_util.h"
  7. #ifndef IWDG_BASE
  8. #if defined(STM32H7)
  9. #define IWDG_BASE 0x58004800
  10. #elif defined(STM32F7) || defined(STM32F4)
  11. #define IWDG_BASE 0x40003000
  12. #elif defined(STM32F1)
  13. #define IWDG_BASE 0x40003000
  14. #else
  15. #error "Unsupported IWDG MCU config"
  16. #endif
  17. #endif
  18. #ifndef RCC_BASE
  19. #error "Unsupported IWDG RCC MCU config"
  20. #endif
  21. /*
  22. defines for working out if the reset was from the watchdog
  23. */
  24. #if defined(STM32H7)
  25. #define WDG_RESET_STATUS (*(__IO uint32_t *)(RCC_BASE + 0xD0))
  26. #define WDG_RESET_CLEAR (1U<<16)
  27. #define WDG_RESET_IS_IWDG (1U<<26)
  28. #elif defined(STM32F7) || defined(STM32F4)
  29. #define WDG_RESET_STATUS (*(__IO uint32_t *)(RCC_BASE + 0x74))
  30. #define WDG_RESET_CLEAR (1U<<24)
  31. #define WDG_RESET_IS_IWDG (1U<<29)
  32. #elif defined(STM32F1)
  33. #define WDG_RESET_STATUS (*(__IO uint32_t *)(RCC_BASE + 0x24))
  34. #define WDG_RESET_CLEAR (1U<<24)
  35. #define WDG_RESET_IS_IWDG (1U<<29)
  36. #else
  37. #error "Unsupported IWDG MCU config"
  38. #endif
  39. typedef struct
  40. {
  41. __IO uint32_t KR; /*!< IWDG Key register, Address offset: 0x00 */
  42. __IO uint32_t PR; /*!< IWDG Prescaler register, Address offset: 0x04 */
  43. __IO uint32_t RLR; /*!< IWDG Reload register, Address offset: 0x08 */
  44. __IO uint32_t SR; /*!< IWDG Status register, Address offset: 0x0C */
  45. __IO uint32_t WINR; /*!< IWDG Window register, Address offset: 0x10 */
  46. } IWDG_Regs;
  47. #define IWDGD (*(IWDG_Regs *)(IWDG_BASE))
  48. static bool was_watchdog_reset;
  49. static bool watchdog_enabled;
  50. /*
  51. setup the watchdog
  52. */
  53. void stm32_watchdog_init(void)
  54. {
  55. // setup for 2s reset
  56. IWDGD.KR = 0x5555;
  57. IWDGD.PR = 2; // div16
  58. IWDGD.RLR = 0xFFF;
  59. IWDGD.KR = 0xCCCC;
  60. watchdog_enabled = true;
  61. }
  62. /*
  63. pat the dog, to prevent a reset. If not called for 1s
  64. after stm32_watchdog_init() then MCU will reset
  65. */
  66. void stm32_watchdog_pat(void)
  67. {
  68. if (watchdog_enabled) {
  69. IWDGD.KR = 0xAAAA;
  70. }
  71. }
  72. /*
  73. save reason code for reset
  74. */
  75. void stm32_watchdog_save_reason(void)
  76. {
  77. if (WDG_RESET_STATUS & WDG_RESET_IS_IWDG) {
  78. was_watchdog_reset = true;
  79. }
  80. }
  81. /*
  82. clear reason code for reset
  83. */
  84. void stm32_watchdog_clear_reason(void)
  85. {
  86. WDG_RESET_STATUS = WDG_RESET_CLEAR;
  87. }
  88. /*
  89. return true if reboot was from a watchdog reset
  90. */
  91. bool stm32_was_watchdog_reset(void)
  92. {
  93. return was_watchdog_reset;
  94. }
  95. /*
  96. save persistent watchdog data
  97. */
  98. void stm32_watchdog_save(const uint32_t *data, uint32_t nwords)
  99. {
  100. set_rtc_backup(1, data, nwords);
  101. }
  102. /*
  103. load persistent watchdog data
  104. */
  105. void stm32_watchdog_load(uint32_t *data, uint32_t nwords)
  106. {
  107. get_rtc_backup(1, data, nwords);
  108. }