summaryrefslogtreecommitdiff
path: root/firmware/target
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2014-02-02 04:31:54 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2014-02-10 23:14:24 +0100
commit6d64111b3c2f772cfc3539bb13851f78d4b55870 (patch)
treef08fb564cdafb53e20b797646426d862fb115cc2 /firmware/target
parent1a06292e418ceb765121e5792b305e17d39b9618 (diff)
downloadrockbox-6d64111b3c2f772cfc3539bb13851f78d4b55870.tar.gz
rockbox-6d64111b3c2f772cfc3539bb13851f78d4b55870.zip
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
Diffstat (limited to 'firmware/target')
-rw-r--r--firmware/target/arm/imx233/icoll-imx233.c3
-rw-r--r--firmware/target/arm/imx233/system-imx233.c52
-rw-r--r--firmware/target/arm/imx233/system-target.h3
-rw-r--r--firmware/target/arm/imx233/timrot-imx233.h1
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)
146 146
147static void do_irq_stat(void) 147static void do_irq_stat(void)
148{ 148{
149 imx233_keep_alive();
149 static unsigned counter = 0; 150 static unsigned counter = 0;
150 if(counter++ >= HZ) 151 if(counter++ >= HZ)
151 { 152 {
@@ -180,6 +181,8 @@ void irq_handler(void)
180 asm volatile( 181 asm volatile(
181 "sub lr, lr, #4 \n" /* Create return address */ 182 "sub lr, lr, #4 \n" /* Create return address */
182 "stmfd sp!, { r0-r5, r12, lr } \n" /* Save what gets clobbered */ 183 "stmfd sp!, { r0-r5, r12, lr } \n" /* Save what gets clobbered */
184 "ldr r5, =0x8001c290 \n" /* Save pointer to instruction */
185 "str lr, [r5] \n" /* in HW_DIGCTL_SCRATCH0 */
183 "ldr r4, =0x80000000 \n" /* Read HW_ICOLL_VECTOR */ 186 "ldr r4, =0x80000000 \n" /* Read HW_ICOLL_VECTOR */
184 "ldr r0, [r4] \n" /* and notify as side-effect */ 187 "ldr r0, [r4] \n" /* and notify as side-effect */
185 "mrs lr, spsr \n" /* Save SPSR_irq */ 188 "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 @@
45#include "fmradio_i2c.h" 45#include "fmradio_i2c.h"
46#include "powermgmt-imx233.h" 46#include "powermgmt-imx233.h"
47 47
48#define WATCHDOG_HW_DELAY (10 * HZ)
49#define WATCHDOG_SW_DELAY (5 * HZ)
50
51static void woof_woof(void)
52{
53 /* stop hadrware watchdog, we catched the error */
54 imx233_rtc_enable_watchdog(false);
55 uint32_t pc = HW_DIGCTL_SCRATCH0;
56 /* write a "SWI #0xdead" instruction at the faulty instruction so that it
57 * will trigger a proper backtrace */
58 *(uint32_t *)pc = 0xef00dead;
59 commit_discard_idcache();
60}
61
62static void good_dog(void)
63{
64 imx233_rtc_reset_watchdog(WATCHDOG_HW_DELAY * 1000 / HZ); /* ms */
65 imx233_rtc_enable_watchdog(true);
66 imx233_timrot_setup(TIMER_WATCHDOG, false, WATCHDOG_SW_DELAY * 1000 / HZ,
67 BV_TIMROT_TIMCTRLn_SELECT__1KHZ_XTAL, BV_TIMROT_TIMCTRLn_PRESCALE__DIV_BY_1,
68 false, &woof_woof);
69 imx233_timrot_set_priority(TIMER_WATCHDOG, ICOLL_PRIO_WATCHDOG);
70}
71
72void imx233_keep_alive(void)
73{
74 /* setting up a timer is not exactly a cheap operation so only do so
75 * every second */
76 static uint32_t last_alive = 0;
77 if(imx233_us_elapsed(last_alive, 1000000))
78 {
79 good_dog();
80 last_alive = HW_DIGCTL_MICROSECONDS;
81 }
82}
83
84static void watchdog_init(void)
85{
86 /* setup two mechanisms:
87 * - hardware watchdog to reset the player after 10 seconds
88 * - software watchdog using a timer to panic after 5 seconds
89 * The hardware mechanism ensures reset when the player is completely
90 * dead and it actually resets the whole chip. On the contrary, the software
91 * mechanism allows partial recovery by panicing and printing (maybe) useful
92 * information, it uses a dedicated timer with the highest level of interrupt
93 * priority so it works even if the player is stuck in IRQ context */
94 good_dog();
95}
96
48void imx233_chip_reset(void) 97void imx233_chip_reset(void)
49{ 98{
50#if IMX233_SUBTARGET >= 3700 99#if IMX233_SUBTARGET >= 3700
@@ -60,7 +109,6 @@ void system_reboot(void)
60 109
61 disable_irq(); 110 disable_irq();
62 111
63 /* use watchdog to reset */
64 imx233_chip_reset(); 112 imx233_chip_reset();
65 while(1); 113 while(1);
66} 114}
@@ -134,6 +182,8 @@ void system_init(void)
134 imx233_power_init(); 182 imx233_power_init();
135 imx233_i2c_init(); 183 imx233_i2c_init();
136 imx233_powermgmt_init(); 184 imx233_powermgmt_init();
185 /* setup watchdog */
186 watchdog_init();
137 187
138 /* make sure auto-slow is disable now, we don't know at which frequency we 188 /* make sure auto-slow is disable now, we don't know at which frequency we
139 * are running and auto-slow could violate constraints on {xbus,hbus} */ 189 * 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);
68 68
69bool dbg_hw_target_info(void); 69bool dbg_hw_target_info(void);
70 70
71/* for watchdog */
72void imx233_keep_alive(void);
73
71#endif /* SYSTEM_TARGET_H */ 74#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
32{ 32{
33 TIMER_TICK, /* for tick task */ 33 TIMER_TICK, /* for tick task */
34 TIMER_USER, /* for user timer */ 34 TIMER_USER, /* for user timer */
35 TIMER_WATCHDOG, /* for watchdog */
35}; 36};
36 37
37struct imx233_timrot_info_t 38struct imx233_timrot_info_t