From 1fa4c20c27264e55b3442fe49bee2078a4516fa6 Mon Sep 17 00:00:00 2001 From: Scott Shawcroft Date: Tue, 4 Oct 2016 16:13:33 -0700 Subject: [PATCH] atmel-samd: Add Micro Trace Buffer support to the debug build. The Micro Trace Buffer records the history of the pc and can be used to debug hard faults even when the stack trace is useless. --- atmel-samd/Makefile | 4 +++- .../cmsis/samd21/source/gcc/startup_samd21.c | 18 +++++++++++++++--- atmel-samd/main.c | 12 ++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) diff --git a/atmel-samd/Makefile b/atmel-samd/Makefile index 525d8c2262..1b67926467 100644 --- a/atmel-samd/Makefile +++ b/atmel-samd/Makefile @@ -92,8 +92,10 @@ CFLAGS_CORTEX_M0 = \ CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M0) $(COPT) #Debugging/Optimization +# TODO(tannewt): Figure out what NDEBUG does. Adding it to the debug build +# reduces code size pretty dramatically. ifeq ($(DEBUG), 1) -CFLAGS += -Os -ggdb +CFLAGS += -Os -ggdb -DNDEBUG -DENABLE_MICRO_TRACE_BUFFER else CFLAGS += -Os -DNDEBUG endif diff --git a/atmel-samd/asf/sam0/utils/cmsis/samd21/source/gcc/startup_samd21.c b/atmel-samd/asf/sam0/utils/cmsis/samd21/source/gcc/startup_samd21.c index c5561b3160..767fe0c254 100644 --- a/atmel-samd/asf/sam0/utils/cmsis/samd21/source/gcc/startup_samd21.c +++ b/atmel-samd/asf/sam0/utils/cmsis/samd21/source/gcc/startup_samd21.c @@ -41,6 +41,8 @@ * */ +#include + #include "samd21.h" /* Initialize segments */ @@ -65,7 +67,7 @@ void Dummy_Handler(void); /* Cortex-M0+ core handlers */ void NMI_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); -void HardFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); +void HardFault_Handler( void ) __attribute__( ( naked ) ); void SVC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); void PendSV_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); void SysTick_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler"))); @@ -269,7 +271,17 @@ void Reset_Handler(void) main(); /* Infinite loop */ - while (1); + while (true); +} + +void HardFault_Handler(void) +{ +#ifdef ENABLE_MICRO_TRACE_BUFFER + // Turn off the micro trace buffer so we don't fill it up in the infinite + // loop below. + REG_MTB_MASTER = 0x00000000 + 6; +#endif + while(true) {} } /** @@ -277,6 +289,6 @@ void Reset_Handler(void) */ void Dummy_Handler(void) { - while (1) { + while (true) { } } diff --git a/atmel-samd/main.c b/atmel-samd/main.c index b28b70668b..42dddb8d3b 100644 --- a/atmel-samd/main.c +++ b/atmel-samd/main.c @@ -270,7 +270,19 @@ void MP_WEAK __assert_func(const char *file, int line, const char *func, const c struct usart_module usart_instance; +#ifdef ENABLE_MICRO_TRACE_BUFFER +#define TRACE_BUFFER_SIZE 256 +__attribute__((__aligned__(TRACE_BUFFER_SIZE * sizeof(uint32_t)))) uint32_t mtb[TRACE_BUFFER_SIZE]; +#endif + void samd21_init(void) { +#ifdef ENABLE_MICRO_TRACE_BUFFER + memset(mtb, 0, sizeof(mtb)); + // AWIDTH is 15. + REG_MTB_POSITION = ((uint32_t) (mtb - REG_MTB_BASE)) & 0xFFFFFFF8; + REG_MTB_FLOW = ((uint32_t) mtb + TRACE_BUFFER_SIZE * sizeof(uint32_t)) & 0xFFFFFFF8; + REG_MTB_MASTER = 0x80000000 + 6; +#endif irq_initialize_vectors(); cpu_irq_enable();