Add heap information to fatal exception & abort dumps
This commit is contained in:
parent
efedd24624
commit
981c87899b
4 changed files with 47 additions and 4 deletions
|
@ -73,6 +73,7 @@
|
||||||
#include <malloc.h>
|
#include <malloc.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <xtensa_ops.h>
|
||||||
|
|
||||||
#include "FreeRTOS.h"
|
#include "FreeRTOS.h"
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
|
@ -87,7 +88,7 @@ char level1_int_disabled;
|
||||||
After tasks start, task stacks are all allocated from the heap and
|
After tasks start, task stacks are all allocated from the heap and
|
||||||
FreeRTOS checks for stack overflow.
|
FreeRTOS checks for stack overflow.
|
||||||
*/
|
*/
|
||||||
static uint32_t xPortSupervisorStackPointer;
|
uint32_t xPortSupervisorStackPointer;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Stack initialization
|
* Stack initialization
|
||||||
|
@ -220,7 +221,7 @@ size_t xPortGetFreeHeapSize( void )
|
||||||
|
|
||||||
uint32_t sp = xPortSupervisorStackPointer;
|
uint32_t sp = xPortSupervisorStackPointer;
|
||||||
if(sp == 0) /* scheduler not started */
|
if(sp == 0) /* scheduler not started */
|
||||||
__asm__ __volatile__ ("mov %0, a1\n" : "=a"(sp));
|
SP(sp);
|
||||||
return sp - brk_val + mi.fordblks;
|
return sp - brk_val + mi.fordblks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,8 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <FreeRTOS.h>
|
#include <FreeRTOS.h>
|
||||||
#include <task.h>
|
#include <task.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "debug_dumps.h"
|
#include "debug_dumps.h"
|
||||||
#include "common_macros.h"
|
#include "common_macros.h"
|
||||||
|
@ -156,18 +158,55 @@ static void fatal_exception_handler_inner(uint32_t *sp, bool registers_saved_on_
|
||||||
}
|
}
|
||||||
dump_stack(sp);
|
dump_stack(sp);
|
||||||
}
|
}
|
||||||
|
dump_heapinfo();
|
||||||
uart_flush_txfifo(0);
|
uart_flush_txfifo(0);
|
||||||
uart_flush_txfifo(1);
|
uart_flush_txfifo(1);
|
||||||
sdk_system_restart_in_nmi();
|
sdk_system_restart_in_nmi();
|
||||||
while(1) {}
|
while(1) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dump_heapinfo(void)
|
||||||
|
{
|
||||||
|
extern char _heap_start;
|
||||||
|
extern uint32_t xPortSupervisorStackPointer;
|
||||||
|
struct mallinfo mi = mallinfo();
|
||||||
|
uint32_t brk_val = (uint32_t) sbrk(0);
|
||||||
|
uint32_t sp = xPortSupervisorStackPointer;
|
||||||
|
if(sp == 0) {
|
||||||
|
SP(sp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Total free heap is all memory that could be allocated via
|
||||||
|
malloc (assuming fragmentation doesn't become a problem) */
|
||||||
|
printf("\nFree Heap: %d\n", sp - brk_val + mi.fordblks);
|
||||||
|
|
||||||
|
/* delta between brk & supervisor sp is the contiguous memory
|
||||||
|
region that is available to be put into heap space via
|
||||||
|
brk(). */
|
||||||
|
printf("_heap_start %p brk 0x%08x supervisor sp 0x%08x sp-brk %d bytes\n",
|
||||||
|
&_heap_start, brk_val, sp, sp-brk_val);
|
||||||
|
|
||||||
|
/* arena/fordblks/uordblks determines the amount of free space
|
||||||
|
inside the heap region already added via brk(). May be
|
||||||
|
fragmented.
|
||||||
|
|
||||||
|
The values in parentheses are the values used internally by
|
||||||
|
nano-mallocr.c, the field names outside parentheses are the
|
||||||
|
POSIX compliant field names of the mallinfo structure.
|
||||||
|
|
||||||
|
"arena" should be equal to brk-_heap_start ie total size available.
|
||||||
|
*/
|
||||||
|
printf("arena (total_size) %d fordblks (free_size) %d uordblocks (used_size) %d\n",
|
||||||
|
mi.arena, mi.fordblks, mi.uordblks);
|
||||||
|
}
|
||||||
|
|
||||||
/* Main part of abort handler, can be run from flash to save some
|
/* Main part of abort handler, can be run from flash to save some
|
||||||
IRAM.
|
IRAM.
|
||||||
*/
|
*/
|
||||||
static void abort_handler_inner(uint32_t *caller, uint32_t *sp) {
|
static void abort_handler_inner(uint32_t *caller, uint32_t *sp) {
|
||||||
printf("abort() invoked at %p.\n", caller);
|
printf("abort() invoked at %p.\n", caller);
|
||||||
dump_stack(sp);
|
dump_stack(sp);
|
||||||
|
dump_heapinfo();
|
||||||
uart_flush_txfifo(0);
|
uart_flush_txfifo(0);
|
||||||
uart_flush_txfifo(1);
|
uart_flush_txfifo(1);
|
||||||
sdk_system_restart_in_nmi();
|
sdk_system_restart_in_nmi();
|
||||||
|
|
|
@ -10,9 +10,12 @@
|
||||||
#define _DEBUG_DUMPS_H
|
#define _DEBUG_DUMPS_H
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
/* Dump stack memory starting from stack pointer address sp. */
|
/* Dump stack memory to stdout, starting from stack pointer address sp. */
|
||||||
void dump_stack(uint32_t *sp);
|
void dump_stack(uint32_t *sp);
|
||||||
|
|
||||||
|
/* Dump heap statistics to stdout */
|
||||||
|
void dump_heapinfo(void);
|
||||||
|
|
||||||
/* Called from exception_vectors.S when a fatal exception occurs.
|
/* Called from exception_vectors.S when a fatal exception occurs.
|
||||||
|
|
||||||
Probably not useful to be called in other contexts.
|
Probably not useful to be called in other contexts.
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
* Note that the compiler will push a stack frame (minimum 16 bytes)
|
* Note that the compiler will push a stack frame (minimum 16 bytes)
|
||||||
* in the prelude of a C function that calls any other functions.
|
* in the prelude of a C function that calls any other functions.
|
||||||
*/
|
*/
|
||||||
#define SP(var) asm volatile ("mov %0, a1" : "=r" (var));
|
#define SP(var) asm volatile ("mov %0, a1" : "=r" (var))
|
||||||
|
|
||||||
/* Read the function return address to a variable.
|
/* Read the function return address to a variable.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue