修复上电启动失败:日志消息队列改为内核启动后惰性创建
This commit is contained in:
+21
-12
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user