[feat] add coredump
This commit is contained in:
parent
5064b5fc5c
commit
23c774b2a9
@ -15,10 +15,16 @@ stddriver/src/system_stm32f4xx.c
|
|||||||
sdcard/fatfs_drv.c
|
sdcard/fatfs_drv.c
|
||||||
sdcard/sdio_lowlevel.c
|
sdcard/sdio_lowlevel.c
|
||||||
sdcard/sdio_sd.c
|
sdcard/sdio_sd.c
|
||||||
|
|
||||||
|
stdio/mini_printf.c
|
||||||
|
|
||||||
|
coredump/coredump.c
|
||||||
)
|
)
|
||||||
|
|
||||||
add_library(driver STATIC ${FILELIST})
|
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}/stddriver/inc)
|
||||||
target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/cmsis/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}/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)
|
target_include_directories(driver PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../component/fatfs/inc)
|
||||||
|
|||||||
56
driver/coredump/coredump.c
Executable file
56
driver/coredump/coredump.c
Executable file
@ -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");
|
||||||
|
}
|
||||||
37
driver/coredump/coredump.h
Executable file
37
driver/coredump/coredump.h
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef __COREDUMP_H__
|
||||||
|
#define __COREDUMP_H__
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#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__ */
|
||||||
125
driver/stdio/mini_printf.c
Executable file
125
driver/stdio/mini_printf.c
Executable file
@ -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 <stdbool.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
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');
|
||||||
|
}
|
||||||
17
driver/stdio/mini_printf.h
Executable file
17
driver/stdio/mini_printf.h
Executable file
@ -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__ */
|
||||||
@ -66,8 +66,19 @@ Reset_Handler:
|
|||||||
|
|
||||||
.section .text.Default_Handler,"ax",%progbits
|
.section .text.Default_Handler,"ax",%progbits
|
||||||
Default_Handler:
|
Default_Handler:
|
||||||
Infinite_Loop:
|
MRS r0, msp
|
||||||
b Infinite_Loop
|
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
|
.size Default_Handler, .-Default_Handler
|
||||||
|
|
||||||
.section .isr_vector,"a",%progbits
|
.section .isr_vector,"a",%progbits
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user