arcs-dev-tools
ARCS SDK 工具链
为 Claude Code 提供与 ARCS 硬件交互的工具链能力:拉取仓库、安装开发环境、编译、烧录、运行、日志读取。
本 skill 只负责工具链操作,不负责代码编写和理解。 代码开发、需求理解、bug 分析由 Claude Code 本身完成。
当前状态
本 skill 仍处于开发阶段。欢迎在使用过程中反馈:
- 复现稳定的 bug(最好附上命令输出/日志片段)
- 环境兼容性问题(发行版、Python 版本、串口设备类型等)
- 更好的"触发语句/使用示例"(请提交到仓库的
docs/文档中,避免放进 skill 包内)
已验证能力(已跑通)
- 运行某个 sample:模型自行定位示例 → 编译 → 烧录 → 读取日志 → 判定成功/失败
- UI 显示并迭代:模型先写一个在 UI 上显示一行字的示例 → 烧录运行 → 再修改文字内容 → 重新烧录并确认生效
使用示例
示例与触发语句见 <skill_dir>/references/usage.md(按需加载,避免主文件过长)。
批量模式
- 逐个串行执行 编译→烧录→验证(串口设备同一时间只能一个操作使用)
- 每个示例独立输出验证结果,最后汇总
- 某个失败不影响后续继续
默认配置
| 参数 | 默认值 | 说明 |
|---|---|---|
| BOARD | arcs_evb |
目标开发板 |
| 串口设备 | 动态扫描 | 每次操作前扫描 /dev/ttyACM* /dev/ttyUSB* |
| 烧录波特率 | 3000000 |
cskburn 波特率 |
| 串口波特率 | 921600 |
日志读取波特率 |
| 烧录起始地址 | 0x0 |
Flash 烧录偏移 |
| 仓库地址 | https://gitlab.example.com/listenai/arcs-sdk.git |
git clone 地址(需用户提供实际地址) |
核心原则:先确认非偶发,再处理
遇到异常现象时,必须重复验证 2-3 次确认是否稳定复现,再决定是否处理。
- 每次都复现 → 真实问题,返回给 Claude Code 处理
- 仅偶发 → 标记为环境因素,不作为代码问题
工具链操作
操作 1:拉取仓库
当用户的环境中还没有 arcs-sdk 仓库时执行。
# 克隆仓库(用户需提供实际的仓库地址)
git clone <仓库地址> arcs-sdk
cd arcs-sdk
git submodule update --init --recursive
- 如果用户未提供仓库地址,询问用户
- 如果仓库已存在,跳过此步骤,直接使用现有仓库
- 支持切换分支:
git checkout <branch>
操作 2:安装开发环境
首次使用或工具链缺失时执行。但必须先检查环境变量,用户可能已自行配置工具链路径。
优先检查环境变量:
# 检查用户是否已指定工具链路径
echo "NUCLEI_TOOLCHAIN_PATH=$NUCLEI_TOOLCHAIN_PATH"
echo "LISTENAI_TOOLS_PATH=$LISTENAI_TOOLS_PATH"
| 环境变量 | 含义 | 设置后跳过 |
|---|---|---|
NUCLEI_TOOLCHAIN_PATH |
用户指定的 RISC-V GCC 工具链路径 | 跳过 prepare_toolchain.sh |
LISTENAI_TOOLS_PATH |
用户指定的 listenai-tools 路径(cmake、ninja 等) | 跳过 prepare_listenai_tools.sh |
环境变量已设置时,不要运行对应的安装脚本,直接使用用户指定的路径。
仅当环境变量未设置时,才运行安装脚本:
# 1. 安装构建工具(仅当 LISTENAI_TOOLS_PATH 未设置时)
bash prepare_listenai_tools.sh
# 2. 安装 GCC 交叉编译工具链(仅当 NUCLEI_TOOLCHAIN_PATH 未设置时)
bash prepare_toolchain.sh
# 3. 确保 cskburn 有执行权限
chmod +x ./tools/burn/cskburn
检查项(按优先级):
- 若
NUCLEI_TOOLCHAIN_PATH已设置 → 检查$NUCLEI_TOOLCHAIN_PATH/bin/riscv64-unknown-elf-gcc是否可执行 - 若
LISTENAI_TOOLS_PATH已设置 → 检查$LISTENAI_TOOLS_PATH/cmake/bin/cmake是否可执行 - 若环境变量未设置 → 检查仓库内
listenai-dev-tools/下的对应路径 ./tools/burn/cskburn是否可执行
如果检查通过,跳过安装。
操作 3:编译
输入:项目路径(示例目录或用户自建项目目录)
输出:build/arcs.bin 固件文件,或编译错误信息
cd <项目目录>
bash ./build.sh -C -DBOARD=arcs_evb && bash ./build.sh -r -w -DBOARD=arcs_evb
build.sh 查找策略:
- 项目目录下有
build.sh→ 直接用 - 没有 → 用仓库根目录的
build.sh -S <项目相对路径>
编译失败时:
- 将完整错误输出返回给 Claude Code,由 Claude Code 分析并修改代码
- 查阅
<skill_dir>/references/knowledge.md对应 topic 看是否有已知解决方案 - Claude Code 修改代码后,再次调用本操作重新编译
确认编译产物:
- 在
build/下查找.bin文件 - 返回固件文件的完整路径和大小
ARCS 编译产物命名规则:
build/<name>.bin— 固件文件(用于烧录)build/<name>— ELF 文件(无后缀),用于 GDB 调试,包含调试符号- 例如:
build/helloworld.bin对应的 ELF 是build/helloworld - ELF 文件没有
.elf后缀,不要去找*.elf,直接用去掉.bin后的同名无后缀文件
ARCS 启动顺序与 build 目录结构:
芯片启动顺序:ROM_BOOT → AP 固件 (boot) → CP 固件 (应用)
如果 build/ 下存在 boot/ 子目录:
build/boot/boot.bin— AP 核心的 boot 固件build/boot/boot— AP boot 的 ELF(无后缀),debug AP 时用此文件build/<name>.bin— 已合并 boot 的完整固件(=boot.bin+ 应用 bin),直接烧录即可build/<name>.bin.without.boot— 不含 boot 的纯应用固件build/<name>— CP 应用的 ELF(无后缀),debug CP 时用此文件
GDB 调试时选择正确的 ELF:
- Debug AP (boot) → 用
build/boot/boot - Debug CP (应用) → 用
build/<name>
操作 4:烧录
输入:固件文件路径 输出:烧录成功/失败
烧录前:
# 动态扫描串口设备
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
# 确认无进程占用
fuser <串口设备> 2>/dev/null
执行:
# 必须使用仓库自带的 cskburn,必须带 -C arcs 参数
./tools/burn/cskburn -C arcs -s <串口设备> -b 3000000 0x0 <固件文件路径>
重要:必须使用
./tools/burn/cskburn(仓库根目录下),不要使用listenai-dev-tools/listenai-tools/cskburn/cskburn。 后者是通用版本,不支持-C arcs参数,缺少烧录前自动擦除步骤,会导致写入失败。
正常烧录输出示例:
Waiting for device...
Entering update mode...
Detected flash size: 16 MB
Erasing region 0x00000000-0x00021000...
Burning partition 1/1... (0x00000000, 130.88 KB)
130.88 KB / 130.88 KB (100.00%)
Resetting...
Finished
失败处理:
Failed opening device→ 板子未进入烧录模式,提示用户按 BOOT+RESET 进入烧录模式EBUSY→fuser找到占用进程,提示用户释放ETIMEDOUT→ 等 3 秒,重新扫描设备号,重试- 设备消失 → 等待后重新扫描
/dev/ttyACM* Failed burning partition: 01→ 检查是否误用了listenai-dev-tools中的 cskburn,换用./tools/burn/cskburn
操作 5:运行(日志读取)
输入:无(烧录完成后自动执行)或独立调用 输出:串口日志文本
使用 serial_read.py(技能自带脚本,纯 Python stdlib,零外部依赖):
python3 <skill_dir>/serial_read.py read <串口设备> -b 921600 -t <读取秒数>
兼容旧用法:不加
read子命令也可以(自动识别为 read 模式)。
<skill_dir>即本技能安装目录,与 SKILL.md 同级。
参数说明:
| 参数 | 默认值 | 说明 |
|---|---|---|
-b, --baudrate |
921600 |
波特率 |
-t, --timeout |
5 |
读取超时(秒) |
--dtr |
不传(拉低) | 传入则拉高 DTR |
--rts |
不传(拉低) | 传入则拉高 RTS |
特性:
- 非 TTY 环境兼容(
O_NOCTTY+select()非阻塞读取) - 默认拉低 DTR 和 RTS(通过
ioctl TIOCMBIC) - 打开后自动 flush 缓冲区,避免读到残留数据
- 实时输出到 stdout
串口问题处理:
- 乱码 → 确保波特率设置正确(921600),或等板子完全启动后再读
- 设备断连 → 关闭连接 → 等 2-3 秒 → 重新扫描设备 → 重连
- 无输出 → 先尝试操作 7 复位芯片,仍无输出则提醒用户检查连接或重新烧录
- 权限问题 → 确保用户在 uucp/dialout 组中
- 设备占用 → 读取前检查是否有其他进程占用(fuser <串口设备>)
日志返回给 Claude Code,由 Claude Code 判断程序是否正常运行。
操作 6:检查硬件连接(串口)
独立操作,可在任意时刻调用。
ls /dev/ttyACM* /dev/ttyUSB* 2>/dev/null
- 找到唯一设备 → 返回设备路径
- 找到多个 →
udevadm info识别后询问用户 - 找不到 →
lsusb+dmesg | tail -20后告知用户
操作 7:复位芯片
通过烧录串口的 DTR 信号复位芯片,无需手动按 Reset 键。
python3 <skill_dir>/serial_read.py reset <串口设备>
原理:拉高 DTR → 等待 0.5 秒 → 拉低 DTR,触发芯片硬件复位。
使用场景:
- 烧录后需要复位芯片重新启动
- 芯片卡死需要重启
- 调试过程中需要重新运行程序
复位后读日志的典型组合:
# 先复位,再立即读取启动日志
python3 <skill_dir>/serial_read.py reset <串口设备> && \
python3 <skill_dir>/serial_read.py read <串口设备> -b 921600 -t 5
操作 8:JLink 环境检测与部署
当用户需要通过 JLink 调试 ARCS 芯片时执行。详细步骤见 <skill_dir>/references/jlink-setup.md。
检测与部署流程:
- 检测 JLink 软件是否已安装(JLinkExe、JLinkGDBServerCLExe)
- 检测并部署 JLinkDevices 配置(
~/.config/SEGGER/JLinkDevices/Listenai.xml+Flashloader.elf) - 检测目标核心(AP/CP)并选择对应 JLink Script,告知用户当前调试的核心
- 动态检测 JLink 硬件序列号
- 执行连接测试(JLinkExe 纯 CLI 读取 flash 验证通畅,不要使用 JFlashExe 避免弹出 GUI)
核心选择:ARCS 双核(AP+CP),通过 build 目录 .config 中的 CONFIG_ARCS_AP_CORE/CONFIG_ARCS_CP_CORE 自动判断。Debug AP 用 jtagscan0,debug CP 用 jtagscan1,烧录/读 Flash 始终用 jtagscan0。
ARCS JLink 接线:PA01-SWDIO, PA00-SWCLK, GND, VTref(3.3V)。接口模式为 cJTAG (2-pin)。
资源文件:<skill_dir>/assets/jlink/ 下包含 Flashloader.elf、arcs.jflash 模板、JLinkScript 文件。
严禁违反以下三条,否则必定连接失败:
- 接口必须用
-if cJTAG,不能用-if JTAG或-if SWD- 必须加载 JLinkScript:
-JLinkScriptFile <skill_dir>/assets/jlink/jtagscan0.JLinkScript(或 jtagscan1),不带 JLinkScript 会报Could not connect to target- 设备名必须用
ARCS,不能用ListenAI ARCS
调试策略:JLink GDB 优先
当用户提到"debug"、"调试"、"断点"、"单步"、"崩溃"、"卡死"、"排查问题"等关键词时,优先使用 JLink GDB 调试,而非串口日志。
调试方法优先级
- JLink GDB 调试(首选)— 可设断点、单步执行、查看变量和寄存器、精确定位问题
- 串口日志读取(备选)— 仅当 JLink 环境不可用时使用
选择逻辑
用户提到 debug/调试/排查问题
→ 检查 JLink 环境是否就绪(操作 8)
→ 就绪 → 使用 JLink GDB 调试(流水线 C)
→ 未就绪 → 尝试部署 JLink 环境(操作 8)
→ 部署成功 → 使用 JLink GDB 调试
→ 无法部署(无 JLink 硬件等)→ 降级为串口日志(流水线 A/B)
→ 告知用户:"当前使用串口日志排查,建议连接 JLink 以获得更精确的调试能力"
常用流水线
流水线 A:运行现有示例
Claude Code 调用顺序:
- 检查硬件连接
- 定位示例目录,阅读 README 和源码(Claude Code 自己做)
- 编译(操作 3)
- 烧录(操作 4)
- 日志读取(操作 5)
- Claude Code 对比日志和预期输出,判断结果
流水线 B:编写新代码并验证
Claude Code 调用顺序:
- 检查硬件连接
- Claude Code 参考仓库中的示例和 API,编写代码
- 编译(操作 3)→ 失败则 Claude Code 改代码 → 重新编译(循环)
- 烧录(操作 4)
- 日志读取(操作 5)
- Claude Code 判断是否符合预期 → 不符合则改代码 → 回到步骤 3(循环)
流水线 C:JLink GDB 调试
当用户需要 debug/调试时,优先使用此流水线:
Claude Code 调用顺序:
- JLink 环境检测(操作 8)→ 未就绪则自动部署
- 编译(操作 3)→ 定位 ELF 文件:
build/<name>(无后缀,不是.elf),确认带调试信息(with debug_info, not stripped) - 检测目标核心(AP/CP)→ 选择对应 JLink Script
- 启动 JLinkGDBServer:
⚠️
-JLinkScriptFile是必填参数,缺少会导致CPU-TAP not found in JTAG chainJLinkGDBServerCLExe -device ARCS -if cJTAG -speed 4000 -port 2331 \ -USB <serial_number> -nogui -noir -nologtofile \ -JLinkScriptFile <jtagscan_script> &设备名必须用
ARCS,不能用ListenAI ARCS(会卡死) - GDB 连接并调试:
GDB 命令文件示例:<riscv-gdb> -batch -x <gdb_commands_file> <elf_file>set pagination off set confirm off target remote localhost:2331 monitor reset monitor halt load break main continue - 根据调试目标设置断点、单步执行、查看变量
- 调试完成后关闭 GDBServer 进程
经验知识库
文件:<skill_dir>/references/knowledge.md
按 6 个 topic 组织:仓库管理 / 环境安装 / 编译 / 烧录 / 串口 / JLink。遇到问题时只读对应 topic。
本文件由维护者手动维护,模型不要修改。
自优化 SKILL.md
发现应沉淀到 skill 的通用性问题时,不要直接修改 SKILL.md,告知用户,用户同意后再更新。
注意事项
- 本 skill 只做工具链操作:代码编写、需求理解、bug 分析由 Claude Code 本身完成
- 串口独占:烧录和日志读取不能同时使用同一串口
- 设备号动态扫描:每次操作前都扫描,不硬编码
- 异常先确认再处理:重复验证 2-3 次,确认非偶发后再处理
- 安全优先:不执行
rm -rf等危险操作 - 避免使用的方法:
- picocom/minicom: 在非交互式环境中无法正常工作(需要 TTY)
- pyserial: 需要额外安装 Python 包,在受限环境中可能不可用
- stty + cat: 在非 TTY 环境下会回显波特率,且无法控制 DTR/RTS 信号线