diff options
-rw-r--r-- | firmware/target/arm/imx233/icoll-imx233.c | 3 | ||||
-rw-r--r-- | firmware/target/arm/imx233/system-imx233.c | 52 | ||||
-rw-r--r-- | firmware/target/arm/imx233/system-target.h | 3 | ||||
-rw-r--r-- | firmware/target/arm/imx233/timrot-imx233.h | 1 |
4 files changed, 58 insertions, 1 deletions
diff --git a/firmware/target/arm/imx233/icoll-imx233.c b/firmware/target/arm/imx233/icoll-imx233.c index e42e0f3291..e23af602db 100644 --- a/firmware/target/arm/imx233/icoll-imx233.c +++ b/firmware/target/arm/imx233/icoll-imx233.c @@ -146,6 +146,7 @@ struct imx233_icoll_irq_info_t imx233_icoll_get_irq_info(int src) static void do_irq_stat(void) { + imx233_keep_alive(); static unsigned counter = 0; if(counter++ >= HZ) { @@ -180,6 +181,8 @@ void irq_handler(void) asm volatile( "sub lr, lr, #4 \n" /* Create return address */ "stmfd sp!, { r0-r5, r12, lr } \n" /* Save what gets clobbered */ + "ldr r5, =0x8001c290 \n" /* Save pointer to instruction */ + "str lr, [r5] \n" /* in HW_DIGCTL_SCRATCH0 */ "ldr r4, =0x80000000 \n" /* Read HW_ICOLL_VECTOR */ "ldr r0, [r4] \n" /* and notify as side-effect */ "mrs lr, spsr \n" /* Save SPSR_irq */ diff --git a/firmware/target/arm/imx233/system-imx233.c b/firmware/target/arm/imx233/system-imx233.c index b25ccb5c47..5298f7cff9 100644 --- a/firmware/target/arm/imx233/system-imx233.c +++ b/firmware/target/arm/imx233/system-imx233.c @@ -45,6 +45,55 @@ #include "fmradio_i2c.h" #include "powermgmt-imx233.h" +#define WATCHDOG_HW_DELAY (10 * HZ) +#define WATCHDOG_SW_DELAY (5 * HZ) + +static void woof_woof(void) +{ + /* stop hadrware watchdog, we catched the error */ + imx233_rtc_enable_watchdog(false); + uint32_t pc = HW_DIGCTL_SCRATCH0; + /* write a "SWI #0xdead" instruction at the faulty instruction so that it + * will trigger a proper backtrace */ + *(uint32_t *)pc = 0xef00dead; + commit_discard_idcache(); +} + +static void good_dog(void) +{ + imx233_rtc_reset_watchdog(WATCHDOG_HW_DELAY * 1000 / HZ); /* ms */ + imx233_rtc_enable_watchdog(true); + imx233_timrot_setup(TIMER_WATCHDOG, false, WATCHDOG_SW_DELAY * 1000 / HZ, + BV_TIMROT_TIMCTRLn_SELECT__1KHZ_XTAL, BV_TIMROT_TIMCTRLn_PRESCALE__DIV_BY_1, + false, &woof_woof); + imx233_timrot_set_priority(TIMER_WATCHDOG, ICOLL_PRIO_WATCHDOG); +} + +void imx233_keep_alive(void) +{ + /* setting up a timer is not exactly a cheap operation so only do so + * every second */ + static uint32_t last_alive = 0; + if(imx233_us_elapsed(last_alive, 1000000)) + { + good_dog(); + last_alive = HW_DIGCTL_MICROSECONDS; + } +} + +static void watchdog_init(void) +{ + /* setup two mechanisms: + * - hardware watchdog to reset the player after 10 seconds + * - software watchdog using a timer to panic after 5 seconds + * The hardware mechanism ensures reset when the player is completely + * dead and it actually resets the whole chip. On the contrary, the software + * mechanism allows partial recovery by panicing and printing (maybe) useful + * information, it uses a dedicated timer with the highest level of interrupt + * priority so it works even if the player is stuck in IRQ context */ + good_dog(); +} + void imx233_chip_reset(void) { #if IMX233_SUBTARGET >= 3700 @@ -60,7 +109,6 @@ void system_reboot(void) disable_irq(); - /* use watchdog to reset */ imx233_chip_reset(); while(1); } @@ -134,6 +182,8 @@ void system_init(void) imx233_power_init(); imx233_i2c_init(); imx233_powermgmt_init(); + /* setup watchdog */ + watchdog_init(); /* make sure auto-slow is disable now, we don't know at which frequency we * are running and auto-slow could violate constraints on {xbus,hbus} */ diff --git a/firmware/target/arm/imx233/system-target.h b/firmware/target/arm/imx233/system-target.h index 33e8f12265..6272cf7a85 100644 --- a/firmware/target/arm/imx233/system-target.h +++ b/firmware/target/arm/imx233/system-target.h @@ -68,4 +68,7 @@ void usb_remove_int(void); bool dbg_hw_target_info(void); +/* for watchdog */ +void imx233_keep_alive(void); + #endif /* SYSTEM_TARGET_H */ diff --git a/firmware/target/arm/imx233/timrot-imx233.h b/firmware/target/arm/imx233/timrot-imx233.h index f1a7780f34..e33de39390 100644 --- a/firmware/target/arm/imx233/timrot-imx233.h +++ b/firmware/target/arm/imx233/timrot-imx233.h @@ -32,6 +32,7 @@ enum { TIMER_TICK, /* for tick task */ TIMER_USER, /* for user timer */ + TIMER_WATCHDOG, /* for watchdog */ }; struct imx233_timrot_info_t |