da66c500ea
B1 on-board closed loop surfaced a byte-level console interleave: before the console writer (defaultTask) registers, con_append() routes to dbg_console_write_raw() -> con_tx_bounded(), which is register-level polling with no mutual exclusion. adcTask logged every 1 ms, so its first-frame line collided with defaultTask's [NAND_FTL] init line and the required marker spanned two interleaved lines -> false FAIL. - console_log: add dbg_console_writer_ready() (returns s_con_writer_up) - adc_task: gate first-frame and 10 s stats logs on writer readiness; defer the first-frame report until the writer is up - docs: close B1/P1-1 in the registry; flip stale "remaining @test" notes; correct the console doc's obsolete "drop-only, no interleave" claim (that held for HAL gState, not register-level raw send) Bench (run_boot_test.py): VERDICT PASS, readback OK. adcTask frames/seq +10000 per 10 s = 1000 Hz, idle=0, frst_err=0; stack 496/2048 (75%). @build 0/0.
73 lines
3.8 KiB
C
73 lines
3.8 KiB
C
/*
|
||
* 模块名称:Console Single-Writer Logging — 控制台单写者日志(USART1 调试串口)
|
||
* 模块功能:调试控制台单写者环形缓冲的公共 API:所有任务/上下文(含 printf)只把
|
||
* 已格式化整行文本入环形缓冲,写者任务(defaultTask)为唯一
|
||
* HAL_UART_Transmit 发送点(行级原子 + 指针可控)
|
||
* 使用方法:
|
||
* 1. 生产者:DBG_ERROR/DBG_INFO/DBG_DEBUG 宏(dbg_log.h,内部用库 snprintf
|
||
* 有界格式化整行后调 dbg_console_write_line);或直接调 dbg_console_write_line
|
||
* 2. 写者任务:进入主循环前调 dbg_console_writer_attach() 注册为唯一发送者,
|
||
* 循环中周期调 dbg_console_drain() 排空(defaultTask 已接线,见 Src/freertos.c)
|
||
* 适用平台:STM32F407ZGTx(仅 MCU 端;模拟器不编译本模块——模拟器 DBG_*
|
||
* 直接映射 printf,见 simulator/dbg_log.h)
|
||
* 作者:王建锋
|
||
* 创建日期:2026-09-24
|
||
* 修改记录:
|
||
* 2026-09-24 王建锋 创建(自 Src/usart.c USER CODE 区迁出:
|
||
* HAL 库生成文件不得包含应用代码)
|
||
*/
|
||
|
||
#ifndef CONSOLE_LOG_H
|
||
#define CONSOLE_LOG_H
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
#include <stdio.h>
|
||
#include <stdint.h>
|
||
|
||
/*
|
||
* 单写者控制台 API(与 DBG_ENABLE 无关,任何构建都必须可见):
|
||
* dbg_console_write_line - 生产者入口:调用方已格式化好的整行文本一次入环形缓冲
|
||
* (刻意**不用**自研可变参数函数——规范 S12 7.6 禁止;格式化在
|
||
* DBG_PRINT 宏内用库 snprintf 完成)
|
||
* dbg_console_write_raw - 异常/早期路径:有界单次直发(不加锁)
|
||
* dbg_console_writer_attach- 写者任务(defaultTask)注册自己为唯一发送者
|
||
* dbg_console_writer_ready - 写者是否已注册(1=已注册)。供**周期性任务**在写者就绪前
|
||
* 抑制日志用:写者未注册时 con_append 走无锁直发路径
|
||
* (仅假设 defaultTask 在日志),其余任务此时落日志会与
|
||
* defaultTask 的存储初始化日志字节级交错(2026-10-10 台架实测)
|
||
* dbg_console_drain - 写者任务排空缓冲并发送(单次有界;TX 失败自动软复位自愈)
|
||
* dbg_console_dropped - 因缓冲满丢弃的行数(诊断)
|
||
* dbg_console_tx_fault - 因僵尸通道软复位自愈的次数(诊断)
|
||
* dbg_console_tx_fault_log_take
|
||
* - 取走"TX 故障待上报"标志(读后清)。**必须**由写者任务在
|
||
* dbg_console_drain() 之外调用后自行 syslog_post——本模块
|
||
* 刻意不调日志子系统,否则形成 write_line→con_append→drain
|
||
* →syslog_post→write_line 调用图成环,静态栈深全线虚高
|
||
*/
|
||
#define DBG_CON_LINE_MAX 192U /* 单行文本上限(含结尾 '\0',超出截断) */
|
||
int dbg_console_write_line(const char *line, unsigned len);
|
||
void dbg_console_write_raw(const char *buf, unsigned len);
|
||
void dbg_console_writer_attach(void);
|
||
uint8_t dbg_console_writer_ready(void);
|
||
void dbg_console_drain(void);
|
||
uint32_t dbg_console_dropped(void);
|
||
uint32_t dbg_console_tx_fault(void);
|
||
uint8_t dbg_console_tx_fault_log_take(void);
|
||
|
||
/*
|
||
* 函数功能:MicroLIB printf 底层重定向(C 库 retarget 钩子,须为全局符号)
|
||
* 入口参数:ch - 字符;f - 文件流(忽略)
|
||
* 返回值:原样返回 ch
|
||
* 限定条件:printf 调用点执行(任意任务上下文);字节交单写者路径
|
||
*/
|
||
int fputc(int ch, FILE *f);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|
||
|
||
#endif /* CONSOLE_LOG_H */
|