feat(vd960DBN): fault_diag — .noinit RAM 现场 + 执行轨迹 marker 定位神秘复位
现象: LUP 帧后复位, RST=0x00000000 (无标志) 且 HardFault 打印缺失
(上次 0x10000000=SFT 确认 HardFault 路径, 这次连打印都没有)
方案: .noinit 段复位不清零, 跨复位留痕
- Link.ld: 新增 .noinit 段 (startup 只清 .bss 不碰)
- fault_diag.h: FaultDiag{magic,mcause,mepc,mtval,marker,boot_cnt} + FAULT_MARKER 轨迹宏
- HardFault_Handler: 纯 RAM 写 mcause/mepc/mtval (官方 __get_MCAUSE/MEPC/MTVAL,
不依赖 UART/printf, 栈坏也能留痕) + 尽力打印
- main 开头 fault_diag_init(): 打印上次现场 + 递增 boot_cnt
- 轨迹 marker: 主循环 LOOP_TOP/UART_SRV/SIM_SPI/POLL_BLE + LUP 链
LUP_FRAME/INGEST/EVT_FEED 入口出口, 复位后看 marker 停在哪一步
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : fault_diag.h
|
||||
* Author : wfq
|
||||
* Version : V1.0
|
||||
* Date : 2026-08-13
|
||||
* Description : 故障诊断 — .noinit RAM 现场 + 执行轨迹 marker
|
||||
*
|
||||
* 背景: HardFault 时 UART/printf 可能不可用 (栈坏/中断禁用), 打印丢现场;
|
||||
* RST=0x00000000 的复位无任何标志, 无法从 RSTSCKR 判断复位源。
|
||||
* 方案: 全局记录放 .noinit 段 (复位不清零, 链接脚本已加):
|
||||
* - HardFault_Handler 纯 RAM 写 mcause/mepc/mtval (不依赖 UART)
|
||||
* - 关键路径 FAULT_MARKER() 记录执行轨迹
|
||||
* - main 开头 fault_diag_init() 打印上次现场 + 递增 boot_cnt
|
||||
* 用法: FAULT_MARKER(MK_XXX) 插在嫌疑路径各阶段; 复位后看 marker 停在哪。
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __FAULT_DIAG_H
|
||||
#define __FAULT_DIAG_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct {
|
||||
uint32_t magic; /* 0xFA57FA57 = 现场有效 */
|
||||
uint32_t mcause; /* RISC-V 异常原因 (5/7=野指针 2=非法指令 4/6=未对齐) */
|
||||
uint32_t mepc; /* 异常指令 PC (对照 .map 反查函数) */
|
||||
uint32_t mtval; /* 错误访问地址 */
|
||||
uint32_t marker; /* 最后执行位置标记 */
|
||||
uint32_t boot_cnt; /* 复位计数 */
|
||||
} FaultDiag;
|
||||
|
||||
/* 定义在 ch32v20x_it.c (.noinit 段) */
|
||||
extern FaultDiag g_fault_diag;
|
||||
|
||||
/* main 开头调用: 打印上次现场 + 重置 + boot_cnt++ */
|
||||
void fault_diag_init(void);
|
||||
|
||||
/* 执行轨迹标记 */
|
||||
#define FAULT_MARKER(s) (g_fault_diag.marker = (s))
|
||||
|
||||
#define MK_MAIN_ENTRY 0xA0000001UL /* main 入口 */
|
||||
#define MK_INIT_DONE 0xA0000002UL /* 初始化完成, 进主循环前 */
|
||||
#define MK_LOOP_TOP 0xA0000010UL /* 主循环 while 开头 */
|
||||
#define MK_UART_SRV_IN 0xA0000011UL /* uart_srv 调用前 */
|
||||
#define MK_UART_SRV_OUT 0xA0000012UL /* uart_srv 返回后 */
|
||||
#define MK_SIM_SPI_IN 0xA0000013UL /* sim_snap_spi 调用前 */
|
||||
#define MK_POLL_BLE_IN 0xA0000014UL /* poll_dbn_ble 调用前 */
|
||||
#define MK_LUP_FRAME_IN 0xA0000020UL /* lup_process_frame 入口 */
|
||||
#define MK_LUP_FRAME_OUT 0xA0000021UL /* lup_process_frame 出口 */
|
||||
#define MK_INGEST_IN 0xA0000030UL /* iot_sensor_ingest 入口 */
|
||||
#define MK_INGEST_OUT 0xA0000031UL /* iot_sensor_ingest 出口 */
|
||||
#define MK_EVT_FEED_IN 0xA0000032UL /* iot_evt_feed 入口 */
|
||||
#define MK_EVT_FEED_OUT 0xA0000033UL /* iot_evt_feed 出口 */
|
||||
#define MK_EVT_CB_IN 0xA0000034UL /* iot_evt_sensor_cb 入口 */
|
||||
#define MK_EVT_CB_OUT 0xA0000035UL /* iot_evt_sensor_cb 出口 */
|
||||
|
||||
#endif /* __FAULT_DIAG_H */
|
||||
Reference in New Issue
Block a user