summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVic Yang <victoryang@chromium.org>2014-10-23 15:10:15 -0700
committerchrome-internal-fetch <chrome-internal-fetch@google.com>2014-10-24 03:02:40 +0000
commitc72c86b9b18d0ca609ede492f910bc2fc98b468c (patch)
treefbae00366577126e89387c47271458ddd6f5fdb0
parent6dc5e697aab2c6613b82853eb79eca3fcbddfde5 (diff)
downloadchrome-ec-c72c86b9b18d0ca609ede492f910bc2fc98b468c.tar.gz
stm32: Add watchdog debug message for hwtimer32
This adds the option to use one 16-bit timer for watchdog helper when using 32-bit hwtimer. With this, a debug message is dumped before watchdog fires and we can easily see the task hogging the processor. BRANCH=None BUG=None TEST=On Ryu P2, 'waitms 3000' and see debug message before the EC reboots. Change-Id: I498f63a105a0ba1ab7ec7d274dc8b1f16a44140f Signed-off-by: Vic Yang <victoryang@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/225253 Reviewed-by: Vincent Palatin <vpalatin@chromium.org>
-rw-r--r--chip/stm32/hwtimer32.c77
1 files changed, 77 insertions, 0 deletions
diff --git a/chip/stm32/hwtimer32.c b/chip/stm32/hwtimer32.c
index a0829feec1..4dc4c8cdb7 100644
--- a/chip/stm32/hwtimer32.c
+++ b/chip/stm32/hwtimer32.c
@@ -136,6 +136,11 @@ static void update_prescaler(void)
* prescaler counter ticks down, or if forced via EGR).
*/
STM32_TIM_PSC(TIM_CLOCK32) = (clock_get_freq() / SECOND) - 1;
+
+#ifdef CONFIG_WATCHDOG_HELP
+ /* Watchdog timer runs at 1KHz */
+ STM32_TIM_PSC(TIM_WATCHDOG) = (clock_get_freq() / SECOND * MSEC) - 1;
+#endif /* CONFIG_WATCHDOG_HELP */
}
DECLARE_HOOK(HOOK_FREQ_CHANGE, update_prescaler, HOOK_PRIO_DEFAULT);
@@ -177,3 +182,75 @@ int __hw_clock_source_init(uint32_t start_t)
return IRQ_TIM(TIM_CLOCK32);
}
+
+#ifdef CONFIG_WATCHDOG_HELP
+
+#define IRQ_WD IRQ_TIM(TIM_WATCHDOG)
+
+void watchdog_check(uint32_t excep_lr, uint32_t excep_sp)
+{
+ /* clear status */
+ STM32_TIM_SR(TIM_WATCHDOG) = 0;
+
+ watchdog_trace(excep_lr, excep_sp);
+}
+
+void IRQ_HANDLER(IRQ_WD)(void) __attribute__((naked));
+void IRQ_HANDLER(IRQ_WD)(void)
+{
+ /* Naked call so we can extract raw LR and SP */
+ asm volatile("mov r0, lr\n"
+ "mov r1, sp\n"
+ /* Must push registers in pairs to keep 64-bit aligned
+ * stack for ARM EABI. This also conveninently saves
+ * R0=LR so we can pass it to task_resched_if_needed. */
+ "push {r0, lr}\n"
+ "bl watchdog_check\n"
+ "pop {r0, lr}\n"
+ "b task_resched_if_needed\n");
+}
+const struct irq_priority IRQ_PRIORITY(IRQ_WD)
+ __attribute__((section(".rodata.irqprio")))
+ = {IRQ_WD, 0}; /* put the watchdog at the highest
+ priority */
+
+void hwtimer_setup_watchdog(void)
+{
+ /* Enable clock */
+ __hw_timer_enable_clock(TIM_WATCHDOG, 1);
+
+ /*
+ * Timer configuration : Up counter, counter disabled, update
+ * event only on overflow.
+ */
+ STM32_TIM_CR1(TIM_WATCHDOG) = 0x0004;
+ /* No special configuration */
+ STM32_TIM_CR2(TIM_WATCHDOG) = 0x0000;
+ STM32_TIM_SMCR(TIM_WATCHDOG) = 0x0000;
+
+ /* AUto-reload value */
+ STM32_TIM_ARR(TIM_WATCHDOG) = CONFIG_AUX_TIMER_PERIOD_MS;
+
+ /* Update prescaler */
+ update_prescaler();
+
+ /* Reload the pre-scaler */
+ STM32_TIM_EGR(TIM_WATCHDOG) = 0x0001;
+
+ /* setup the overflow interrupt */
+ STM32_TIM_DIER(TIM_WATCHDOG) = 0x0001;
+ STM32_TIM_SR(TIM_WATCHDOG) = 0;
+
+ /* Start counting */
+ STM32_TIM_CR1(TIM_WATCHDOG) |= 1;
+
+ /* Enable timer interrupts */
+ task_enable_irq(IRQ_WD);
+}
+
+void hwtimer_reset_watchdog(void)
+{
+ STM32_TIM_CNT(TIM_WATCHDOG) = 0x0000;
+}
+
+#endif /* CONFIG_WATCHDOG_HELP */