4. Log分析工具入门:常用串口工具(Putty/SecureCRT)、Log抓取与保存、时间戳对齐

在嵌入式 HAL 驱动调试中,串口(UART)是最基础、最可靠的调试信息输出通道。掌握串口工具的使用、Log 抓取与保存方法,以及时间戳对齐技术,是进行高效 Log 分析的前提。本节将系统介绍常用串口工具的特性、配置要点与实战技巧。

4.1 常用串口工具对比与选型

嵌入式调试领域最常用的两款串口终端工具是 PuTTY 和 SecureCRT。下表从多个维度对比两者的核心差异:

对比维度 PuTTY SecureCRT
授权方式 免费开源 商业付费(试用期有限)
串口支持 原生支持 Serial 连接 原生支持 Serial 连接,配置更丰富
Log 自动保存 需手动开启“Logging”功能 支持 Session 自动记录 Log
会话管理 单会话,配置保存在注册表 多会话管理,支持文件夹分组
脚本支持 有限(仅命令行参数) 支持 VBScript / Python 脚本
时间戳功能 需额外配置或第三方插件 内置时间戳选项,支持多种格式
适用场景 快速调试、临时连接 长期调试、自动化测试、团队协作
选型建议: 对于初学者或临时调试任务,PuTTY 完全够用;对于需要长时间抓取 Log、多会话管理或自动化脚本的复杂调试场景,推荐使用 SecureCRT。

4.2 串口工具配置要点

无论使用哪款工具,串口参数配置必须与目标板 UART 设置完全一致。以下为典型配置参数:

  • 波特率(Baud Rate): 常用 115200、921600,需与驱动代码中 HAL_UART_Init() 的 BaudRate 字段匹配。
  • 数据位(Data Bits): 通常为 8 位。
  • 停止位(Stop Bits): 通常为 1 位。
  • 校验位(Parity): 通常为 None。
  • 流控(Flow Control): 通常为 None。
PuTTY 配置示例:
打开 PuTTY → 选择 "Serial" 连接类型 → 输入串口号(如 COM3)→ 设置 Speed 为 115200 → 在左侧 "Serial" 分类中确认 Data Bits=8, Stop Bits=1, Parity=None, Flow Control=None → 保存 Session。

4.3 Log 抓取与保存方法

Log 抓取的核心目标是 完整、连续、不丢行 地记录所有串口输出。以下是两种工具的 Log 保存配置:

4.3.1 PuTTY Log 保存

  1. 在 PuTTY 配置界面左侧选择 "Logging"。
  2. 选择 "Printable output" 或 "All session output"。
  3. 指定 Log 文件路径(支持 &Y、&M、&D、&T 等时间变量)。
  4. 勾选 "Flush log file more frequently" 以减少缓存丢失。

4.3.2 SecureCRT Log 保存

  1. 打开 Session 选项 → "Log File" 选项卡。
  2. 勾选 "Start logging upon connection"。
  3. 设置 Log 文件路径与命名规则。
  4. 在 "Advanced" 中勾选 "Append to file" 和 "Include timestamp in log"。
避坑提示: 抓取 Log 时,务必确保串口工具的缓冲区足够大(如 SecureCRT 的 "Scrollback buffer" 设置为 5000 行以上),否则在高速输出时可能丢失早期 Log 行。

4.4 时间戳对齐技术

时间戳对齐是 Log 分析中最关键的环节之一。它允许我们将 Log 中的每一行与系统时间或外部参考时间关联,从而精确定位事件发生的先后顺序和间隔。

4.4.1 时间戳对齐的三种方式

方式 原理 精度 适用场景
工具侧时间戳 串口工具在接收 Log 时自动添加 PC 端时间 毫秒级(受串口延迟影响) 快速定位、粗略时序分析
目标板时间戳 嵌入式代码在 Log 输出时打印系统滴答(SysTick)或 RTC 时间 微秒级(取决于时钟源) 精确时序分析、中断延迟测量
混合对齐 工具侧时间戳 + 目标板时间戳交叉验证 高精度 复杂故障排查、多板同步

4.4.2 目标板时间戳实现示例

在 HAL 驱动中,通常使用 HAL_GetTick() 获取系统滴答时间,并将其格式化后随 Log 输出:

#include "main.h"

void debug_log(const char *fmt, ...) {
    va_list args;
    char buffer[256];
    uint32_t tick = HAL_GetTick();  // 获取系统滴答(单位 ms)

    // 格式化时间戳前缀
    int len = snprintf(buffer, sizeof(buffer), "[%lu.%03lu] ",
                       tick / 1000, tick % 1000);

    // 格式化用户消息
    va_start(args, fmt);
    vsnprintf(buffer + len, sizeof(buffer) - len, fmt, args);
    va_end(args);

    // 通过串口输出
    HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), 1000);
}

4.5 时间戳对齐流程

下图展示了从 Log 抓取到时间戳对齐的完整流程:

时间戳对齐流程 时间戳对齐流程 串口工具抓取 原始 Log 流 工具侧时间戳 目标板时间戳 混合对齐 对齐后的 Log 说明: 工具侧时间戳:由串口工具在接收时添加,精度受串口延迟影响。 目标板时间戳:由嵌入式代码在 Log 输出时打印,精度更高。 混合对齐:结合两者优势,适用于高精度时序分析场景。

4.6 时间戳对齐实战技巧

  • 工具侧时间戳配置: SecureCRT 中可在 "Log File" 选项卡勾选 "Include timestamp in log",格式建议选择 [YYYY-MM-DD HH:MM:SS.mmm]。
  • 目标板时间戳精度提升: 使用 DWT_CYCCNT 寄存器(Cortex-M 内核)获取 CPU 周期计数,可实现纳秒级时间戳。
  • 对齐验证: 在 Log 开头和结尾分别打印一个已知时间点(如 SystemClock_Config() 完成时的 SysTick 值),与工具侧时间戳对比,验证对齐精度。
  • 常见问题: 如果工具侧时间戳与目标板时间戳出现固定偏移,通常是由于串口驱动中的发送缓冲延迟导致,可在代码中增加 __DSB() 指令强制刷新写缓冲。
实战案例: 某摄像头预览卡顿问题中,通过目标板时间戳发现 ISP 处理线程每帧耗时从 28ms 突增到 45ms,而工具侧时间戳仅显示整体延迟。混合对齐后定位到是 DMA 传输完成中断被更高优先级中断抢占导致,最终通过调整中断优先级解决。

4.7 本章小结