大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是 JLink Script 文件基础及其在 IAR 下调用方法。

 

JLink 可以说是 MCU 开发者最熟悉的调试工具了,相比于其他调试器(比如 DAPLink、ST-LINK、I-jet 等),JLink 除了性能强大之外,还胜在其配套各种软件小工具相当方便易用。JLink 工具玩得熟的老司机一定在 J-Link Commander 命令行工具(即 \SEGGER\JLink_Vxxx\JLink.exe)下敲过命令,读写内存、下载文件、操控内核无所不能。这个底层工具其实也是 JLink 精华所在,今天痞子衡要讲的 JLink Script 文件主题其实就是依赖这个工具。

 

 

一、JLink Script 作用

如果你有脚本语言经验(比如 Python),你应该很熟悉脚本语言那一套规则,脚本语言不同于一般编译型语言(比如 C),编译型语言经过编译链接生成的二进制机器码被 CPU 直接识别执行,但脚本不需要预编译,它是由配套解释器动态翻译执行的,而 CPU 负责执行的是脚本解释器。

 

基于上述概念 JLink.exe 就是一个解释器,它能解释执行 JLink Script 文件,其命令格式如下,使用 -JLinkScriptFile 参数指定 JLink Script 文件路径便可执行 JLink Script 文件里的语句。

 

  • 命令格式:JLink.exe -JLinkScriptFile MyFile.JLinkScript

 

为什么需要 JLink Script 文件?有些情况下,需要定制 J-Link 执行的某些操作,比如 J-Link 连接顺序或者执行复位的方式等,或者一些定制的硬件板需要一些特殊处理,这些动作没法直接集成到 J-Link 软件的通用处理里,因此需要被放在单独的 JLink Script 文件里,根据连接的具体目标对象来指定加载执行。

 

  • Note:其实除了常见的明文脚本(.JLinkScript)文件之外,JLink Script 文件还有另外一种经过预编译的文件形式(.pex),这种格式是纯二进制的,可以保护脚本内容。

 

二、JLink Script 文件基础

JLink Script 这一套东西整体上由五大部分组成:基本语法、全局 DLL 变量、全局 DLL 常量、系统 API 接口、用户自定义动作集。

 

2.1 脚本基础语法

JLink Script 并不是一个通用的脚本语言,因此其并不像你熟知的那些 Python 之类的脚本语言那样语法完善,它仅是为了配合 JLink 完成一些必要操作。JLink Script 语法跟 C 语言类似,支持 C 语言中允许的大多数语句(if else,while,变量声明,…),但不是所有的语句。

 

此外,还有一些语句是特定于 JLink Script 的,JLink Script 已经尽可能允许最大的灵活性,因此几乎任何必要的目标初始化操作都可以得到支持。

 

  • 语法简明手册:https://wiki.segger.com/J-Link_script_files#Script_file_language

 

2.2 全局 DLL 常 / 变量

JLink Script 在被解释执行时,其实是和 JLink DLL(即 \SEGGER\JLink_Vxxx\JLinkARM.dll)联动的,DLL 里存放了 JLink 各种底层功能集合,同时也默认预定义一些全局变量,这些变量用于 DLL 配置,需要在 JLink Script 中被赋值。比如最基础的变量 CPU,用于指示连接的目标内核类型,而支持的全部 CPU 类型都定义在全局常量里。

 

  • 变量列表:https://wiki.segger.com/J-Link_script_files#Global_DLL_variables 常量列表:https://wiki.segger.com/J-Link_script_files#Global_DLL_constants

 

2.3 系统内置的 API 接口

JLink DLL 中实现了很多基础操作功能,这些功能通过 API 函数接口形式开放给 JLink Script 来调用,这些 API 全部以 JLINK_ 为前缀。举一个比较常用的 API 函数 JLINK_TARGET_Halt(),这个函数功能就是挂起目标内核。

 

  • API 接口列表:https://wiki.segger.com/J-Link_script_files#Script_file_API_functions

 

2.4 用户可自定义动作集

终于要讲到 JLink Script 最关键的部分了,前面都是基础,而 JLink Script 最核心的功能其实在用户自定义动作集合里,这些动作由 JLink 预先定义,但是内部具体操作可由用户来编写。在 IDE 在线下载调试过程中按规定触发条件来调用执行这些动作,下表列出了全部动作,其中蓝框标出的四个动作最常用。

 

  • InitTarget():替换 J-Link DLL 的目标 CPU 自动查找过程。对于默认情况下不可访问且需要执行一些特殊步骤才能成功执行常规调试连接过程的目标 CPU 非常有用。SetupTarget():在 InitTarget()以及 JLink 常规调试连接序列之后被调用,通常用于更高级别的 CPU 调试设置,如写入某些内存位置、初始化 PLL 以加快下载速度等。ResetTarget():替换 DLL 的复位策略。无论在 DLL 中选择了什么复位类型,如果存在此函数,将调用它而不是 DLL 内部复位。AfterResetTarget():在 ResetTarget()之后调用。复位结束后,用于初始化一些必要外设(比如看门狗)。除此之外,对于某些内核类型有必要在复位后执行一些特殊操作,以保证复位后的设备功能正常。

 

 

  • 自定义动作列表:https://wiki.segger.com/J-Link_script_files#Customizable_actions

 

