.. _jlink_flash_tool: ==================================== J-Link 烧录工具 ==================================== 通过 SEGGER J-Link 仿真器经 JTAG 通道对 ARCS / VenusA 芯片的 flash 进行烧录、擦除和回读。 与 :ref:`cskburn ` 的串口烧录互为补充:日常烧录用串口更快,J-Link 适用于串口 不可用、无法进入 BOOT 模式,或需要精确控制擦写范围、读回 flash 内容的场景。 .. note:: J-Link **调试**\ (GDB、断点、单步)不在本文档范围内,见 :ref:`gdb_debug`。 两者共用同一套 J-Link 环境与接线。 **所需资产:** 随 ``arcs-sdk`` 仓库提供,位于 ``tools/jlink/`` —— 设备描述 XML、各芯片 Flashloader、JLinkScript,均来自芯片原厂。 **所用工具:** ``JLinkExe``,由 SEGGER J-Link 软件包提供,纯命令行无 GUI 依赖。 前置条件 ======== 1. 已安装 J-Link 软件(推荐 V7.98 及以上) 2. 已完成设备描述部署: .. code-block:: bash mkdir -p ~/.config/SEGGER/JLinkDevices cp -r tools/jlink/. ~/.config/SEGGER/JLinkDevices/ 3. 已按 cJTAG 接线:SWCLK-PA00 / SWDIO-PA01 / GND / **VTref-3.3V** .. important:: ``JLinkExe`` **只从** ``~/.config/SEGGER/JLinkDevices/`` 读取设备描述,不支持 ``-JLinkDevicesXMLPath`` 参数,也不读取当前工作目录。仓库中的 ``tools/jlink/`` 仅是\ **部署源**\ ,不拷贝到该目录则无法使用。 完整的环境安装与接线说明见 :ref:`gdb_preparation`。 基本语法 ======== 所有操作通过 ``JLinkExe`` 完成。JLinkExe 是交互式程序,命令经\ **标准输入**\ 送入, 推荐用 here-document 书写,可读性最好: .. code-block:: bash JLinkExe -NoGui 1 -Device VENUSA -IF cJTAG -Speed 4000 -AutoConnect 1 \ -JTAGConf -1,-1 \ -JLinkScriptFile ~/.config/SEGGER/JLinkDevices/scripts/jtagscan0.JLinkScript <<'EOF' loadbin build/helloworld.bin 0x30000000 verifybin build/helloworld.bin 0x30000000 exit EOF ARCS 芯片把 ``-Device`` 换成 ``ARCS`` 即可,其余相同。 .. important:: ``-JTAGConf -1,-1`` **不能省。** JLinkExe 连接时会交互式询问 .. code-block:: text Device position in JTAG chain (IRPre,DRPre) : -1,-1 => Auto-detect 该参数用于预先应答(``-1,-1`` 即自动探测)。不加时,**标准输入的第一行会被当作 这个提问的答案吃掉。** 那条命令就不会执行——现象是命令看似正常结束却没有任何效果。 .. warning:: **不要使用** ``-CommanderScript`` **参数。**\ 它不会应答上述交互提问,进程会一直 挂起直到超时。 参数说明: .. list-table:: :header-rows: 1 :widths: 32 68 * - 参数 - 说明 * - ``-Device`` - 芯片短名,``ARCS`` 或 ``VENUSA``。\ **不要用长名**\ ,如 ``ListenAI ARCS`` 会卡死 * - ``-IF cJTAG`` - 接口固定 cJTAG,不能用 ``JTAG`` 或 ``SWD`` * - ``-Speed 4000`` - 固定 4000 kHz,不要用自适应速率 * - ``-JLinkScriptFile`` - **必填**\ 。烧录一律用 ``jtagscan0``,即 TAP0 * - ``-USB <序列号>`` - 接了多个探针时指定。查询:``echo ShowEmuList | JLinkExe -NoGui 1`` Flash 烧录 ========== 1. 基本烧录 ----------- .. code-block:: bash JLinkExe -NoGui 1 -Device VENUSA -IF cJTAG -Speed 4000 -AutoConnect 1 \ -JTAGConf -1,-1 \ -JLinkScriptFile ~/.config/SEGGER/JLinkDevices/scripts/jtagscan0.JLinkScript <<'EOF' loadbin build/helloworld.bin 0x30000000 verifybin build/helloworld.bin 0x30000000 exit EOF 烧录后会自动执行 ``verifybin`` 独立校验。成功输出: .. code-block:: text Erasing flash [100%] Done. Programming flash [100%] Done. J-Link: Flash download: Program & Verify speed: 38 KB/s Verify successful. .. important:: **成功判定看** ``Verify successful``。 若 flash 内容与待写数据完全一致,J-Link 会跳过擦写并输出 ``Skipped. Contents already match``,此时\ **没有** ``Programming flash`` 字样, 但这是正常优化而非失败。 2. 读取 flash ------------- .. code-block:: bash JLinkExe -NoGui 1 -Device VENUSA -IF cJTAG -Speed 4000 -AutoConnect 1 \ -JTAGConf -1,-1 \ -JLinkScriptFile ~/.config/SEGGER/JLinkDevices/scripts/jtagscan0.JLinkScript <<'EOF' savebin backup.bin 0x30000000 0x1000000 exit EOF 烧录前用它做整片备份,是最可靠的回退手段。 3. 擦除 ------- .. code-block:: bash JLinkExe -NoGui 1 -Device VENUSA -IF cJTAG -Speed 4000 -AutoConnect 1 \ -JTAGConf -1,-1 \ -JLinkScriptFile ~/.config/SEGGER/JLinkDevices/scripts/jtagscan0.JLinkScript <<'EOF' erase 0x30100000 0x30120000 exit EOF 擦除后该区间回读应为全 ``0xFF``。 4. 完整工作流程 --------------- .. code-block:: bash # 步骤 1:备份现有固件 JLinkExe $JL <<'EOF' savebin backup.bin 0x30000000 0x1000000 exit EOF # 步骤 2:烧录新固件并校验 JLinkExe $JL <<'EOF' loadbin app.bin 0x30000000 verifybin app.bin 0x30000000 exit EOF # 步骤 3:复位并运行 JLinkExe $JL <<'EOF' r g exit EOF # 步骤 4:如需回退,从备份恢复后同样需要复位 JLinkExe $JL <<'EOF' loadbin backup.bin 0x30000000 exit EOF JLinkExe $JL <<'EOF' r g exit EOF 其中 ``$JL`` 为公共参数,建议先定义一次: .. code-block:: bash JL="-NoGui 1 -Device VENUSA -IF cJTAG -Speed 4000 -AutoConnect 1 -JTAGConf -1,-1 \ -JLinkScriptFile $HOME/.config/SEGGER/JLinkDevices/scripts/jtagscan0.JLinkScript" (``JLinkExe`` 的完整参数见上文"基本语法") .. important:: **烧录后必须复位,固件不会自动运行。** ``loadbin`` 会隐式执行 reset & halt 把内核停住,烧完 flash 后内核仍处于 halt 状态。此时板子看起来"没反应",容易被误判成烧录失败。 ``r`` 复位、``g`` 让内核继续运行,两条缺一不可。 .. tip:: 若通过串口日志确认固件是否启动,注意 **接入 J-Link 后串口设备号会变** —— J-Link 自身会注册一个 CDC ACM 设备占用 ``/dev/ttyACM0``,目标板会顺延到 ``/dev/ttyACM1``。辨认方法: .. code-block:: bash for d in /dev/ttyACM*; do n=$(basename $d); p=$(readlink -f /sys/class/tty/$n/device); \ echo "$d $(cat $p/../idVendor)"; done # 1a86 = 目标板串口 1366 = J-Link 另外只在启动时打印一次的固件(如 helloworld),需\ **先打开串口再执行复位**\ , 否则会错过输出。 与串口烧录的取舍 ================ .. list-table:: :header-rows: 1 :widths: 18 41 41 * - - 串口(cskburn) - J-Link * - 命令 - ``./tools/burn/cskburn -C venusa -s /dev/ttyACM0 0x0 xxx.bin`` - ``JLinkExe $JL <<'EOF'`` … ``loadbin xxx.bin 0x30000000`` * - 速度 - 快,3 Mbps - 约 38 KB/s * - 前置条件 - 需进入 BOOT 模式,串口未被占用 - 需探针与 cJTAG 接线 * - 擦除粒度 - 按分区 - 任意区间 * - 读回 flash - 支持 - 支持 * - 适用场景 - **日常烧录首选** - 串口不可用、精确擦写、配合调试会话 .. tip:: 两者互为备份。串口进不去 BOOT 模式时用 J-Link;J-Link 操作后目标核被留在 halt 状态导致程序不运行时,用 ``./tools/burn/cskburn -C -s --chip-id`` 可复位芯片恢复运行(串口通路独立于 J-Link)。 常见问题 ======== 1. 设备名无法识别 ----------------- .. code-block:: text The selected device "VENUSA" is unknown to this software version. ``tools/jlink/`` 未拷贝到 ``~/.config/SEGGER/JLinkDevices/``,或拷贝不完整。 按前置条件重新部署。 2. 命令卡死不返回 ----------------- .. warning:: **不要使用** ``-CommanderScript`` **参数**——它不会应答 J-Link 的交互式 IRPre/DRPre 提问,进程会一直挂起直到超时。 使用 here-document 传入命令,并加上 ``-JTAGConf -1,-1`` 预先应答该提问。 若命令看似正常结束却没有任何效果(如 ``savebin`` 未生成文件),通常是漏了 ``-JTAGConf -1,-1`` —— 标准输入的第一行被当作提问的答案吃掉了。 3. 强杀 J-Link 进程后出现异常 ----------------------------- 若上一次会话被超时强杀,探针可能残留异常状态,随后出现 ``Could not start CPU core``、``JTAG communication error``、 ``cJTAG is not supported by the connected probe``、USB 反复重新枚举等现象。 这些是\ **偶发的残留效应,并非稳定故障**\ 。处理顺序: 1. 直接重试,通常即恢复 2. 目标核被留在 halt 导致程序不运行 → ``cskburn --chip-id`` 复位芯片 3. 探针仍不响应 → 拔插 USB(虚拟机下需重新直通) .. tip:: 遇到这类报错先重复 2~3 次确认是否稳定复现,不要当作真实缺陷排查。 4. 烧录速度慢 ------------- J-Link 经 cJTAG 烧录实测约 38 KB/s,属正常水平。对速度敏感时改用串口 cskburn。 5. 其他连接问题 --------------- 探针识别不到、``CPU-TAP not found in JTAG chain``、目标掉线等问题, 与调试场景共通,见 :ref:`gdb_debug` 的常见问题一节。 .. _jlink_assets: 资产说明 ======== ``tools/jlink/`` 是芯片原厂 J-Link 资产在 SDK 内的镜像,来源为 ``soc/arcs/hal`` 子模块的 ``tools/flash_tool/`` 与 ``tools/scripts/jlink/``: .. code-block:: text tools/jlink/ ├── JLinkDevices.xml 设备描述,已裁剪为 ARCS + VenusA ├── Devices/Arcs/flashloader.elf ARCS 烧写算法 ├── Devices/Venusa/flashloader.elf VenusA 烧写算法 ├── scripts/jtagscan0.JLinkScript TAP0(AP 核) ├── scripts/jtagscan1.JLinkScript TAP1(CP 核) ├── program_readme.txt 原厂附带,Windows/Eclipse 下用 JFlash 的说明 └── program_howto_1.png / program_howto_2.png / debug_howto.png .. note:: **设备描述与烧写算法必须保持一致。** 若 ``JLinkDevices.xml`` 声明了 某颗芯片,但 ``Devices/`` 下缺少对应的 Loader 文件,J-Link 启动时会弹出 ``Device: : Flash bank 0x...: No loader specified`` 错误——即使你要调试的 是另一颗芯片也照弹。增删芯片时两边务必同步。 .. note:: 原厂 XML 中 ``Loader`` 路径写作小写 ``flashloader.elf``,而原厂磁盘文件名为 大写 ``Flashloader.elf``。Windows 不区分大小写无影响,**Linux 下会找不到 Flashloader**。入库时已将文件名统一改为小写与 XML 一致,因此拷贝到 ``~/.config/SEGGER/JLinkDevices/`` 即可直接使用,无需额外重命名。 .. warning:: 若此前用过旧版教程的 OSS 分发包(``ListenAI.xml`` + ``ListenAI/ARCS.FLM``), 请先清空 ``~/.config/SEGGER/JLinkDevices/`` 再拷贝。J-Link 会读取该目录下所有 XML,两套共存会使 ARCS 被定义两次且 WorkRAM 配置矛盾,行为不可预期。