From 8701086cacca088ae34580908cec45f77042b94e Mon Sep 17 00:00:00 2001 From: Min Xu Date: Sat, 25 Oct 2014 21:30:23 +0200 Subject: Retrieve + print previous PC from stack to debug wdog/spurious IRQ Retrive previous PC from the stack before entering specific interrupt handler routines. Allow user to trace where interrupt occured: e.g. WatchDog and Spurious interrupt Prior to this change, spurious interrupt would occur so much (observed via gdb/remote debug) so it appears that the board stalled. Once a custom spurious interrupt installed, the code continues after the interrupt instead of re-entering the interrupt. --- firmware/src/os/system_irq.c | 18 +++++++++++++++--- firmware/src/simtrace/main_simtrace.c | 16 ++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) (limited to 'firmware') diff --git a/firmware/src/os/system_irq.c b/firmware/src/os/system_irq.c index dc787eb..4c1da31 100644 --- a/firmware/src/os/system_irq.c +++ b/firmware/src/os/system_irq.c @@ -25,15 +25,15 @@ #include #include +#include #include "../openpcd.h" static sysirq_hdlr *sysirq_hdlrs[AT91SAM7_SYSIRQ_COUNT]; -static void sys_irq(void) +void sys_irq(u_int32_t previous_pc) { u_int32_t sr; - DEBUGP("sys_irq "); /* Somehow Atmel decided to do really stupid interrupt sharing * for commonly-used interrupts such as the timer irq */ @@ -139,6 +139,10 @@ static void sys_irq(void) if (*AT91C_WDTC_WDMR & AT91C_WDTC_WDFIEN) { sr = *AT91C_WDTC_WDSR; if (sr) { + char dbg_buf[100]; + sprintf(dbg_buf, "sys_irq [Old PC = %08X]\n\r", previous_pc); + AT91F_DBGU_Frame(dbg_buf); + DEBUGP("WDT("); if (sysirq_hdlrs[AT91SAM7_SYSIRQ_WDT]) { DEBUGP("handler "); @@ -154,6 +158,14 @@ static void sys_irq(void) DEBUGPCR("END"); } +static void sysirq_entry(void) +{ + /* DON'T MODIFY THIS SECTION AND Cstartup.S/IRQ_Handler_Entry */ + register unsigned *previous_pc asm("r0"); + asm("ADD R1, SP, #16; LDR R0, [R1]"); + sys_irq(previous_pc); +} + void sysirq_register(enum sysirqs irq, sysirq_hdlr *hdlr) { if (irq >= AT91SAM7_SYSIRQ_COUNT) @@ -167,6 +179,6 @@ void sysirq_init(void) AT91F_AIC_ConfigureIt(AT91C_BASE_AIC, AT91C_ID_SYS, OPENPCD_IRQ_PRIO_SYS, AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, - &sys_irq); + &sysirq_entry); AT91F_AIC_EnableIt(AT91C_BASE_AIC, AT91C_ID_SYS); } diff --git a/firmware/src/simtrace/main_simtrace.c b/firmware/src/simtrace/main_simtrace.c index b3f2665..b84525f 100644 --- a/firmware/src/simtrace/main_simtrace.c +++ b/firmware/src/simtrace/main_simtrace.c @@ -136,8 +136,24 @@ static int simtrace_usb_in(struct req_ctx *rctx) } } +void custom_spurious_handler(unsigned previous_pc) +{ + char dbg_buf[100]; + sprintf(dbg_buf, "SPURRIOUS IRQ [Old PC = %08X]\n\r", previous_pc); + AT91F_DBGU_Frame(dbg_buf); +} + +void custom_spurious_entry(void) +{ + register unsigned *previous_pc asm("r0"); + asm("ADD R1, SP, #16; LDR R0, [R1]"); + custom_spurious_handler(previous_pc); +} + void _init_func(void) { + AT91C_BASE_AIC->AIC_SPU = (int)custom_spurious_entry; + /* low-level hardware initialization */ pio_irq_init(); iso_uart_init(); -- cgit v1.2.3