Skip to content

Commit 1fa4c20

Browse files
committed
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.
1 parent 98458c5 commit 1fa4c20

File tree

3 files changed

+30
-4
lines changed

3 files changed

+30
-4
lines changed

atmel-samd/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,8 +92,10 @@ CFLAGS_CORTEX_M0 = \
9292
CFLAGS = $(INC) -Wall -Werror -ansi -std=gnu99 -nostdlib $(CFLAGS_CORTEX_M0) $(COPT)
9393

9494
#Debugging/Optimization
95+
# TODO(tannewt): Figure out what NDEBUG does. Adding it to the debug build
96+
# reduces code size pretty dramatically.
9597
ifeq ($(DEBUG), 1)
96-
CFLAGS += -Os -ggdb
98+
CFLAGS += -Os -ggdb -DNDEBUG -DENABLE_MICRO_TRACE_BUFFER
9799
else
98100
CFLAGS += -Os -DNDEBUG
99101
endif

atmel-samd/asf/sam0/utils/cmsis/samd21/source/gcc/startup_samd21.c

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
*
4242
*/
4343

44+
#include <stdbool.h>
45+
4446
#include "samd21.h"
4547

4648
/* Initialize segments */
@@ -65,7 +67,7 @@ void Dummy_Handler(void);
6567

6668
/* Cortex-M0+ core handlers */
6769
void NMI_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
68-
void HardFault_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
70+
void HardFault_Handler( void ) __attribute__( ( naked ) );
6971
void SVC_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
7072
void PendSV_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
7173
void SysTick_Handler ( void ) __attribute__ ((weak, alias("Dummy_Handler")));
@@ -269,14 +271,24 @@ void Reset_Handler(void)
269271
main();
270272

271273
/* Infinite loop */
272-
while (1);
274+
while (true);
275+
}
276+
277+
void HardFault_Handler(void)
278+
{
279+
#ifdef ENABLE_MICRO_TRACE_BUFFER
280+
// Turn off the micro trace buffer so we don't fill it up in the infinite
281+
// loop below.
282+
REG_MTB_MASTER = 0x00000000 + 6;
283+
#endif
284+
while(true) {}
273285
}
274286

275287
/**
276288
* \brief Default interrupt handler for unused IRQs.
277289
*/
278290
void Dummy_Handler(void)
279291
{
280-
while (1) {
292+
while (true) {
281293
}
282294
}

atmel-samd/main.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,19 @@ void MP_WEAK __assert_func(const char *file, int line, const char *func, const c
270270

271271
struct usart_module usart_instance;
272272

273+
#ifdef ENABLE_MICRO_TRACE_BUFFER
274+
#define TRACE_BUFFER_SIZE 256
275+
__attribute__((__aligned__(TRACE_BUFFER_SIZE * sizeof(uint32_t)))) uint32_t mtb[TRACE_BUFFER_SIZE];
276+
#endif
277+
273278
void samd21_init(void) {
279+
#ifdef ENABLE_MICRO_TRACE_BUFFER
280+
memset(mtb, 0, sizeof(mtb));
281+
// AWIDTH is 15.
282+
REG_MTB_POSITION = ((uint32_t) (mtb - REG_MTB_BASE)) & 0xFFFFFFF8;
283+
REG_MTB_FLOW = ((uint32_t) mtb + TRACE_BUFFER_SIZE * sizeof(uint32_t)) & 0xFFFFFFF8;
284+
REG_MTB_MASTER = 0x80000000 + 6;
285+
#endif
274286
irq_initialize_vectors();
275287
cpu_irq_enable();
276288

0 commit comments

Comments
 (0)