diff options
author | David Sidrane <david_s5@nscdg.com> | 2015-03-04 17:02:32 -1000 |
---|---|---|
committer | David Sidrane <david_s5@nscdg.com> | 2015-03-05 08:33:56 -1000 |
commit | 1694c8faccfb83875a9ec5b98e131e970c16865e (patch) | |
tree | 423d90d4e931dea493aa7dad38ec8957711bbfce | |
parent | baf9bd0346d7ee8dd236dc0ce0214a7c5543544a (diff) | |
download | px4-firmware-1694c8faccfb83875a9ec5b98e131e970c16865e.tar.gz px4-firmware-1694c8faccfb83875a9ec5b98e131e970c16865e.tar.bz2 px4-firmware-1694c8faccfb83875a9ec5b98e131e970c16865e.zip |
Reduced memory footprint with serialization and malloc
-rw-r--r-- | src/drivers/boards/px4fmu-v2/px4fmu2_init.c | 102 | ||||
-rw-r--r-- | src/modules/systemlib/hardfault_log.h | 82 | ||||
-rw-r--r-- | src/systemcmds/hardfault_log/hardfault_log.c | 519 |
3 files changed, 417 insertions, 286 deletions
diff --git a/src/drivers/boards/px4fmu-v2/px4fmu2_init.c b/src/drivers/boards/px4fmu-v2/px4fmu2_init.c index 98babbf05..52ee00a7d 100644 --- a/src/drivers/boards/px4fmu-v2/px4fmu2_init.c +++ b/src/drivers/boards/px4fmu-v2/px4fmu2_init.c @@ -311,7 +311,8 @@ __EXPORT int nsh_archinitialize(void) if (hadCrash == OK) { - syslog(LOG_INFO, "[boot] There was a hard fault hit the SPACE BAR to halt the system!\n"); + syslog(LOG_INFO, "[boot] There is a hard fault logged. Hold down the SPACE BAR," \ + " while booting to halt the system!\n"); /* Yes. So add one to the boot count - this will be reset after a successful * commit to SD @@ -326,13 +327,13 @@ __EXPORT int nsh_archinitialize(void) if (reboots > 2 || bytesWaiting != 0 ) { - /* Since we can not commit the fault dump to disk. display it + /* Since we can not commit the fault dump to disk. Display it * to the console. */ hardfault_write("boot", fileno(stdout), HARDFAULT_DISPLAY_FORMAT, false); - syslog(LOG_INFO, "[boot] There were %d uncommitted Hard faults System halted%s\n", + syslog(LOG_INFO, "[boot] There were %d reboots with Hard fault that were not committed to disk - System halted %s\n", reboots, (bytesWaiting==0 ? "" : " Due to Key Press\n")); @@ -344,7 +345,8 @@ __EXPORT int nsh_archinitialize(void) /* Clear any key press that got us here */ static volatile bool dbgContinue = false; - for (int c ='>'; !dbgContinue; c= getchar()) { + int c = '>'; + while (!dbgContinue) { switch(c) { @@ -387,6 +389,9 @@ __EXPORT int nsh_archinitialize(void) "Enter C - Clear the fault log\n" \ "Enter D - Dump fault log\n\n?>"); fflush(stdout); + if (!dbgContinue) { + c = getchar(); + } break; } // outer switch @@ -484,6 +489,13 @@ __EXPORT int nsh_archinitialize(void) return OK; } +inline static void copy_reverse(stack_word_t *dest, stack_word_t *src, int size) +{ + while (size--) { + *dest++ = *src--; + } +} + __EXPORT void board_crashdump(uint32_t currentsp, void *tcb, uint8_t *filename, int lineno) { /* We need a chunk of ram to save the complete contest in. @@ -498,7 +510,7 @@ __EXPORT void board_crashdump(uint32_t currentsp, void *tcb, uint8_t *filename, /* Zero out everything */ - memset(pdump,0,sizeof(fullcontext_s)); + memset(pdump, 0, sizeof(fullcontext_s)); /* Save Info */ @@ -524,56 +536,63 @@ __EXPORT void board_crashdump(uint32_t currentsp, void *tcb, uint8_t *filename, /* Save Context */ - /* If not NULL then we are in an interrupt context and the user context - * is in current_regs else we are running in the users context - */ #if CONFIG_TASK_NAME_SIZE > 0 - strncpy(pdump->context.proc.name, rtcb->name, CONFIG_TASK_NAME_SIZE); + strncpy(pdump->info.name, rtcb->name, CONFIG_TASK_NAME_SIZE); #endif - pdump->context.proc.pid = rtcb->pid; + pdump->info.pid = rtcb->pid; - pdump->context.stack.current_sp = currentsp; + + /* If current_regs is not NULL then we are in an interrupt context + * and the user context is in current_regs else we are running in + * the users context + */ if (current_regs) { - pdump->info.stuff |= eRegs; - memcpy(&pdump->context.proc.xcp.regs, (void*)current_regs, sizeof(pdump->context.proc.xcp.regs)); - currentsp = pdump->context.proc.xcp.regs[REG_R13]; - } + pdump->info.stacks.interrupt.sp = currentsp; + pdump->info.flags |= eRegs; + memcpy(pdump->info.regs, (void*)current_regs, sizeof(pdump->info.regs)); + pdump->info.stacks.user.sp = pdump->info.regs[REG_R13]; + currentsp = pdump->info.stacks.user.sp; + } else { - pdump->context.stack.itopofstack = (uint32_t) &g_intstackbase;; - pdump->context.stack.istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3); + /* users context */ + + pdump->info.stacks.user.sp = currentsp; + } - if (pdump->context.proc.pid == 0) { + if (pdump->info.pid == 0) { - pdump->context.stack.utopofstack = g_idle_topstack - 4; - pdump->context.stack.ustacksize = CONFIG_IDLETHREAD_STACKSIZE; + pdump->info.stacks.user.top = g_idle_topstack - 4; + pdump->info.stacks.user.size = CONFIG_IDLETHREAD_STACKSIZE; } else { - pdump->context.stack.utopofstack = (uint32_t) rtcb->adj_stack_ptr; - pdump->context.stack.ustacksize = (uint32_t) rtcb->adj_stack_size;; + pdump->info.stacks.user.top = (uint32_t) rtcb->adj_stack_ptr; + pdump->info.stacks.user.size = (uint32_t) rtcb->adj_stack_size;; } #if CONFIG_ARCH_INTERRUPTSTACK > 3 /* Get the limits on the interrupt stack memory */ - pdump->context.stack.itopofstack = (uint32_t)&g_intstackbase; - pdump->context.stack.istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3); + pdump->info.stacks.interrupt.top = (uint32_t)&g_intstackbase; + pdump->info.stacks.interrupt.size = (CONFIG_ARCH_INTERRUPTSTACK & ~3); /* If the current stack pointer is within the interrupt stack then * save the interrupt stack data centered about the interrupt stack pointer */ - if (pdump->context.stack.current_sp <= pdump->context.stack.itopofstack && - pdump->context.stack.current_sp > pdump->context.stack.itopofstack - pdump->context.stack.istacksize) + if (pdump->info.stacks.interrupt.sp <= pdump->info.stacks.interrupt.top && + pdump->info.stacks.interrupt.sp > pdump->info.stacks.interrupt.top - pdump->info.stacks.interrupt.size) { - pdump->info.stuff |= eIntStack; - memcpy(&pdump->istack, (void *)(pdump->context.stack.current_sp-sizeof(pdump->istack)/2), - sizeof(pdump->istack)); + pdump->info.flags |= eIntStack; + stack_word_t * ps = (stack_word_t *) pdump->info.stacks.interrupt.sp; + copy_reverse(pdump->istack, &ps[arraySize(pdump->istack)/2], arraySize(pdump->istack)); + } else { + pdump->info.flags |= eInvalidIntStack; } #endif @@ -581,30 +600,33 @@ __EXPORT void board_crashdump(uint32_t currentsp, void *tcb, uint8_t *filename, /* If the saved context of the interrupted process's stack pointer lies within the * allocated user stack memory then save the user stack centered about the user sp */ - if (currentsp <= pdump->context.stack.utopofstack && - currentsp > pdump->context.stack.utopofstack - pdump->context.stack.ustacksize) + if (currentsp <= pdump->info.stacks.user.top && + currentsp > pdump->info.stacks.user.top - pdump->info.stacks.user.size) { - pdump->info.stuff |= eUserStack; - memcpy(&pdump->ustack, (void *)(currentsp-sizeof(pdump->ustack)/2), sizeof(pdump->ustack)); + pdump->info.flags |= eUserStack; + stack_word_t * ps = (stack_word_t *) pdump->info.stacks.user.sp; + copy_reverse(pdump->ustack, &ps[arraySize(pdump->ustack)/2], arraySize(pdump->ustack)); + } else { + pdump->info.flags |= eInvalidUserStack; } /* Oh boy we have a real hot mess on our hands so save above and below the * current sp */ - if ((pdump->info.stuff & eStackValid) == 0) + if ((pdump->info.flags & eStackValid) == 0) { - pdump->info.stuff |= eStackUnknown; + pdump->info.flags |= (eStackUnknown | eStackValid); #if CONFIG_ARCH_INTERRUPTSTACK > 3 /* sp and above in istack */ - memcpy(&pdump->istack, (void *)pdump->context.stack.current_sp, sizeof(pdump->istack)); + stack_word_t * ps = (stack_word_t *) pdump->info.stacks.interrupt.sp; + copy_reverse(pdump->istack, &ps[arraySize(pdump->istack)], arraySize(pdump->istack)); /* below in ustack */ - memcpy(&pdump->ustack, (void *)(pdump->context.stack.current_sp-sizeof(pdump->ustack)), - sizeof(pdump->ustack)); + ps = (stack_word_t *) pdump->info.stacks.user.sp; + copy_reverse(pdump->ustack, &ps[arraySize(pdump->ustack)], arraySize(pdump->ustack)); #else /* save above and below in ustack */ - memcpy(&pdump->ustack, (void *)(pdump->context.stack.current_sp-sizeof(pdump->ustack)/2), - sizeof(pdump->ustack)/2); + copy_reverse(pdump->ustack, &ps[arraySize(pdump->ustack)/2], arraySize(pdump->ustack)); #endif } diff --git a/src/modules/systemlib/hardfault_log.h b/src/modules/systemlib/hardfault_log.h index 2161103a1..6983a5737 100644 --- a/src/modules/systemlib/hardfault_log.h +++ b/src/modules/systemlib/hardfault_log.h @@ -67,7 +67,7 @@ #else # define BBSRAM_NUMBER_STACKS 2 #endif -#define BBSRAM_FIXED_ELEMENTS_SIZE (sizeof(context_s)+sizeof(info_s)) +#define BBSRAM_FIXED_ELEMENTS_SIZE (sizeof(info_s)) #define BBSRAM_LEFTOVER (BBSRAM_REAMINING-BBSRAM_FIXED_ELEMENTS_SIZE) #define CONFIG_ISTACK_SIZE (BBSRAM_LEFTOVER/BBSRAM_NUMBER_STACKS/sizeof(stack_word_t)) @@ -123,7 +123,7 @@ #if defined(__cplusplus) #define EXTERN extern "C" extern "C" -{ +//{ #else #define EXTERN extern #endif @@ -131,36 +131,19 @@ extern "C" /* Used for stack frame storage */ typedef uint32_t stack_word_t; -typedef struct { - int pid; /* Process ID */ - struct xcptcontext xcp; /* Interrupt register save area */ -#if CONFIG_TASK_NAME_SIZE > 0 - char name[CONFIG_TASK_NAME_SIZE+1]; /* Task name (with NULL terminator) */ -#endif -} process_t; - /* Stack related data */ + typedef struct { - uint32_t current_sp; /* The stack the up_assert is running on - * it may be either the user stack for an assertion - * failure or the interrupt stack in the case of a - * hard fault - */ - uint32_t utopofstack; /* Top of the user stack at the time of the - * up_assert - */ - uint32_t ustacksize; /* Size of the user stack at the time of the - * up_assert - */ + uint32_t sp; + uint32_t top; + uint32_t size; -#if CONFIG_ARCH_INTERRUPTSTACK > 3 +} _stack_s; - uint32_t itopofstack; /* Top of the interrupt stack at the time of the - * up_assert - */ - uint32_t istacksize; /* Size of the interrupt stack at the time of the - * up_assert - */ +typedef struct { + _stack_s user; +#if CONFIG_ARCH_INTERRUPTSTACK > 3 + _stack_s interrupt; #endif } stack_t; @@ -249,30 +232,33 @@ typedef struct /* Flags to identify what is in the dump */ typedef enum { - eRegs = 0x01, - eUserStack = 0x02, - eIntStack = 0x04, - eStackUnknown = 0x08, - eStackValid = eUserStack | eIntStack, -} stuff_t; + eRegs = 0x01, + eUserStack = 0x02, + eIntStack = 0x04, + eStackValid = eUserStack | eIntStack, + eStackUnknown = 0x08, + eInvalidUserStack = 0x20, + eInvalidIntStack = 0x40, +} fault_flags_t; typedef struct { - stuff_t stuff; /* What is in the dump */ - uintptr_t current_regs; /* Used to validate the dump */ - int lineno; /* __LINE__ to up_assert */ - char filename[MAX_FILE_PATH_LENGTH]; /* Last MAX_FILE_PATH_LENGTH of chars in - * __FILE__ to up_assert - */ + fault_flags_t flags; /* What is in the dump */ + uintptr_t current_regs; /* Used to validate the dump */ + int lineno; /* __LINE__ to up_assert */ + int pid; /* Process ID */ + uint32_t regs[XCPTCONTEXT_REGS]; /* Interrupt register save + * area */ + stack_t stacks; /* Stack info */ +#if CONFIG_TASK_NAME_SIZE > 0 + char name[CONFIG_TASK_NAME_SIZE+1]; /* Task name (with NULL + * terminator) */ +#endif + char filename[MAX_FILE_PATH_LENGTH]; /* the Last of chars in + * __FILE__ to up_assert */ } info_s; -typedef struct { /* The Context data */ - stack_t stack; - process_t proc; -} context_s; - typedef struct { - info_s info; /* Then info */ - context_s context; /* The Context data */ + info_s info; /* The info */ #if CONFIG_ARCH_INTERRUPTSTACK > 3 /* The amount of stack data is compile time * sized backed on what is left after the * other BBSRAM files are defined @@ -378,6 +364,6 @@ int hardfault_increment_reboot(char *caller, bool reset); #if defined(__cplusplus) extern "C" -} +//} #endif diff --git a/src/systemcmds/hardfault_log/hardfault_log.c b/src/systemcmds/hardfault_log/hardfault_log.c index e8f37335b..959ea4a3a 100644 --- a/src/systemcmds/hardfault_log/hardfault_log.c +++ b/src/systemcmds/hardfault_log/hardfault_log.c @@ -38,11 +38,13 @@ #include <nuttx/config.h> #include <nuttx/compiler.h> +#include <nuttx/arch.h> #include <sys/ioctl.h> #include <stdio.h> #include <stdint.h> +#include <stddef.h> #include <stdlib.h> #include <fcntl.h> #include <string.h> @@ -65,7 +67,7 @@ __EXPORT int hardfault_log_main(int argc, char *argv[]); /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ - +#define OUT_BUFFER_LEN 200 /**************************************************************************** * Private Types ****************************************************************************/ @@ -119,26 +121,6 @@ static int genfault(int fault) /* This is not going to happen */ break; - case 2: - printf("null %s\n",NULL); - /* This is not going to happen */ - break; - - case 3: - { - char marker[20]; - strncpy(marker, "<-- ", sizeof(marker)); - printf("nill %s\n",""); - printf("nill fault==3 %s\n",(fault==3) ? "3" : ""); - printf("nill fault!=3 %s\n",(fault!=3) ? "3" : ""); - printf("0x%08x 0x%08x%s\n", fault, -fault, (fault==3) ? "" : marker); - printf("0x%08x 0x%08x%s\n", fault, -fault, (fault!=3) ? "" : marker); - printf("0x%08x 0x%08x%s\n", fault, -fault, fault==3 ? "" : marker); - printf("0x%08x 0x%08x%s\n", fault, -fault, fault!=3 ? "" : marker); - } - /* This is not going to happen */ - break; - default: break; @@ -237,106 +219,154 @@ static int hardfault_get_desc(char *caller, struct bbsramd_s *desc, bool silent) /**************************************************************************** * write_stack_detail ****************************************************************************/ -static void write_stack_detail(int size, uint32_t topaddr, uint32_t spaddr, - uint32_t botaddr, char *sp_name, char *buffer, int max, int fd) +static int write_stack_detail(bool inValid, _stack_s *si, char *sp_name, + char *buffer, int max, int fd) { int n = 0; - n = snprintf(&buffer[n], max-n, " %s stack:\n",sp_name); - n += snprintf(&buffer[n], max-n, " top: 0x%08x\n", topaddr); - n += snprintf(&buffer[n], max-n, " sp: 0x%08x\n", spaddr); - write(fd, buffer,n); + uint32_t sbot = si->top - si->size; + n = snprintf(&buffer[n], max-n, " %s stack: \n",sp_name); + n += snprintf(&buffer[n], max-n, " top: 0x%08x\n", si->top); + n += snprintf(&buffer[n], max-n, " sp: 0x%08x %s\n", si->sp, (inValid ? "Invalid" : "Valid")); + if (n != write(fd, buffer, n)) { + return -EIO; + } n = 0; - n += snprintf(&buffer[n], max-n, " bottom: 0x%08x\n", botaddr); - n += snprintf(&buffer[n], max-n, " size: 0x%08x\n", size); - write(fd, buffer,n); -#ifndef CONFIG_STACK_COLORATION + n += snprintf(&buffer[n], max-n, " bottom: 0x%08x\n", sbot); + n += snprintf(&buffer[n], max-n, " size: 0x%08x\n", si->size); + if (n != write(fd, buffer, n)) { + return -EIO; + } +#ifdef CONFIG_STACK_COLORATION FAR struct tcb_s tcb; - tcb.stack_alloc_ptr = (void*) botaddr; - tcb.adj_stack_size = size; + tcb.stack_alloc_ptr = (void*) sbot; + tcb.adj_stack_size = si->size; n = snprintf(buffer, max, " used: %08x\n", up_check_tcbstack(&tcb)); - write(fd, buffer,n); + if (n != write(fd, buffer, n)) { + return -EIO; + } #endif + return OK; } /**************************************************************************** * write_stack ****************************************************************************/ -static void write_stack(stack_word_t *swindow, int winsize, uint32_t wtopaddr, +static int read_stack(int fd, stack_word_t *words, int num) +{ + int bytes = read(fd, (char *) words, sizeof(stack_word_t) * num); + if (bytes > 0) { + bytes /= sizeof(stack_word_t); + } + return bytes; +} +static int write_stack(bool inValid, int winsize, uint32_t wtopaddr, uint32_t topaddr, uint32_t spaddr, uint32_t botaddr, - char *sp_name, char *buffer, int max, int fd) + char *sp_name, char *buffer, int max, int infd, int outfd) { - char marker[30]; - for (int i = winsize; i >= 0; i--) { - if (wtopaddr == topaddr) { - strncpy(marker, "<-- ", sizeof(marker)); - strncat(marker, sp_name, sizeof(marker)); - strncat(marker, " top", sizeof(marker)); - } else if (wtopaddr == spaddr) { - strncpy(marker, "<-- ", sizeof(marker)); - strncat(marker, sp_name, sizeof(marker)); - } else if (wtopaddr == botaddr) { - strncpy(marker, "<-- ", sizeof(marker)); - strncat(marker, sp_name, sizeof(marker)); - strncat(marker, " bottom", sizeof(marker)); - } else { - marker[0] = '\0'; - } - int n = snprintf(buffer, max,"0x%08x 0x%08x%s\n", wtopaddr, swindow[i], marker); - write(fd, buffer,n); - wtopaddr--; - } + char marker[30]; + stack_word_t stack[32]; + int ret = OK; + + int n = snprintf(buffer, max,"%s memory region, stack pointer lies %s stack\n", + sp_name, (inValid ? "outside of" : "within" )); + if (n != write(outfd, buffer, n)) { + + ret = -EIO; + + } else { + + while(winsize > 0 && ret == OK) { + int chunk = read_stack(infd, stack, arraySize(stack)); + if (chunk <= 0 ) { + ret = -EIO; + } else { + winsize -= chunk; + for (int i = 0; i < chunk; i++) { + if (wtopaddr == topaddr) { + strncpy(marker, "<-- ", sizeof(marker)); + strncat(marker, sp_name, sizeof(marker)); + strncat(marker, " top", sizeof(marker)); + } else if (wtopaddr == spaddr) { + strncpy(marker, "<-- ", sizeof(marker)); + strncat(marker, sp_name, sizeof(marker)); + } else if (wtopaddr == botaddr) { + strncpy(marker, "<-- ", sizeof(marker)); + strncat(marker, sp_name, sizeof(marker)); + strncat(marker, " bottom", sizeof(marker)); + } else { + marker[0] = '\0'; + } + n = snprintf(buffer, max,"0x%08x 0x%08x%s\n", wtopaddr, stack[i], marker); + if (n != write(outfd, buffer, n)) { + ret = -EIO; + } + wtopaddr--; + } + } + } + } + return ret; } /**************************************************************************** * write_registers ****************************************************************************/ -static void write_registers(fullcontext_s* fc, char *buffer, int max, int fd) +static int write_registers(uint32_t regs[], char *buffer, int max, int fd) { int n = snprintf(buffer, max, " r0:0x%08x r1:0x%08x r2:0x%08x r3:0x%08x r4:0x%08x r5:0x%08x r6:0x%08x r7:0x%08x\n", - fc->context.proc.xcp.regs[REG_R0], fc->context.proc.xcp.regs[REG_R1], - fc->context.proc.xcp.regs[REG_R2], fc->context.proc.xcp.regs[REG_R3], - fc->context.proc.xcp.regs[REG_R4], fc->context.proc.xcp.regs[REG_R5], - fc->context.proc.xcp.regs[REG_R6], fc->context.proc.xcp.regs[REG_R7]); + regs[REG_R0], regs[REG_R1], + regs[REG_R2], regs[REG_R3], + regs[REG_R4], regs[REG_R5], + regs[REG_R6], regs[REG_R7]); - write(fd, buffer,n); + if (n != write(fd, buffer, n)) { + return -EIO; + } n = snprintf(buffer, max, " r8:0x%08x r9:0x%08x r10:0x%08x r11:0x%08x r12:0x%08x sp:0x%08x lr:0x%08x pc:0x%08x\n", - fc->context.proc.xcp.regs[REG_R8], fc->context.proc.xcp.regs[REG_R9], - fc->context.proc.xcp.regs[REG_R10], fc->context.proc.xcp.regs[REG_R11], - fc->context.proc.xcp.regs[REG_R12], fc->context.proc.xcp.regs[REG_R13], - fc->context.proc.xcp.regs[REG_R14], fc->context.proc.xcp.regs[REG_R15]); + regs[REG_R8], regs[REG_R9], + regs[REG_R10], regs[REG_R11], + regs[REG_R12], regs[REG_R13], + regs[REG_R14], regs[REG_R15]); - write(fd, buffer,n); + if (n != write(fd, buffer, n)) { + return -EIO; + } #ifdef CONFIG_ARMV7M_USEBASEPRI n = snprintf(buffer, max, " xpsr:0x%08x basepri:0x%08x control:0x%08x\n", - fc->context.proc.xcp.regs[REG_XPSR], fc->context.proc.xcp.regs[REG_BASEPRI], + regs[REG_XPSR], regs[REG_BASEPRI], getcontrol()); #else n = snprintf(buffer, max, " xpsr:0x%08x primask:0x%08x control:0x%08x\n", - fc->context.proc.xcp.regs[REG_XPSR], fc->context.proc.xcp.regs[REG_PRIMASK], + regs[REG_XPSR], regs[REG_PRIMASK], getcontrol()); #endif - write(fd, buffer,n); + if (n != write(fd, buffer, n)) { + return -EIO; + } #ifdef REG_EXC_RETURN - n = snprintf(buffer, max, " exe return:0x%08x\n", fc->context.proc.xcp.regs[REG_EXC_RETURN]); - write(fd, buffer,n); + n = snprintf(buffer, max, " exe return:0x%08x\n", regs[REG_EXC_RETURN]); + if (n != write(fd, buffer, n)) { + return -EIO; + } #endif + return OK; } /**************************************************************************** * write_registers_info ****************************************************************************/ -static int write_registers_info(int fdout, fullcontext_s *fc, char *buffer, - int sz) +static int write_registers_info(int fdout, info_s *pi , char *buffer, int sz) { int ret = -ENOENT; - if (fc->info.stuff & eRegs) { - int n = snprintf(buffer, sz, " Processor registers: from 0x%08x\n", fc->info.current_regs); - write(fdout, buffer,n); - write_registers(fc, buffer, sz, fdout); - ret = OK; + if (pi->flags & eRegs) { + ret = -EIO; + int n = snprintf(buffer, sz, " Processor registers: from 0x%08x\n", pi->current_regs); + if (n == write(fdout, buffer, n)) { + ret = write_registers(pi->regs, buffer, sz, fdout); + } } return ret; } @@ -344,18 +374,14 @@ static int write_registers_info(int fdout, fullcontext_s *fc, char *buffer, /**************************************************************************** * write_interrupt_stack_info ****************************************************************************/ -static int write_interrupt_stack_info(int fdout, fullcontext_s *fc, char *buffer, - unsigned int sz) +static int write_interrupt_stack_info(int fdout, info_s *pi, char *buffer, + unsigned int sz) { int ret = -ENOENT; - if (fc->info.stuff & eIntStack) { - write_stack_detail(fc->context.stack.istacksize, - fc->context.stack.itopofstack, - fc->context.stack.current_sp, - fc->context.stack.itopofstack - fc->context.stack.istacksize, - "IRQ", - buffer, sz, fdout); - ret = OK; + if (pi->flags & eIntStack) { + ret = write_stack_detail((pi->flags & eInvalidIntStack) != 0, + &pi->stacks.interrupt, "IRQ", + buffer, sz, fdout); } return ret; } @@ -363,18 +389,13 @@ static int write_interrupt_stack_info(int fdout, fullcontext_s *fc, char *buffer /**************************************************************************** * write_user_stack_info ****************************************************************************/ -static int write_user_stack_info(int fdout, fullcontext_s *fc, char *buffer, - unsigned int sz) +static int write_user_stack_info(int fdout, info_s *pi, char *buffer, + unsigned int sz) { int ret = -ENOENT; - if (fc->info.stuff & eUserStack) { - write_stack_detail(fc->context.stack.ustacksize, - fc->context.stack.utopofstack, - fc->context.proc.xcp.regs[REG_R13], - fc->context.stack.utopofstack - fc->context.stack.ustacksize, - "User", - buffer, sz, fdout); - ret = OK; + if (pi->flags & eUserStack) { + ret = write_stack_detail((pi->flags & eInvalidUserStack) != 0, + &pi->stacks.user, "User", buffer, sz, fdout); } return ret; } @@ -382,81 +403,97 @@ static int write_user_stack_info(int fdout, fullcontext_s *fc, char *buffer, /**************************************************************************** * write_dump_info ****************************************************************************/ -static void write_dump_info(int fdout, fullcontext_s *fc, struct timespec *ts, +static int write_dump_info(int fdout, info_s *info, struct bbsramd_s * desc, char *buffer, unsigned int sz) { char fmtbuff[ TIME_FMT_LEN + 1]; - format_fault_time(HEADER_TIME_FMT, ts, fmtbuff, sizeof(fmtbuff)); + format_fault_time(HEADER_TIME_FMT, &desc->lastwrite, fmtbuff, sizeof(fmtbuff)); - bool isFault = (fc->info.current_regs != 0 || fc->context.proc.pid == 0); + bool isFault = (info->current_regs != 0 || info->pid == 0); int n; n = snprintf(buffer, sz, "System fault Occurred on: %s\n", fmtbuff); - write(fdout, buffer, n); + + if (n != write(fdout, buffer, n)) { + return -EIO; + } + if (isFault) { n = snprintf(buffer, sz, " Type:Hard Fault"); } else { n = snprintf(buffer, sz, " Type:Assertion failed"); } - write(fdout, buffer, n); + if (n != write(fdout, buffer, n)) { + return -EIO; + } #ifdef CONFIG_TASK_NAME_SIZE n = snprintf(buffer, sz, " in file:%s at line: %d running task: %s\n", - fc->info.filename, fc->info.lineno, fc->context.proc.name); + info->filename, info->lineno, info->name); #else n = snprintf(buffer, sz, " in file:%s at line: %d \n", - fc->info.filename, fc->info.lineno); + info->filename, info->lineno); #endif - write(fdout, buffer, n); + if (n != write(fdout, buffer, n)) { + return -EIO; + } n = snprintf(buffer, sz, " FW git-hash: %s\n", FW_GIT); - write(fdout, buffer, n); + if (n != write(fdout, buffer, n)) { + return -EIO; + } n = snprintf(buffer, sz, " Build datetime: %s %s\n", __DATE__, __TIME__); - write(fdout, buffer, n); - + if (n != write(fdout, buffer, n)) { + return -EIO; + } + return OK; } /**************************************************************************** * write_dump_time ****************************************************************************/ -static void write_dump_time(char *caller, char *tag, int fdout, +static int write_dump_time(char *caller, char *tag, int fdout, struct timespec *ts, char *buffer, unsigned int sz) { + int ret = OK; char fmtbuff[ TIME_FMT_LEN + 1]; format_fault_time(HEADER_TIME_FMT, ts, fmtbuff, sizeof(fmtbuff)); int n = snprintf(buffer, sz, "[%s] -- %s %s Fault Log --\n",caller, fmtbuff, tag); - write(fdout, buffer, n); + if (n != write(fdout, buffer, n)) { + ret = -EIO; + } + return ret; } /**************************************************************************** * write_dump_footer ****************************************************************************/ -static void write_dump_header(char * caller, int fdout, struct timespec *ts, +static int write_dump_header(char * caller, int fdout, struct timespec *ts, char *buffer, unsigned int sz) { - write_dump_time(caller, "Begin", fdout, ts, buffer, sz); + return write_dump_time(caller, "Begin", fdout, ts, buffer, sz); } /**************************************************************************** * write_dump_footer ****************************************************************************/ -static void write_dump_footer(char * caller, int fdout, struct timespec *ts, - char *buffer, unsigned int sz) +static int write_dump_footer(char * caller, int fdout, struct timespec *ts, + char *buffer, unsigned int sz) { - write_dump_time(caller, "END", fdout, ts, buffer, sz); + return write_dump_time(caller, "END", fdout, ts, buffer, sz); } /**************************************************************************** * write_intterupt_satck ****************************************************************************/ -static int write_intterupt_stack(int fdout, fullcontext_s *fc, char *buffer, +static int write_intterupt_stack(int fdin, int fdout, info_s *pi, char *buffer, unsigned int sz) { int ret = -ENOENT; - if ((fc->info.stuff & eIntStack) != 0) { - int winsize = arraySize(fc->istack); - int wtopaddr = fc->context.stack.current_sp + winsize/2; - write_stack(fc->istack, winsize, wtopaddr, - fc->context.stack.itopofstack, - fc->context.stack.current_sp, - fc->context.stack.itopofstack - fc->context.stack.istacksize, - "Interrupt sp", buffer, sz, fdout); - ret = OK; + if ((pi->flags & eIntStack) != 0) { + lseek(fdin, offsetof(fullcontext_s, istack), SEEK_SET); + ret = write_stack((pi->flags & eInvalidIntStack) != 0, + CONFIG_ISTACK_SIZE, + pi->stacks.interrupt.sp + CONFIG_ISTACK_SIZE/2, + pi->stacks.interrupt.top, + pi->stacks.interrupt.sp, + pi->stacks.interrupt.top - pi->stacks.interrupt.size, + "Interrupt sp", buffer, sz, fdin, fdout); } return ret; @@ -466,19 +503,19 @@ static int write_intterupt_stack(int fdout, fullcontext_s *fc, char *buffer, /**************************************************************************** * write_user_stack ****************************************************************************/ -static int write_user_stack(int fdout, fullcontext_s *fc, char *buffer, +static int write_user_stack(int fdin, int fdout, info_s *pi, char *buffer, unsigned int sz) { int ret = -ENOENT; - if ((fc->info.stuff & eUserStack) != 0) { - int winsize = arraySize(fc->ustack); - int wtopaddr = fc->context.proc.xcp.regs[REG_R13] + winsize/2; - write_stack(fc->ustack, winsize, wtopaddr, - fc->context.stack.utopofstack, - fc->context.proc.xcp.regs[REG_R13], - fc->context.stack.utopofstack - fc->context.stack.ustacksize, - "User sp", buffer, sz, fdout); - ret = OK; + if ((pi->flags & eUserStack) != 0) { + lseek(fdin,offsetof(fullcontext_s, ustack), SEEK_SET); + ret = write_stack((pi->flags & eInvalidUserStack) != 0, + CONFIG_USTACK_SIZE, + pi->stacks.user.sp + CONFIG_USTACK_SIZE/2, + pi->stacks.user.top, + pi->stacks.user.sp, + pi->stacks.user.top - pi->stacks.user.size, + "User sp", buffer, sz, fdin, fdout); } return ret; @@ -494,7 +531,9 @@ static int hardfault_commit(char *caller) struct bbsramd_s desc; char path[LOG_PATH_LEN+1]; ret = hardfault_get_desc(caller, &desc, false); + if (ret >= 0) { + int fd = ret; state = (desc.lastwrite.tv_sec || desc.lastwrite.tv_nsec) ? OK : 1; int rv = close(fd); @@ -502,30 +541,109 @@ static int hardfault_commit(char *caller) identify(caller); syslog(LOG_INFO, "Failed to Close Fault Log (%d)\n",rv); } else { + if (state != OK) { identify(caller); syslog(LOG_INFO, "Nothing to save\n",path); ret = -ENOENT; } else { - ret = format_fault_file_name(&desc.lastwrite, path, arraySize(path)); - if (ret == OK) { - int fdout = open(path, O_RDWR | O_CREAT); - if (fdout > 0) { - identify(caller); - syslog(LOG_INFO, "Saving Fault Log file %s\n",path); - ret = hardfault_write(caller, fdout, HARDFAULT_FILE_FORMAT, true); - identify(caller); - syslog(LOG_INFO, "Done saving Fault Log file\n"); - close(fdout); - } - - } + ret = format_fault_file_name(&desc.lastwrite, path, arraySize(path)); + if (ret == OK) { + int fdout = open(path, O_RDWR | O_CREAT); + if (fdout > 0) { + identify(caller); + syslog(LOG_INFO, "Saving Fault Log file %s\n",path); + ret = hardfault_write(caller, fdout, HARDFAULT_FILE_FORMAT, true); + identify(caller); + syslog(LOG_INFO, "Done saving Fault Log file\n"); + close(fdout); + } + } } } } return ret; } + +/**************************************************************************** + * hardfault_dowrite + ****************************************************************************/ +static int hardfault_dowrite(char * caller, int infd, int outfd, + struct bbsramd_s *desc, int format) +{ + int ret = -ENOMEM; + char *line = zalloc(OUT_BUFFER_LEN); + if (line) { + char *info = zalloc(sizeof(info_s)); + if (info) { + lseek(infd, offsetof(fullcontext_s, info), SEEK_SET); + ret = read(infd, info, sizeof(info_s)); + if (ret < 0) { + identify(caller); + syslog(LOG_INFO, "Failed to read Fault Log file [%s] (%d)\n", HARDFAULT_PATH, ret); + ret = -EIO; + } else { + info_s *pinfo = (info_s *) info; + ret = write_dump_header(caller, outfd, &desc->lastwrite, line, OUT_BUFFER_LEN); + if (ret == OK) { + + switch(format) { + case HARDFAULT_DISPLAY_FORMAT: + ret = write_intterupt_stack(infd, outfd, pinfo, line, OUT_BUFFER_LEN); + if (ret == OK || ret == -ENOENT) { + ret = write_user_stack(infd, outfd, pinfo, line, OUT_BUFFER_LEN); + if (ret == OK || ret == -ENOENT) { + ret = write_dump_info(outfd, pinfo, desc, line, OUT_BUFFER_LEN); + if (ret == OK || ret == -ENOENT) { + ret = write_registers_info(outfd, pinfo, line, OUT_BUFFER_LEN); + if (ret == OK || ret == -ENOENT) { + ret = write_interrupt_stack_info(outfd, pinfo, line, OUT_BUFFER_LEN); + if (ret == OK || ret == -ENOENT) { + ret = write_user_stack_info(outfd, pinfo, line, OUT_BUFFER_LEN); + } + } + } + } + } + break; + + case HARDFAULT_FILE_FORMAT: + ret = write_dump_info(outfd, pinfo, desc, line, OUT_BUFFER_LEN); + if (ret == OK) { + ret = write_registers_info(outfd, pinfo, line, OUT_BUFFER_LEN); + if (ret == OK || ret == -ENOENT) { + ret = write_interrupt_stack_info(outfd, pinfo, line, OUT_BUFFER_LEN); + if (ret == OK || ret == -ENOENT) { + ret = write_user_stack_info(outfd, pinfo, line, OUT_BUFFER_LEN); + if (ret == OK || ret == -ENOENT) { + ret = write_intterupt_stack(infd, outfd, pinfo, line, OUT_BUFFER_LEN); + if (ret == OK || ret == -ENOENT) { + ret = write_user_stack(infd, outfd, pinfo, line, OUT_BUFFER_LEN); + } + } + } + } + } + break; + + default: + ret = -EINVAL; + break; + } + } + if (ret == OK || ret == -ENOENT) { + ret = write_dump_footer(caller, outfd, &desc->lastwrite, line, OUT_BUFFER_LEN); + } + } + free(info); + } + free(line); + } + return ret; +} + + /**************************************************************************** * Public Functions ****************************************************************************/ @@ -602,75 +720,80 @@ __EXPORT int hardfault_increment_reboot(char *caller, bool reset) identify(caller); syslog(LOG_INFO, "Failed to open Fault reboot count file [%s] (%d)\n", HARDFAULT_REBOOT_PATH, ret); } else { + + ret = OK; if (!reset) { - read(fd, &count, sizeof(count)); - lseek(fd, 0, SEEK_SET); - count++; + if (read(fd, &count, sizeof(count)) != sizeof(count)) { + ret = -EIO; + close(fd); + } else { + lseek(fd, 0, SEEK_SET); + count++; + } + } + + if (ret == OK) { + ret = write(fd, &count, sizeof(count)); + if (ret != sizeof(count)) { + ret = -EIO; + } else { + ret = close(fd); + if (ret == OK) { + ret = count; + } + } } - ret = write(fd, &count, sizeof(count)); - close(fd); - ret = count; } return ret; } /**************************************************************************** * hardfault_write ****************************************************************************/ -fullcontext_s dump; __EXPORT int hardfault_write(char *caller, int fd, int format, bool rearm) { - char line[200]; - memset(&dump,0,sizeof(dump)); struct bbsramd_s desc; + + switch(format) { + + case HARDFAULT_FILE_FORMAT: + case HARDFAULT_DISPLAY_FORMAT: + break; + + default: + return -EINVAL; + } + int ret = hardfault_get_desc(caller, &desc, false); if (ret >= 0) { int hffd = ret; - ret = read(hffd, (char *)&dump, sizeof(dump)); + + + int rv = hardfault_dowrite(caller, hffd, fd, &desc, format); + + ret = close(hffd); if (ret < 0) { identify(caller); - syslog(LOG_INFO, "Failed to read Fault Log file [%s] (%d)\n", HARDFAULT_PATH, ret); - } else { - ret = close(hffd); - if (ret < 0) { - identify(caller); - syslog(LOG_INFO, "Failed to Close Fault Log (%d)\n", ret); + syslog(LOG_INFO, "Failed to Close Fault Log (%d)\n", ret); - } else { - - switch(format) { - case HARDFAULT_DISPLAY_FORMAT: - write_dump_header(caller, fd, &desc.lastwrite,line, arraySize(line)); - write_intterupt_stack(fd, &dump, line, arraySize(line)); - write_user_stack(fd, &dump, line, arraySize(line)); - write_dump_info(fd, &dump, &desc.lastwrite, line, arraySize(line)); - write_registers_info(fd, &dump, line, arraySize(line)); - write_interrupt_stack_info(fd, &dump, line, arraySize(line)); - write_user_stack_info(fd, &dump, line, arraySize(line)); - break; - - case HARDFAULT_FILE_FORMAT: - write_dump_header(caller, fd, &desc.lastwrite,line, arraySize(line)); - write_dump_info(fd, &dump, &desc.lastwrite, line, arraySize(line)); - write_registers_info(fd, &dump, line, arraySize(line)); - write_interrupt_stack_info(fd, &dump, line, arraySize(line)); - write_user_stack_info(fd, &dump,line, arraySize(line)); - write_intterupt_stack(fd, &dump,line, arraySize(line)); - write_user_stack(fd, &dump, line, arraySize(line)); - break; - - default: - return -EINVAL; - break; - } + } - write_dump_footer(caller, fd, &desc.lastwrite,line, arraySize(line)); + if (rv == OK && rearm) { + ret = hardfault_rearm(caller); + if (ret < 0) { + identify(caller); + syslog(LOG_INFO, "Failed to re-arm Fault Log (%d)\n", ret); + } + } - if (rearm) { - ret = hardfault_rearm(caller); + if (ret == OK) { + ret = rv; + } - } - } + if (ret != OK) + { + identify(caller); + syslog(LOG_INFO, "Failed to Write Fault Log (%d)\n", ret); } } return ret; |