summaryrefslogtreecommitdiff
path: root/chip/stm32/watchdog.c
diff options
context:
space:
mode:
Diffstat (limited to 'chip/stm32/watchdog.c')
-rw-r--r--chip/stm32/watchdog.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/chip/stm32/watchdog.c b/chip/stm32/watchdog.c
index 1fd84b2f43..a25e2576ca 100644
--- a/chip/stm32/watchdog.c
+++ b/chip/stm32/watchdog.c
@@ -26,11 +26,31 @@
#define IWDG_PRESCALER 6
#define IWDG_PRESCALER_DIV (1 << ((IWDG_PRESCALER) + 2))
+/*
+ * We use the WWDG as an early warning for the real watchdog, which just
+ * resets. Since it has a very short period, we need to allow several cycles
+ * of this to make up one IWDG cycle. The WWDG's early warning kicks in
+ * half way through the cycle, with a maximum time of 65.54ms at 32 MHz.
+ */
+#define WATCHDOG_CYCLES_BEFORE_RESET \
+ (WATCHDOG_PERIOD_MS / (65540 * 32000 / CPU_CLOCK))
+
+/* Keep a track of how many WWDG cycles we have had */
+static unsigned int watchdog_count;
+
+
+static void watchdog_reset_count(void)
+{
+ watchdog_count = WATCHDOG_CYCLES_BEFORE_RESET;
+}
+
void watchdog_reload(void)
{
/* Reload the watchdog */
STM32_IWDG_KR = 0xaaaa;
+
+ watchdog_reset_count();
}
@@ -44,7 +64,17 @@ void watchdog_reload(void)
*/
void watchdog_check(uint32_t excep_lr, uint32_t excep_sp)
{
- /* This is not actually called for now, since we reset instead */
+ /* Reset the windowed watchdog here */
+ STM32_WWDG_CR = 0xff;
+ STM32_WWDG_SR = 0;
+
+ /* If the count has expired, output a trace */
+ if (!--watchdog_count) {
+ /* Reset here, to give the UART enough time to send trace */
+ watchdog_reset_count();
+ watchdog_trace(excep_lr, excep_sp);
+ watchdog_reset_count();
+ }
}
@@ -86,5 +116,19 @@ int watchdog_init(void)
/* Start the watchdog (and re-lock registers) */
STM32_IWDG_KR = 0xcccc;
+ watchdog_reset_count();
+
+#ifdef CONFIG_WATCHDOG_HELP
+ /* enable clock */
+ STM32_RCC_APB1ENR |= 1 << 11;
+
+ STM32_WWDG_SR = 0;
+ STM32_WWDG_CR = 0xff;
+ STM32_WWDG_CFR = 0x7f | STM32_WWDG_TB_8 | STM32_WWDG_EWI;
+
+ /* Enable watchdog interrupt */
+ task_enable_irq(IRQ_WATCHDOG);
+#endif
+
return EC_SUCCESS;
}