2. RTOS日志基础
在RTOS环境中,日志系统与通用Linux或桌面系统有本质差异:RAM通常只有几十KB到几百KB,没有文件系统或仅有极简文件系统,任务栈空间有限,且日志代码本身不能长时间关中断或阻塞高优先级任务。因此,理解日志等级、格式、同步/异步输出与缓冲机制,是设计产品级日志系统的第一步。
一、日志等级:从“全开”到“只留错误”
日志等级是日志系统的第一道过滤网。常见等级从高到低为:ERROR、WARN、INFO、DEBUG、TRACE。等级越高,表示事件越严重、越需要保留;等级越低,表示信息越详细、越适合开发阶段使用。
在RTOS中,等级通常通过编译期宏和运行期变量双重控制。编译期宏用于裁剪代码体积,运行期变量用于现场动态调整。例如:
#define LOG_LEVEL_ERROR 0
#define LOG_LEVEL_WARN 1
#define LOG_LEVEL_INFO 2
#define LOG_LEVEL_DEBUG 3
#define LOG_LEVEL_TRACE 4
#ifndef LOG_COMPILE_LEVEL
#define LOG_COMPILE_LEVEL LOG_LEVEL_INFO
#endif
extern uint8_t g_log_runtime_level;
#define LOG_E(tag, fmt, ...) \
do { if (LOG_LEVEL_ERROR <= LOG_COMPILE_LEVEL && \
LOG_LEVEL_ERROR <= g_log_runtime_level) \
log_output(LOG_LEVEL_ERROR, tag, fmt, ##__VA_ARGS__); } while(0)
这样,量产固件可把LOG_COMPILE_LEVEL设为LOG_LEVEL_WARN,只保留警告和错误;现场调试时再通过串口命令把g_log_runtime_level临时调到LOG_LEVEL_DEBUG,无需重新烧录。
二、日志格式:时间、等级、模块、内容
一条可读的RTOS日志通常包含四个字段:时间戳、等级、模块标签、消息体。时间戳可以来自SysTick、硬件定时器或RTC;模块标签用于区分驱动、协议栈、应用任务;消息体则承载具体参数和状态。
常见格式如下:
[ 12345][I][NET ] dhcp bound, ip=192.168.1.20
[ 12402][W][UART] rx overrun, drop=3
[ 12510][E][FS ] mount fail, err=-2
格式设计要兼顾可读性与解析效率。若日志需要上位机自动解析,建议采用固定宽度字段或结构化前缀,例如tick|level|tag|msg,避免在中断上下文中使用浮点格式化或动态内存分配。
三、同步与异步输出:阻塞与丢包的权衡
同步输出指调用LOG_I()后立即完成串口、SEGGER RTT或ITM的写入。优点是时序准确、实现简单;缺点是当输出外设慢于日志产生速度时,会阻塞当前任务,甚至在高优先级任务中造成实时性抖动。
异步输出指日志先写入环形缓冲区,由低优先级日志任务或DMA后台搬运到外设。优点是调用快、对实时任务影响小;缺点是缓冲区满时需要选择丢包、覆盖或阻塞策略,且日志时间戳可能略晚于实际事件。
四、缓冲机制:环形缓冲区与多级缓冲
RTOS日志最常用的缓冲结构是单生产者单消费者环形缓冲区。生产者可能是多个任务或ISR,消费者是日志输出任务。写入时只移动写指针,读取时只移动读指针,配合临界区或原子操作即可实现无锁或轻量锁。
当单级缓冲不足时,可采用多级缓冲:第一级为ISR专用的短缓冲,第二级为任务级环形缓冲,第三级为DMA搬运缓冲。这样既能保证中断响应,又能平滑突发日志流量。
五、常见RTOS日志方案对比
不同RTOS和工具链提供了不同层次的日志能力。下表从输出方式、实时性、资源占用和适用场景四个维度进行对比:
| 方案 | 输出方式 | 实时性影响 | 资源占用 | 适用场景 |
|---|---|---|---|---|
| printf 重定向 UART | 同步阻塞 | 高,可能阻塞任务 | 低 | 裸机或极简RTOS调试 |
| SEGGER RTT | 异步,J-Link 读取 | 低 | 中,需J-Link | 开发阶段高速日志 |
| ARM ITM / SWO | 异步,调试器读取 | 低 | 低,需SWO引脚 | Cortex-M 开发调试 |
| 自建环形缓冲 + 日志任务 | 异步,可配UART/Flash | 低,可控制丢包 | 中,需RAM和任务栈 | 产品级现场日志 |
| Flash 日志文件系统 | 异步,掉电保存 | 中,写Flash耗时 | 高,需Flash和FS | 黑匣子、故障回溯 |
六、案例与误区复盘
某工业网关项目在量产初期频繁出现“任务看门狗复位”,排查发现日志宏在中断中直接调用printf,而串口波特率仅115200,一条80字节日志耗时约7ms,导致高优先级控制任务被延迟。整改方案是:ISR只把日志写入256字节环形缓冲,日志任务以最低优先级搬运,缓冲区满时丢弃DEBUG级别日志,保留ERROR和WARN。整改后看门狗复位消失,现场仍能通过ERROR日志定位故障。
总结来说,RTOS日志基础可以归纳为四句话:等级分层过滤,格式固定可解析,异步缓冲保实时,方案选型看场景。只有把等级、格式、同步/异步和缓冲机制配合好,日志系统才能在不破坏实时性的前提下,成为产品现场诊断的可靠依据。