diff --git a/driver/CMakeLists.txt b/driver/CMakeLists.txt index bd56f2c..23a07fd 100755 --- a/driver/CMakeLists.txt +++ b/driver/CMakeLists.txt @@ -15,10 +15,16 @@ stddriver/src/system_stm32f4xx.c sdcard/fatfs_drv.c sdcard/sdio_lowlevel.c sdcard/sdio_sd.c + +stdio/mini_printf.c + +coredump/coredump.c ) add_library(driver STATIC ${FILELIST}) target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/stddriver/inc) target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/cmsis/inc) target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/sdcard) +target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/stdio) +target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/coredump) target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../component/fatfs/inc) diff --git a/driver/coredump/coredump.c b/driver/coredump/coredump.c new file mode 100755 index 0000000..e0f5a35 --- /dev/null +++ b/driver/coredump/coredump.c @@ -0,0 +1,56 @@ +#include "coredump.h" +#include "mini_printf.h" + +extern uint32_t _stack_top; +extern uint32_t _data_run; +extern uint32_t _data_run_end; +extern uint32_t _data_ccm_run; +extern uint32_t _data_ccm_run_end; +extern uint32_t _bss_run; +extern uint32_t _bss_run_end; +extern uint32_t _bss_ccm_run; +extern uint32_t _bss_ccm_run_end; + +static void coredump_registers(struct coredump_regs_s *sp, char *thread) +{ + mini_printf("\nregister@%s\n", thread); + mini_printf("R0: 0x%p\n", sp->r0); + mini_printf("R1: 0x%p\n", sp->r1); + mini_printf("R2: 0x%p\n", sp->r2); + mini_printf("R3: 0x%p\n", sp->r3); + mini_printf("R4: 0x%p\n", sp->r4); + mini_printf("R5: 0x%p\n", sp->r5); + mini_printf("R6: 0x%p\n", sp->r6); + mini_printf("R7: 0x%p\n", sp->r7); + mini_printf("R8: 0x%p\n", sp->r8); + mini_printf("R9: 0x%p\n", sp->r9); + mini_printf("R10: 0x%p\n", sp->r10); + mini_printf("R11: 0x%p\n", sp->r11); + mini_printf("R12: 0x%p\n", sp->r12); + mini_printf("R13(SP): 0x%p\n", (uint32_t)sp + sizeof(*sp)); + mini_printf("R14(LR): 0x%p\n", sp->lr); + mini_printf("R15(PC): 0x%p\n", sp->pc); + mini_printf("xPSR: 0x%p\n", sp->xpsr); +} + +static void coredump_memory(uint32_t *start, uint32_t *end, char *comment) +{ + mini_printf("\nmemory@%s, length=%d", comment, end - start); + for (uint32_t p = (uint32_t)start & 0xFFFFFFF0; p < (uint32_t)end; p += 4) { + if ((p & 0xF) == 0) { + mini_printf("\n0x%p:", p); + } + mini_printf(" %p", *(uint32_t *)p); + } +} + +void coredump(struct coredump_regs_s *sp) +{ + mini_printf_init(); + coredump_registers(sp, "main_thread"); + coredump_memory((uint32_t*)sp, &_stack_top, "stack"); + coredump_memory(&_data_run, &_data_run_end, "data"); + coredump_memory(&_data_ccm_run, &_data_ccm_run_end, "data_ccm"); + coredump_memory(&_bss_run, &_bss_run_end, "bss"); + coredump_memory(&_bss_ccm_run, &_bss_ccm_run_end, "bss_ccm"); +} diff --git a/driver/coredump/coredump.h b/driver/coredump/coredump.h new file mode 100755 index 0000000..56cb88c --- /dev/null +++ b/driver/coredump/coredump.h @@ -0,0 +1,37 @@ +#ifndef __COREDUMP_H__ +#define __COREDUMP_H__ + +#include + +#ifdef __cplusplus + extern "C" { +#endif + +struct coredump_regs_s { + /* register saved by software */ + uint32_t exc_return; + uint32_t r4; + uint32_t r5; + uint32_t r6; + uint32_t r7; + uint32_t r8; + uint32_t r9; + uint32_t r10; + uint32_t r11; + + /* saved in sp */ + uint32_t r0; + uint32_t r1; + uint32_t r2; + uint32_t r3; + uint32_t r12; + uint32_t lr; + uint32_t pc; + uint32_t xpsr; +} coredump_regs; + +#ifdef __cplusplus +} +#endif + +#endif /* __COREDUMP_H__ */ diff --git a/driver/stdio/mini_printf.c b/driver/stdio/mini_printf.c new file mode 100755 index 0000000..67f7c3c --- /dev/null +++ b/driver/stdio/mini_printf.c @@ -0,0 +1,125 @@ +#include "mini_printf.h" +#include "stm32f4xx_rcc.h" +#include "stm32f4xx_gpio.h" +#include "stm32f4xx_usart.h" + +void mini_printf_init(void) +{ + USART_ITConfig(USART3, USART_IT_TC, DISABLE); + USART_ClearITPendingBit(USART3, USART_IT_TC); + USART_DMACmd(USART3, USART_DMAReq_Tx, DISABLE); +} + +static void uart_putc_raw(char c) { + while (USART_GetFlagStatus(USART3, USART_FLAG_TXE) == RESET); + USART_SendData(USART3, (uint16_t)c); +} + +static void uart_putc(char c) { + if (c == '\n') + uart_putc_raw('\r'); + uart_putc_raw(c); +} + +#include +#include +void mini_printf(const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + + while (*fmt) { + char c = *fmt++; + if (c == '%') { + char c2 = *fmt++; + switch (c2) { + case '%': + uart_putc(c); + break; + case 's': { + const char *v = va_arg(va, const char *); + while (*v) { + uart_putc(*v++); + } + break; + } + case 'd': { + int v = va_arg(va, int); + if (v < 0) { + v = -v; + uart_putc('-'); + } + static const int tens[] = { + 1000000000, + 100000000, + 1000000, + 100000, + 10000, + 1000, + 100, + 10, + 1, + }; + if (!v) { + uart_putc('0'); + } else { + bool had = false; + for(int i = 0; i < sizeof(tens) / sizeof(tens[0]); i++) { + int d = 0; + while (tens[i] <= v) { + v -= tens[i]; + d++; + } + if (d || had) { + uart_putc((char)('0'+d)); + had = true; + } + } + } + break; + } + case 'p': { + uint32_t v = va_arg(va, uint32_t); + for(int pos=7;pos>=0;pos--) { + int d = (v >> (pos * 4)) & 0xf; + if (d < 10) uart_putc((char)('0'+d)); + else uart_putc((char)('a'+d - 10)); + } + break; + } + case '0': { + uint32_t v = va_arg(va, uint32_t); + if (fmt[0] > '0' && fmt[0] < '9' && fmt[1] == 'x') { + int zeros = fmt[0]-'1'; + bool had_digit=false; + for(int pos=7;pos>=0;pos--) { + int d = (v >> (pos * 4)) & 0xf; + if (!d && pos > zeros && !had_digit) continue; + had_digit = true; + if (d < 10) uart_putc((char)('0'+d)); + else uart_putc((char)('a'+d - 10)); + } + fmt+=2; + break; + } + __attribute__((fallthrough)); + } + default: + uart_putc('%'); + uart_putc(c2); + uart_putc('?'); + uart_putc('?'); + } + } else { + uart_putc(c); + } + } + va_end(va); +} + +void mini_puts(const char *str) { + while (*str) { + uart_putc(*str++); + } + uart_putc('\n'); +} diff --git a/driver/stdio/mini_printf.h b/driver/stdio/mini_printf.h new file mode 100755 index 0000000..f596a73 --- /dev/null +++ b/driver/stdio/mini_printf.h @@ -0,0 +1,17 @@ +#ifndef __MINI_PRINTF_H__ +#define __MINI_PRINTF_H__ + +#ifdef __cplusplus + extern "C" { +#endif + +#include "stm32f4xx.h" + +void mini_printf_init(void); +void mini_printf(const char *fmt, ...); + +#ifdef __cplusplus +} +#endif + +#endif /* __MINI_PRINTF_H__ */ diff --git a/lark1fq/start.S b/lark1fq/start.S index f5f4379..f5ebad9 100755 --- a/lark1fq/start.S +++ b/lark1fq/start.S @@ -66,8 +66,19 @@ Reset_Handler: .section .text.Default_Handler,"ax",%progbits Default_Handler: -Infinite_Loop: - b Infinite_Loop + MRS r0, msp + STMFD r0!, {r4 - r11} + STMFD r0!, {lr} + MSR msp, r0 + + PUSH {lr} + BL coredump + POP {lr} + + POP {lr} + POP {r4 - r11} + + BX lr .size Default_Handler, .-Default_Handler .section .isr_vector,"a",%progbits