CCM扩容FreeRTOS堆+DMA阈值1024防栈缓冲进CCM+HardFault现场报告与栈/内存钩子+修defaultTask栈溢出+LVGL绘制缓冲护栏+存储套件05/06与恢复模式
This commit is contained in:
+61
-3
@@ -25,6 +25,7 @@
|
||||
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "test_config.h" /* 套件选择:STORAGE 套件下 defaultTask 让出存储所有权 */
|
||||
#include <string.h>
|
||||
#include "net_task.h"
|
||||
#include "ch395f.h"
|
||||
@@ -72,7 +73,10 @@ const osThreadAttr_t timeSyncTask_attributes = {
|
||||
osThreadId_t defaultTaskHandle;
|
||||
const osThreadAttr_t defaultTask_attributes = {
|
||||
.name = "defaultTask",
|
||||
.stack_size = 512 * 4,
|
||||
.stack_size = 1024 * 4, /* 512→1024: 该任务扛 mount+mkfs+FAT探针+cfg加载+syslog写+
|
||||
* 配置引擎(全深层 FatFS I/O),2KB 实测峰值溢出——开启
|
||||
* configCHECK_FOR_STACK_OVERFLOW=2 后被钩子抓到(2026-09-21)。
|
||||
* 此前静默溢出腐蚀堆相邻块。改 .ioc 前须同步此值防 CubeMX 覆盖 */
|
||||
.priority = (osPriority_t) osPriorityNormal,
|
||||
};
|
||||
/* Definitions for netTask */
|
||||
@@ -93,7 +97,7 @@ const osThreadAttr_t ftpTask_attributes = {
|
||||
osThreadId_t testTaskHandle;
|
||||
const osThreadAttr_t testTask_attributes = {
|
||||
.name = "testTask",
|
||||
.stack_size = 1024 * 4,
|
||||
.stack_size = 2048 * 4, /* 1024→2048: 存储套件 deep call chain + 局部缓冲,4KB 实测溢出(2026-09-20) */
|
||||
.priority = (osPriority_t) osPriorityBelowNormal,
|
||||
};
|
||||
/* Definitions for uiTask */
|
||||
@@ -117,7 +121,9 @@ const osEventFlagsAttr_t sys_evt_attributes = {
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* USER CODE BEGIN FunctionPrototypes */
|
||||
void ui_task_func(void *argument);
|
||||
#if !defined(TEST_SUITE_STORAGE)
|
||||
static void default_task_net_cfg_save_notify(void);
|
||||
#endif
|
||||
/* USER CODE END FunctionPrototypes */
|
||||
|
||||
void StartDefaultTask(void *argument);
|
||||
@@ -225,7 +231,12 @@ void StartDefaultTask(void *argument)
|
||||
* 防 FTL 瞬态抖动误触发);结构性错误 → 自动重格式化自愈。代价:卷被清空
|
||||
* (/config.ini 丢失 → 配置引擎首启路径回落工厂默认并自动重建模板)——
|
||||
* 仅当卷已不可用时触发,可用设备 > 一份配置文件。 */
|
||||
static FATFS default_fatfs;
|
||||
#if !defined(TEST_SUITE_STORAGE)
|
||||
/* STORAGE 套件构建下 defaultTask 完全跳过存储 bring-up(挂载/配置/日志盘写),
|
||||
* 卷由 testTask 的 storage_test_run 独占——测试含 nand_ftl_deinit 掉电模拟,
|
||||
* 与任何后台文件写入并发都会互相踩坏 FTL/FatFs 状态(2026-09-20 台架实证:
|
||||
* 双写并发导致 mkfs 半途冻结 + BBT 被误写) */
|
||||
static FATFS default_fatfs;
|
||||
FRESULT fr = f_mount(&default_fatfs, "", 1);
|
||||
if (fr == FR_NO_FILESYSTEM) {
|
||||
DBG_INFO("[FS] no FAT volume, formatting NAND...");
|
||||
@@ -330,6 +341,10 @@ void StartDefaultTask(void *argument)
|
||||
/* 注册"保存网络配置"请求通知:UI(uiTask)投递 → 置事件 → 本任务立即执行写盘
|
||||
* (配置引擎属主 = 本任务;UI 保存不再直接触碰配置文件引擎,P1-3) */
|
||||
net_cfg_set_save_req_cb(default_task_net_cfg_save_notify);
|
||||
#else
|
||||
/* STORAGE 套件构建:挂载/配置引擎/日志盘写全部跳过,存储由 testTask 独占 */
|
||||
DBG_INFO("[FS] mount/cfg skipped (STORAGE suite owns storage)");
|
||||
#endif
|
||||
|
||||
/* 配置 poll 周期计数(每 4 次循环 = 2s 轮询一次,与引擎文档/模拟器一致) */
|
||||
uint32_t cfg_poll_cnt = 0u;
|
||||
@@ -341,16 +356,22 @@ void StartDefaultTask(void *argument)
|
||||
(void)osEventFlagsWait(sys_evtHandle, SYS_EVT_CFG_SAVE, osFlagsWaitAny, 500u);
|
||||
}
|
||||
/* 执行待处理保存(配置引擎属主:写盘 + 成功后立即应用);无请求 = 空操作 */
|
||||
#if !defined(TEST_SUITE_STORAGE)
|
||||
net_cfg_save_run();
|
||||
#endif
|
||||
/* 配置文件变更轮询(2s 周期;沉降去抖在引擎内) */
|
||||
if ((cfg_poll_cnt++ & 3u) == 0u) {
|
||||
#if !defined(TEST_SUITE_STORAGE)
|
||||
cfg_file_poll();
|
||||
#endif
|
||||
}
|
||||
HAL_GPIO_TogglePin(LED1_GPIO_Port, LED1_Pin);
|
||||
HAL_GPIO_TogglePin(LED2_GPIO_Port, LED2_Pin);
|
||||
HAL_GPIO_TogglePin(LED3_GPIO_Port, LED3_Pin);
|
||||
#if !defined(TEST_SUITE_STORAGE)
|
||||
/* 排空运行期日志(上电/重启分类与自检故障落盘) */
|
||||
syslog_drain();
|
||||
#endif
|
||||
}
|
||||
/* USER CODE END StartDefaultTask */
|
||||
}
|
||||
@@ -438,10 +459,47 @@ void StartUiTask(void *argument)
|
||||
* "保存网络配置"请求通知(注册给 net_cfg 的保存交接):
|
||||
* uiTask 投递保存请求 → 置 SYS_EVT_CFG_SAVE → defaultTask 循环立即唤醒执行写盘
|
||||
*/
|
||||
#if !defined(TEST_SUITE_STORAGE)
|
||||
static void default_task_net_cfg_save_notify(void)
|
||||
{
|
||||
if (sys_evtHandle != NULL) {
|
||||
(void)osEventFlagsSet(sys_evtHandle, SYS_EVT_CFG_SAVE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 栈溢出钩子(configCHECK_FOR_STACK_OVERFLOW=2,2026-09-20 存储套件死机事故后加):
|
||||
* 溢出 = 内核状态已不可信,禁止走 printf/内核对象,裸 UART 报任务名后复位。
|
||||
*/
|
||||
void vApplicationStackOverflowHook(void *xTask, signed char *pcTaskName)
|
||||
{
|
||||
static const char msg_head[] = "\r\n[ERR] STACK OVERFLOW task=";
|
||||
|
||||
(void)xTask;
|
||||
HAL_UART_Transmit(&huart1, (const uint8_t *)msg_head,
|
||||
(uint16_t)(sizeof(msg_head) - 1u), 0xFFFFu);
|
||||
if (pcTaskName != NULL) {
|
||||
uint16_t len = 0;
|
||||
while (len < 32u && pcTaskName[len] != '\0') {
|
||||
len++;
|
||||
}
|
||||
HAL_UART_Transmit(&huart1, (const uint8_t *)pcTaskName, len, 0xFFFFu);
|
||||
}
|
||||
HAL_UART_Transmit(&huart1, (const uint8_t *)"\r\n", 2u, 0xFFFFu);
|
||||
HAL_Delay(200);
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
/*
|
||||
* 堆分配失败钩子:只告警不复位(NULL 由各调用点自行处理并上报自检)。
|
||||
* 同样走裸 UART——钩子可能在临界区内被调,printf/信号量不可用。
|
||||
*/
|
||||
void vApplicationMallocFailedHook(void)
|
||||
{
|
||||
static const char msg[] = "\r\n[ERR] MALLOC FAILED (heap exhausted)\r\n";
|
||||
|
||||
HAL_UART_Transmit(&huart1, (const uint8_t *)msg,
|
||||
(uint16_t)(sizeof(msg) - 1u), 0xFFFFu);
|
||||
}
|
||||
/* USER CODE END Application */
|
||||
|
||||
+79
-9
@@ -22,6 +22,7 @@
|
||||
#include "stm32f4xx_it.h"
|
||||
/* Private includes ----------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Includes */
|
||||
#include "usart.h"
|
||||
/* USER CODE END Includes */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
@@ -95,17 +96,86 @@ void NMI_Handler(void)
|
||||
/**
|
||||
* @brief This function handles Hard fault interrupt.
|
||||
*/
|
||||
void HardFault_Handler(void)
|
||||
/* USER CODE BEGIN HardFault_Handler */
|
||||
/* 崩溃现场采集(本函数为手工改写,CubeMX 重生成会覆盖!):
|
||||
* EXC_RETURN bit2 判断异常帧在 MSP 还是 PSP,取帧指针交给 C 报告函数。
|
||||
* 空 while(1) 版会让死机在日志上完全静默(2026-09-20 存储套件死机排查实证) */
|
||||
__asm void HardFault_Handler(void)
|
||||
{
|
||||
/* USER CODE BEGIN HardFault_IRQn 0 */
|
||||
|
||||
/* USER CODE END HardFault_IRQn 0 */
|
||||
while (1)
|
||||
{
|
||||
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
|
||||
/* USER CODE END W1_HardFault_IRQn 0 */
|
||||
}
|
||||
extern hard_fault_report
|
||||
TST lr, #4
|
||||
ITE EQ
|
||||
MRSEQ r0, MSP
|
||||
MRSNE r0, PSP
|
||||
B hard_fault_report
|
||||
}
|
||||
/* USER CODE END HardFault_Handler */
|
||||
|
||||
/* USER CODE BEGIN HardFault_Report */
|
||||
/*
|
||||
* 函数功能:HardFault 现场报告(裸机上下文,不经内核/printf)
|
||||
* 入口参数:frame - 异常栈帧 {R0,R1,R2,R3,R12,LR,PC,xPSR}
|
||||
* 函数说明:直接 HAL_UART_Transmit 轮询输出 PC/LR/xPSR 与 CFSR/HFSR 故障
|
||||
* 寄存器,供开机日志定位崩溃点(对照 .map 找符号);输出后复位。
|
||||
*/
|
||||
static void hard_fault_puts(const char *s)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
|
||||
while (s[len] != '\0') {
|
||||
len++;
|
||||
}
|
||||
HAL_UART_Transmit(&huart1, (const uint8_t *)s, len, 0xFFFFu);
|
||||
}
|
||||
|
||||
static void hard_fault_puthex(uint32_t v)
|
||||
{
|
||||
static const char digits[] = "0123456789ABCDEF";
|
||||
char out[9];
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
out[i] = digits[(v >> (28 - i * 4)) & 0xFu];
|
||||
}
|
||||
out[8] = '\0';
|
||||
hard_fault_puts(out);
|
||||
}
|
||||
|
||||
void hard_fault_report(uint32_t *frame)
|
||||
{
|
||||
hard_fault_puts("\r\n[ERR] HARDFAULT PC=");
|
||||
hard_fault_puthex(frame[6]);
|
||||
hard_fault_puts(" LR=");
|
||||
hard_fault_puthex(frame[5]);
|
||||
hard_fault_puts(" xPSR=");
|
||||
hard_fault_puthex(frame[7]);
|
||||
hard_fault_puts(" R0=");
|
||||
hard_fault_puthex(frame[0]);
|
||||
hard_fault_puts(" R1=");
|
||||
hard_fault_puthex(frame[1]);
|
||||
hard_fault_puts(" R2=");
|
||||
hard_fault_puthex(frame[2]);
|
||||
hard_fault_puts(" R3=");
|
||||
hard_fault_puthex(frame[3]);
|
||||
hard_fault_puts(" CFSR=");
|
||||
hard_fault_puthex(SCB->CFSR);
|
||||
hard_fault_puts(" HFSR=");
|
||||
hard_fault_puthex(SCB->HFSR);
|
||||
|
||||
/* BFAR/MMFAR 仅在对应 valid 位为 1 时有意义 */
|
||||
if ((SCB->CFSR & (1UL << 15)) != 0U) {
|
||||
hard_fault_puts(" BFAR=");
|
||||
hard_fault_puthex(SCB->BFAR);
|
||||
}
|
||||
if ((SCB->CFSR & (1UL << 7)) != 0U) {
|
||||
hard_fault_puts(" MMFAR=");
|
||||
hard_fault_puthex(SCB->MMFAR);
|
||||
}
|
||||
|
||||
HAL_Delay(200);
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
/* USER CODE END HardFault_Report */
|
||||
|
||||
/**
|
||||
* @brief This function handles Memory management fault.
|
||||
|
||||
Reference in New Issue
Block a user