修复上电启动失败:日志消息队列改为内核启动后惰性创建

This commit is contained in:
2026-09-20 00:36:36 +08:00
parent c3f7e52ea3
commit 9c94bfaae6
+21 -12
View File
@@ -7,6 +7,8 @@
* 创建日期:2026-09-14
* 修改记录:
* v1.0 2026-09-14 王建锋 创建初始版本(设计见 docs/运行与自检记录设计说明.md §4.4)
* v1.1 2026-09-21 王建锋 消息队列改为内核启动后由 syslog_drain 惰性创建
* (修复 osKernelStart 前创建 FreeRTOS 内核对象导致的启动失败)
*/
/* 头文件包含区 */
@@ -36,7 +38,8 @@ typedef struct {
static syslog_entry_t s_preboot[SYSLOG_QUEUE_MAX]; /* 启动前待发数组(RTOS 前单生产者/后单消费者,免锁) */
static volatile uint8_t s_preboot_cnt; /* 数组条目数 */
static osMessageQueueId_t s_queue; /* 运行期消息队列(syslog_mcu_init 创建) */
static osMessageQueueId_t s_queue; /* 运行期消息队列(syslog_drain 首次调用时惰性创建) */
static const osMessageQueueAttr_t s_queue_attr = { .name = "syslog" };
static volatile uint8_t s_fs_ready; /* 卷挂载 + /log 目录就绪后置位 */
/* 函数定义区 */
@@ -128,19 +131,17 @@ static int s_read_raw(syslog_id_t id, uint32_t idx, uint8_t *p_rec) {
}
/*
* 函数功能:日志引擎初始化(创建 FreeRTOS 消息队列)
* 函数功能:日志引擎初始化(内核启动前安全空操作)
* 入口参数:无
* 返回值:0 - 成功;-1 - 队列创建失败 int
* 限定条件:app_main_init() 起始处调用,先于任何 syslog_post()
* 返回值:0 - 成功 int
* 限定条件:app_main_init() 起始处调用(osKernelStart 之前);
* 不得调用任何 FreeRTOS API(内核对象须在内核启动后才可创建)
* 函数说明:启动前投递走 s_preboot 静态数组(syslog_post 按内核状态自动分流);
* FreeRTOS 消息队列由 syslog_drain 在运行期(defaultTask 上下文)惰性创建。
* 历史缺陷:此处曾 osMessageQueueNew 创建队列,早于 osKernelInitialize
* 提前拉起内核,其后任务创建在未完成初始化的内核状态上执行,导致启动失败
*/
int syslog_mcu_init(void) {
static const osMessageQueueAttr_t s_queue_attr = { .name = "syslog" };
s_queue = osMessageQueueNew(SYSLOG_QUEUE_MAX, sizeof(syslog_entry_t), &s_queue_attr);
if (s_queue == NULL) {
DBG_ERROR("queue create fail");
return -1;
}
return 0;
}
@@ -175,7 +176,7 @@ void syslog_mcu_mounted(void) {
}
/*
* 函数功能:排空待发日志并落盘(启动前数组 + 运行期队列,FIFO)
* 函数功能:排空待发日志并落盘(启动前数组 + 运行期队列,FIFO);首次调用时惰性创建运行期队列
* 入口参数:无
* 返回值:无
* 限定条件:仅 defaultTask(唯一写者)调用;卷未就绪时直接返回(条目滞留待重试)
@@ -183,6 +184,14 @@ void syslog_mcu_mounted(void) {
void syslog_drain(void) {
syslog_entry_t e;
/* 运行期惰性创建消息队列:本函数仅由 defaultTask(调度器运行中)调用,
保证内核对象创建发生在 osKernelStart 之后 */
if (s_queue == NULL) {
s_queue = osMessageQueueNew(SYSLOG_QUEUE_MAX, sizeof(syslog_entry_t), &s_queue_attr);
if (s_queue == NULL) {
DBG_ERROR("queue create fail");
}
}
if (!s_fs_ready || s_queue == NULL) {
return;
}