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 时序一致性检查清单
逐条回答以下问题:
- 我是否需要验证设备启动时的状态(例如 bootloader 日志、上电首包、启动瞬态引脚电平)?
- 如果我现在执行复位,在我的下一个工具(例如串口读取/逻辑分析仪)真正启动前,会流逝多少时间?
- 设备在这段时间内是否会输出关键数据?
若第 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 顺序重排规则(先听后动)
当存在竞态风险时,采用以下顺序:
- 先启动监听器并确认 Active(串口/逻辑分析仪)
- 再触发复位/上电/烧录后的自动复位
- 持续捕获直到越过启动窗口
推荐执行语句风格:
先监听,后触发;先证实 Active,再执行 reset/power-cycle/flash。
3.4 禁止模式
- 禁止:先复位,再启动串口读取
- 禁止:先上电,再临时打开逻辑分析仪
- 禁止:在未估算启动窗口的情况下串行执行“触发事件 → 启动监听”
3.5 时序评估协议(Protocol: Timing Evaluation)
在执行任何涉及硬件交互的任务前(特别是复位、烧录、握手、上电),必须先启动 <Timing_Analysis> 思维链,并严格评估以下要素:
- 竞态条件(Race Condition):如果分步执行(例如先复位、再读串口),是否会因 Agent 反应延迟而错过目标机瞬态响应(如 Boot Log)?
- 上电稳定时间(Stabilization Time):目标芯片复位后,晶振起振、PLL 锁定、外设初始化需要多久(常见范围 10ms - 2s)?
- 读空判据(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),且脚本至少包含以下逻辑:
- 并发/时序控制:一个线程/进程负责监听,另一个线程负责触发复位(RTS/DTR 或外部命令)。
- 轮询与超时(Polling with Timeout):不能只读一次;必须在
while循环中持续读取,直到捕获特征码或达到预设TIMEOUT(例如 5 秒)。 - 缓冲区管理:在正确时机管理输入缓冲,避免复位瞬间数据丢失;避免在关键窗口内不当清空缓冲区导致首包被丢弃。
推荐最小脚本行为准则:
- 先启动监听并确认 Active;再触发复位;随后持续轮询读取并落盘。
- 读取循环需包含短睡眠(如 10ms)与总超时上限,避免忙等和无限阻塞。
- 输出中必须标记关键时间点(监听启动、复位触发、首包到达、超时结束)。
4. 时间因素处理
调试原则:硬件时序可能只出现在执行的一瞬间,无法通过有先后执行关系的命令去捕获。
解决方案:
- 构建并行程序:同时启动多个监听进程
- 利用设备缓存:读取设备自带的缓存数据
- 持续捕获:使用逻辑分析仪持续捕获并分析
并行捕获示例:
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()
串口调试流程
- 确认串口设备:
ls /dev/ttyUSB*或ls /dev/ttyACM* - 打开串口:使用正确的波特率和超时设置
- 清空缓冲区:重置输入输出缓冲区
- 发送测试数据:发送已知模式的数据
- 读取响应:使用短超时方式读取
- 验证数据:对比发送和接收数据
- 关闭串口:清理资源
常见问题
| 问题 | 解决方法 |
|---|---|
| 设备未找到 | 检查 USB 连接,使用 lsusb 确认设备 |
| 权限错误 | 将用户添加到 dialout 或 uucp 组 |
| 数据丢失 | 增加超时时间,或使用多次读取 |
| 波特率不匹配 | 检查硬件配置,确认正确波特率 |
逻辑分析仪使用
当需要检测时序问题时,使用逻辑分析仪。
参考文档: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 | 完整会话信息 |
时序分析工作流
- 连接逻辑分析仪:将探头连接到待测信号
- 配置捕获参数:根据信号频率选择采样率
- 设置触发器(可选):捕获特定事件
- 捕获数据:执行 sigrok-cli 命令
- 分析数据:使用 CSV 或二进制格式分析
- 验证时序:检查信号周期、占空比等
数据分析示例
计算占空比:
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. 失败处理
遇到失败时:
- 记录失败的详细情况
- 回退到上一个已知正常状态
- 分析可能的失败原因
- 尝试最小化测试用例
- 必要时提示用户人工检查硬件连接
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/
可添加调试模板、示例数据文件等。
重要提醒:
- 任何需要人工操作时,必须先提示用户
- 时间敏感的调试需要并行捕获
- 优先使用本技能中的方法和参考资料
- 遵循硬件环境文件中的配置和限制