From c72c86b9b18d0ca609ede492f910bc2fc98b468c Mon Sep 17 00:00:00 2001 From: Vic Yang Date: Thu, 23 Oct 2014 15:10:15 -0700 Subject: 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 Reviewed-on: https://chromium-review.googlesource.com/225253 Reviewed-by: Vincent Palatin --- chip/stm32/hwtimer32.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) 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 */ -- cgit v1.2.1