hw-debug

star 1

嵌入式硬件调试专家技能,用于硬件环境下的问题诊断和调试。使用场景包括:串口通信调试、时序分析、逻辑分析仪使用、需要人工硬件操作的调试场景、硬件环境信息管理。当遇到与硬件交互、时序问题、或需要真实世界操作的调试任务时触发。

noodlefighter By noodlefighter schedule Updated 2/12/2026

name: hw-debug description: 嵌入式硬件调试专家技能,用于硬件环境下的问题诊断和调试。使用场景包括:串口通信调试、时序分析、逻辑分析仪使用、需要人工硬件操作的调试场景、硬件环境信息管理。当遇到与硬件交互、时序问题、或需要真实世界操作的调试任务时触发。

Hardware Debug

Overview

嵌入式硬件调试专家,专注于硬件环境下的调试工作。核心原则:与真实世界交互需要人工协助、时间因素对调试至关重要、优先使用本技能提供的方法。

角色强调(Role Definition):你是一名资深嵌入式系统工程师。你不仅精通代码,更深刻理解主机端(Host)与目标机(Target/Device)之间的时序解耦。你必须显式区分两端动作,并优先识别两端之间的时序竞态条件(Race Conditions)。

你必须默认以下事实成立:LLM 的 Token 生成与网络传输可能引入秒级延迟;而 MCU 的上电复位(POR)与 Bootloader 执行通常在毫秒级完成。任何“先触发、后监听”的分步操作都可能错失瞬态启动证据。

工作流程

1. 读取硬件环境

首先读取硬件环境信息:工程根目录的 AGENTS.hwenv.md 文件。

# 读取硬件环境配置
read AGENTS.hwenv.md

硬件环境文件应包含:

  • 硬件型号和规格
  • 连接方式(串口设备、JTAG、SWD等)
  • 工具配置(逻辑分析仪、示波器等)
  • 已知的硬件限制和注意事项
  • 上电/复位方法

2. 人工交互原则

核心原则:硬件调试需要与真实世界交互,当需要人工操作时必须暂停并提示用户。

需要人工操作的典型场景

  • 需要重新上电但文档未提供方法
  • 需要物理连接/断开硬件
  • 需要调整硬件跳线/开关
  • 需要更换硬件组件
  • 需要手动触发信号

提示格式

【需要人工操作】[具体操作内容]

示例:

【需要人工操作】请重新上电设备,然后让Agent继续工作

3. 运行环境与时序一致性检查(复位/上电/烧录前必做)

在执行任何涉及复位(reset)、**上电(power cycle)烧录(flash)**的操作前,先完成如下检查。

3.1 时序一致性检查清单

逐条回答以下问题:

  1. 我是否需要验证设备启动时的状态(例如 bootloader 日志、上电首包、启动瞬态引脚电平)?
  2. 如果我现在执行复位,在我的下一个工具(例如串口读取/逻辑分析仪)真正启动前,会流逝多少时间?
  3. 设备在这段时间内是否会输出关键数据?

若第 1 条和第 3 条任一为“是”,则判定存在竞态风险,不得采用“先复位、后监听”的顺序执行。

3.2 Host / Device 双端时序建模

  • Host 端动作:打开串口、启动逻辑分析仪、创建读取线程、清空缓冲区、开始保存日志。
  • Device 端动作:复位、上电、ROM/bootloader 输出、应用启动日志输出、瞬态 GPIO 翻转。

必须在计划中写明:

  • T_host_ready:监听器进入 Active 状态的时间点
  • T_device_event:设备关键事件(复位后首包/首个边沿)时间点
  • 目标关系:T_host_ready <= T_device_event

3.3 顺序重排规则(先听后动)

当存在竞态风险时,采用以下顺序:

  1. 先启动监听器并确认 Active(串口/逻辑分析仪)
  2. 再触发复位/上电/烧录后的自动复位
  3. 持续捕获直到越过启动窗口

推荐执行语句风格:

先监听,后触发;先证实 Active,再执行 reset/power-cycle/flash。

3.4 禁止模式

  • 禁止:先复位,再启动串口读取
  • 禁止:先上电,再临时打开逻辑分析仪
  • 禁止:在未估算启动窗口的情况下串行执行“触发事件 → 启动监听”

3.5 时序评估协议(Protocol: Timing Evaluation)

在执行任何涉及硬件交互的任务前(特别是复位、烧录、握手、上电),必须先启动 <Timing_Analysis> 思维链,并严格评估以下要素:

  1. 竞态条件(Race Condition):如果分步执行(例如先复位、再读串口),是否会因 Agent 反应延迟而错过目标机瞬态响应(如 Boot Log)?
  2. 上电稳定时间(Stabilization Time):目标芯片复位后,晶振起振、PLL 锁定、外设初始化需要多久(常见范围 10ms - 2s)?
  3. 读空判据(Empty Read Logic):串口读空究竟是“无数据输出”,还是“芯片尚未初始化完成”?一次读取是否足以得出结论?

执行决策规则:

  • 若存在瞬态日志/首包/首边沿捕获需求,默认判定为高竞态风险。
  • 若单次读取为空,禁止直接判定失败;必须进入轮询窗口继续观测。
  • 若无法证明 T_host_ready <= T_device_event,禁止执行触发类动作(reset/power-cycle/flash)。

3.6 强制约束:脚本化执行优先(Constraint: Scripting over Action)

<Timing_Analysis> 结论为“直接分步调用工具无法保证时序”,严禁直接调用原子工具(例如单次 read_serial)。

必须编写并执行 Python 脚本(可用 pyserial),且脚本至少包含以下逻辑:

  1. 并发/时序控制:一个线程/进程负责监听,另一个线程负责触发复位(RTS/DTR 或外部命令)。
  2. 轮询与超时(Polling with Timeout):不能只读一次;必须在 while 循环中持续读取,直到捕获特征码或达到预设 TIMEOUT(例如 5 秒)。
  3. 缓冲区管理:在正确时机管理输入缓冲,避免复位瞬间数据丢失;避免在关键窗口内不当清空缓冲区导致首包被丢弃。

推荐最小脚本行为准则:

  • 先启动监听并确认 Active;再触发复位;随后持续轮询读取并落盘。
  • 读取循环需包含短睡眠(如 10ms)与总超时上限,避免忙等和无限阻塞。
  • 输出中必须标记关键时间点(监听启动、复位触发、首包到达、超时结束)。

4. 时间因素处理

调试原则:硬件时序可能只出现在执行的一瞬间,无法通过有先后执行关系的命令去捕获。

解决方案

  1. 构建并行程序:同时启动多个监听进程
  2. 利用设备缓存:读取设备自带的缓存数据
  3. 持续捕获:使用逻辑分析仪持续捕获并分析

并行捕获示例

import subprocess
import threading

def capture_serial():
    """捕获串口数据"""
    # 串口捕获代码

def capture_logic_analyzer():
    """捕获逻辑分析仪数据"""
    # sigrok-cli 捕获代码

# 并行执行
t1 = threading.Thread(target=capture_serial)
t2 = threading.Thread(target=capture_logic_analyzer)
t1.start()
t2.start()

5. 调试方法优先级

优先使用本技能提供的方法

  • 优先串口调试 → 逻辑分析仪 → 其他工具
  • 遵循本技能中的最佳实践
  • 参考本技能的参考资料

串口调试

串口是开发过程首选的与硬件交互方式。

参考文档references/serial-debug.py

关键要点

  • 使用短超时(如 timeout=0.1)而非阻塞读取
  • 清空缓冲区后再发送数据
  • 分批读取避免丢失数据
  • 验证数据完整性

代码示例

import serial

# 打开串口(短超时模式)
ser = serial.Serial(port="/dev/ttyUSB1", baudrate=115200, timeout=0.1)

# 清空缓冲区
ser.reset_input_buffer()
ser.reset_output_buffer()

# 发送数据
test_data = b"Test Message"
ser.write(test_data)

# 读取数据(会等待最多100ms)
received = ser.read(len(test_data))

# 如果没读取完整,继续读取
if len(received) < len(test_data):
    remaining = len(test_data) - len(received)
    more_data = ser.read(remaining)
    received += more_data

# 验证数据
if received == test_data:
    print("✓ 数据一致")
else:
    print(f"⚠ 数据不匹配: 发送={test_data}, 接收={received}")

# 关闭串口
ser.close()

串口调试流程

  1. 确认串口设备ls /dev/ttyUSB*ls /dev/ttyACM*
  2. 打开串口:使用正确的波特率和超时设置
  3. 清空缓冲区:重置输入输出缓冲区
  4. 发送测试数据:发送已知模式的数据
  5. 读取响应:使用短超时方式读取
  6. 验证数据:对比发送和接收数据
  7. 关闭串口:清理资源

常见问题

问题 解决方法
设备未找到 检查 USB 连接,使用 lsusb 确认设备
权限错误 将用户添加到 dialoutuucp
数据丢失 增加超时时间,或使用多次读取
波特率不匹配 检查硬件配置,确认正确波特率

逻辑分析仪使用

当需要检测时序问题时,使用逻辑分析仪。

参考文档references/logic-analyzer.md

基础命令格式

sigrok-cli --driver dreamsourcelab-dslogic [OPTIONS]

推荐配置

对于 1KHz 方波信号

sigrok-cli --driver dreamsourcelab-dslogic \
    --config samplerate=100k:voltage_threshold=1.6-1.6 \
    --channels 0 \
    --time 1s \
    -o waveform.sr

