mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-09 13:12:37 -05:00
imx233: add hardware and software watchdog
The hardware watchdog automatically shutdown the device after 10s of inactivity, being defined as 10s without the tick IRQ fired (aka braindead device). The software IRQ mechanism is more interesting: it uses a very high priority timer setup as one-shot to trigger after 5s of inactivity (but IRQ still enabled). When detected, it patches the running code to insert a SWI instruction so that on interrupt return it will trigger a SWI and produce a meaningfull backtrace to debug the deadlock. This should allow to debug freezes in IRQ context. Change-Id: Ic55dad01201676bfb6dd79e78e535c6707cb88e6
This commit is contained in:
parent
1a06292e41
commit
6d64111b3c
4 changed files with 58 additions and 1 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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} */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ enum
|
|||
{
|
||||
TIMER_TICK, /* for tick task */
|
||||
TIMER_USER, /* for user timer */
|
||||
TIMER_WATCHDOG, /* for watchdog */
|
||||
};
|
||||
|
||||
struct imx233_timrot_info_t
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue