CCM扩容FreeRTOS堆+DMA阈值1024防栈缓冲进CCM+HardFault现场报告与栈/内存钩子+修defaultTask栈溢出+LVGL绘制缓冲护栏+存储套件05/06与恢复模式

This commit is contained in:
2026-09-21 00:47:58 +08:00
parent 271adc38e1
commit 9230effced
9 changed files with 357 additions and 36 deletions
+61 -3
View File
@@ -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 */