三、JLink Script 在 IAR 下调用方法

单纯的 JLink Script 没有意义,需要和工具链配合使用才能发挥最大作用,除了 SEGGER 工具之外(Embedded Studio、Ozone、SystemView),JLink Script 还可以和常见的 IDE 环境(IAR/Keil/Eclipse)一起工作,痞子衡以 IAR 为例介绍三种调用 JLink Script 的方法(使用的是恩智浦 i.MXRT685-EVK 开发板做的测试)。

 

3.1 JLinkDevices.xml 中指定

第一种方法是在 \SEGGER\JLink_Vxxx\JLinkDevices.xml 文件中指定,如果你对这个文件不了解,可先回顾下痞子衡之前写的文章 《串行 NOR Flash 下载算法(J-Link 工具篇)》。

 

给板卡通上电,连上 J-Link 调试器,随便打开一个测试工程(\SDK_xxx_EVK-MIMXRT685\boards\evkmimxrt685\demo_apps\hello_world\iar),选择 flash_debug,将其工程选项做如下更改:

 

  1. 设置内核为 Cortex-M33,即不启用 Device 里的 NXP MIMXRT685S_CM33 设置调试器选择 J-Link/J-Trace,且不要勾选 Use flash loader(s)

 

 

这么做是为了在 IAR 下载时不用 NXP MIMXRT685S_CM33 默认指定的 JLink 下载算法,而弹出一个框让用户主动选择合适的 JLink 下载算法,我们修改 JLinkDevices.xml 如下:

 

  • Note:\SEGGER\JLink_Vxxx\Devices\NXP\iMXRT6xx_UFL\iMXRT6xx_CortexM33.JLinkScript 便是我们要测试的 JLink Script,在里面我们可以加一句 JLINK_SYS_Report("J-Link script: This UFL script comes from Segger package"); 便于检查调用结果。

 

 

选好 MIMXRT685_UFL 这个指定下载算法后,直接在 IAR 里点击下载,进入正常调试后,可以在 Debug Log 里看到 iMXRT6xx_CortexM33.JLinkScript 确实被调用了。

 

 

3.2 工程选项 Debugger/Extra Options 中指定

在上一小节测试基础上,将 JLinkDevices.xml 里的 JLinkScriptFile="Devices/NXP/iMXRT6xx_UFL/iMXRT6xx_CortexM33.JLinkScript" 这一句去掉,即不在下载算法里直接调用 JLink Script。然后将 iMXRT6xx_CortexM33.JLinkScript 文件拷贝一份放到 \SDK_xxx_EVK-MIMXRT685\boards\evkmimxrt685\demo_apps\hello_world\iar 目录下,并在 IAR 工程选项中做如下设置:

 

  • Note:\SDK_xxx_EVK-MIMXRT685\boards\evkmimxrt685\demo_apps\hello_world\iar\iMXRT6xx_CortexM33.JLinkScript 便是我们要测试的 JLink Script,在里面我们可以加一句 JLINK_SYS_Report("J-Link script: This UFL script comes from Extra Option"); 便于检查调用结果。

 

 

再次在 IAR 里点击下载,进入正常调试后,可以在 Debug Log 里看到新的 iMXRT6xx_CortexM33.JLinkScript 确实被调用了。

 

 

3.3 工程目录 settings 文件下指定

在上一小节测试基础上,不勾选 IAR 工程选项 Extra Options 中 Use command line options。然后将 iMXRT6xx_CortexM33.JLinkScript 文件拷贝一份放到 \SDK_xxx_EVK-MIMXRT685\boards\evkmimxrt685\demo_apps\hello_world\iar\settings 目录下,需要重命名 JLink Script 文件与测试工程名一致:

 

  • Note:\SDK_xxx_EVK-MIMXRT685\boards\evkmimxrt685\demo_apps\hello_world\iar\settings\hello_world_flash_debug.JLinkScript 便是我们要测试的 JLink Script,在里面我们可以加一句 JLINK_SYS_Report("J-Link script: This UFL script comes from settings"); 便于检查调用结果。

 

 

再次在 IAR 里点击下载,进入正常调试后,可以在 Debug Log 里看到 hello_world_flash_debug.JLinkScript 确实被调用了。

 

 

至此,JLink Script 文件基础及其在 IAR 下调用方法痞子衡便介绍完毕了,掌声在哪里~~~