参数说明

  • samplerate=100k:100kHz 采样率,每个周期 100 个采样点
  • voltage_threshold=1.6-1.6:CMOS 电平阈值
  • --channels 0:使用通道 0
  • --time 1s:捕获 1 秒数据(1000 个 1KHz 周期)

输出格式选择

格式 扩展名 用途
二进制 .bin 高速存储,最高效
位格式 .txt 人类可读的原始数据
CSV .csv 表格导入分析
Sigrok 会话 .sr 完整会话信息

时序分析工作流

  1. 连接逻辑分析仪:将探头连接到待测信号
  2. 配置捕获参数:根据信号频率选择采样率
  3. 设置触发器(可选):捕获特定事件
  4. 捕获数据:执行 sigrok-cli 命令
  5. 分析数据:使用 CSV 或二进制格式分析
  6. 验证时序:检查信号周期、占空比等

数据分析示例

计算占空比

cat waveform.csv | awk '
  /^1$/ {high++} /^0$/ {low++}
  END {
    duty = (high / (high + low)) * 100
    print "High:", high, "Low:", low
    print "Duty cycle:", duty "%"
  }'

统计高低电平数量

cat waveform.csv | grep -c "^1$"  # 高电平计数
cat waveform.csv | grep -c "^0$"  # 低电平计数

调试最佳实践

1. 问题隔离策略

  • 从简单开始:先测试基本功能(如串口回环)
  • 逐步增加复杂度:确认基础工作后,再测试复杂场景
  • 控制变量:一次只改变一个参数

2. 日志记录

记录关键信息

  • 每次操作的硬件状态
  • 串口发送/接收的原始数据
  • 逻辑分析仪捕获的数据文件
  • 人工操作的时间和内容

3. 失败处理

遇到失败时

  1. 记录失败的详细情况
  2. 回退到上一个已知正常状态
  3. 分析可能的失败原因
  4. 尝试最小化测试用例
  5. 必要时提示用户人工检查硬件连接

4. 持续捕获技术

对于瞬态问题,使用持续捕获:

# 持续捕获到二进制文件
sigrok-cli --driver dreamsourcelab-dslogic \
    --config samplerate=200k:voltage_threshold=1.6-1.6 \
    --config continuous=on \
    --channels 0 \
    --output-format binary \
    -o waveform_continuous.bin

调试脚本模板

创建可复用的调试脚本模板,参考以下结构:

#!/usr/bin/env python3
"""
硬件调试脚本模板
"""

import serial
import subprocess
import threading

class HardwareDebugger:
    def __init__(self, serial_port, baudrate):
        self.ser = serial.Serial(port=serial_port, baudrate=baudrate, timeout=0.1)

    def serial_test(self, test_data):
        """串口测试"""
        self.ser.reset_input_buffer()
        self.ser.reset_output_buffer()
        self.ser.write(test_data)
        received = self.ser.read(len(test_data))
        return received

    def close(self):
        """关闭资源"""
        if self.ser.is_open:
            self.ser.close()

if __name__ == "__main__":
    debugger = HardwareDebugger("/dev/ttyUSB1", 115200)
    # 执行调试逻辑
    debugger.close()

故障排除

串口相关问题

症状 可能原因 解决方法
设备未找到 USB 连接松动 检查物理连接,使用 lsusb
权限被拒绝 用户不在正确组中 sudo usermod -aG dialout $USER
数据乱码 波特率不匹配 检查并设置正确的波特率
无数据接收 超时时间太短 增加 timeout

逻辑分析仪相关问题

症状 可能原因 解决方法
设备未检测到 固件未加载 安装 sigrok-firmware-dreamsourcelab-dslogic
捕获数据全 0 电压阈值错误 调整 voltage_threshold 参数
采样率不满足 信号频率过高 提高采样率或降低信号频率
权限错误 用户不在 usbmon 组 sudo usermod -aG usbmon $USER

Resources

references/

  • serial-debug.py - 串口调试示例代码(短超时回环测试)
  • logic-analyzer.md - DSLogic 逻辑分析仪使用完整指南

scripts/

可添加自动化调试脚本,如:

  • 自动化串口测试脚本
  • 逻辑分析仪数据转换脚本
  • 并行捕获脚本

assets/

可添加调试模板、示例数据文件等。


重要提醒

  • 任何需要人工操作时,必须先提示用户
  • 时间敏感的调试需要并行捕获
  • 优先使用本技能中的方法和参考资料
  • 遵循硬件环境文件中的配置和限制
Install via CLI
npx skills add https://github.com/noodlefighter/hw-debug-skill --skill hw-debug
Repository Details
star Stars 1
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator
noodlefighter
noodlefighter Explore all skills →