eclipse+gcc+jlink 配置与调试指南
eclipse+gcc+jlink 配置与调试指南
准备工具
Eclipse IDE for C/C++ Developers
下载链接:eclipse-cpp-2022-03-R-win32-x86_64.zip
注意:该版本为 win64 的 zip 版本,其他版本请依照官网提示下载, 若下载太慢尝试切换国内镜像下载。选择下图内 select another mirror 选项。关于 eclipse 的介绍这里不再展开。
arm-none-eabi-gcc
下载链接:gcc-arm-11.2-2022.02-mingw-w64-i686-arm-none-eabi.zip
该版本是基于 GCC11.2 的 gcc-arm-none-eabi 的 zip 版本,不要下载错了。GCC11 以上的版本可能是为了支持 64 位的 MCU,压缩包的体积超过 1G,加上官网在国外,下载会很慢。建议在官网下载 GCC10 以下的版本或者找一找国内其他人分享下载的网盘。
J-Link
略
安装教程
解压 eclipse-cpp-2022-03-R-win32-x86_64.zip,放在适当的位置,比如我放在 D:\Applications\eclipse
。然后双击 eclipse.exe 打开 IDE。点击 Help->Eclipse Markplace...,在首页搜索内输入 mcu 安装 Eclipse Embedded C/C++ 插件。
解压 gcc-arm-11.2-2022.02-mingw-w64-i686-arm-none-eabi.zip 到 eclipse 目录内。这里我并没有把 gcc 添加到环境变量里。
J-Link 安装教程略。
新建工程
点击 File->New->Project...->C/C++->C Project, 点击 next。
选择 Empty Project,Arm Cross GCC,点击 Next。
勾选 Debug 与 Release 选项,点击 Next。
选择编译及链接工具
然后在工程文件夹下建立 src 文件夹存放源代码、启动文件和链接文件。本教程使用的是 NXP 的 LPC845 的 MCU,直接复制准备好的源代码及链接文件。启动文件文件和链接文件可以从 NXP 官网下载的 SDK 中找到,一般放在 / SDK_2_11_0_LPC845/devices/LPC845/gcc 中。
编译工程
编译工程需要将启动文件的后缀. s 改为大写的. S,否则 eclipse 识别不到
点击工具链 Project->Properties,进行编译相关设置。
点击 C/C++ Build->Tool Chain Editor。工具链选择 ARM Cross Builder,构建工具选择 CDT Internal Builder。如果选择 Gnu Make Builder 需要另外安装 GNU make 工具,这里不展开描述。
点击 C/C++ Build->Settings->Tool Settings->Target Processor。LPC845 是 M0 + 的内核,所以 Arm family (-mcpu) 选择 cortex-m0plus,指令集 Instruction set 选择 Thumb (-mthumb)。
点击 C/C++ Build->Settings->Tool Settings->GNU Arm Cross C Compiler->Preprocessor。我是用的 NXP 的 SDK,编译需要添加 MCU 型号的宏 CPU_LPC845M301JBD48。
点击 C/C++ Build->Settings->Tool Settings->GNU Arm Cross C Compiler->Includes。添加头文件路径。
点击 C/C++ Build->Settings->Tool Settings->GNU Arm Cross C Linker->General 添加链接文件。
点击 C/C++ Build->Settings->Tool Settings->GNU Arm Cross C Linker->Miscellaneous。配置 newlib。注意: 使用 newlib 及 newlib-nano 库需自行实现_write, _exit 等 os 函数。为简单起见,如果我们不需要使用系统相关的函数,建议勾选 Do not use syscalls。TODO:实现 syscall 接口,参考 stm32CubeIDE 或者 MCUxpress IDE。
点击 C/C++ Build->Settings->Tool Settings->GNU Arm Cross Create Flash Image。选择生成 hex 文件或者 bin,此处只能 hex 和 bin 二选一。如果需要同时生成两者可以点击 C/C++ Build->Settings->Build Steps,设置编译完成后的步骤 (用于自动生成 bin 文件)。
命令行如下:
${cross_prefix}${cross_objcopy}${cross_suffix} -O binary ${BuildArtifactFileBaseName}.elf ${BuildArtifactFileBaseName}.bin
描述信息如下:
Creating a binary from the .elf file
至此 Debug 编译设置工作已经完成,请按照此操作完成 Release 编译设置。注意,在 Release 配置中加上 NDEBUG 的宏以区分 Debug 配置和 Release 配置(在 Release 中屏蔽断言)。点击 Project->Build Project 选项即可构建文件,在工程文件夹 Debug/Release 下找到对应的 bin,hex 和 elf 文件。
调试工程
安装芯片包
为了不分散放置各种配置文件,方便统一管理,我们重定向芯片包的位置到 eclipse 目录中。点击 Window->Preference->C/C++->MCU Packages,更新芯片包的位置。
在线更新芯片包数据:step 1:点击工具栏 pack 选项,进行在线安装。step 2:刷新芯片包定义。step 3:选择要安装的芯片包,右键点击 Install 进行安装。
因为大多数芯片包的数据服务器都在国外,国内在线安装芯片包太过缓慢,甚至会断开连接,所以在此分享离线安装步骤。解压 CMSIS-Packs 到 eclipse 目录中。(放到网上的文章就不分享 CMSIS-Packs 的本地数据了,读者可以跳过离线安装芯片包这一步。)
然后关闭 eclipse,并打开 cmd,跳转到 eclipse.exe 所在的位置。输入命令:eclipse.exe -clean
然后会看到 packs 界面出现了芯片包数据,同时在 .cahe 文件夹内,放入 keil 的芯片包再右键进行安装对应的芯片包,即可快速安装好对应的芯片包。然后回到 packs 界面右键安装即可。
设置工程所需芯片
点击 Project->Properties->C/C++ Build->Settings->Devices。
设置 J-Link 调试配置
点击 Run->Debug Configurations...,进行 Debug 相关设置
SVD 文件存放在芯片包中,直接在芯片包内查找即可, SDK 里面也有。需要注意的是 LPC845 的 SVD 文件是以 xml 结尾,具体文件名是 LPC845.xml。
上述步骤设置完成后,点击窗口右下角的 debug 即可开始调试。寄存器在界面的右方 peripheral 界面中。选择对应的寄存器在下方的 memory 选项卡中会出现对应的寄存器信息。
设置 OpenOCD + CMSIS-DAP 调试配置
关于 OpenOCD 和 CMSIS-DAP 网上有一大堆介绍,这里不再展开说明。官网有提供二进制文件 下载链接, 包括 xPack OpenOCD 项目的和官方在 Github 上的。也可以从 guntoolchains.com 下载二进制文件,下载下来的压缩包还提供 usb 驱动,使用起来很便利。多说一句,我使用的 CMSIS-DAP 是 v1 版本的,由于接口基于 HID 的,在 win10 上不需要另外安装驱动,即插即用。如果 CMSIS-DAP 是 v2 版本,是需要安装 winUSB 驱动的。
以官方在 Github 释放的二进制文件为例。下载压缩包后解压到 eclipse 目录内,重命名为 OpenOCD。打开 PowerShell,跳转到 OpenOCD,输入 bin/openocd.exe -s share/openocd/scripts/ -f interface/cmsis-dap.cfg -f target/lpc84x.cfg
会出现 Using CMSIS-DAPv2 的警告并出现写数据失败的错误。
PS D:\Applications\eclipse\OpenOCD> bin/openocd.exe -s share/openocd/scripts/ -f interface/cmsis-dap.cfg -f target/lpc84x.cfg
Open On-Chip Debugger 0.11.0 (2021-03-07-12:52)
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "swd". To override use 'transport select <transport>'.
cortex_m reset_config sysresetreq
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Warn : Using CMSIS-DAPv2 interface 1 with wrong class 10 subclass 0 or protocol 0
Info : Using CMSIS-DAPv2 interface with VID:PID=0x2e3c:0xf000, serial=4A159C010040054205971C02
Warn : could not claim interface: Operation not supported or unimplemented on this platform
Error: error writing data: Entity not found
Error: CMSIS-DAP command CMD_INFO failed.
PS D:\Applications\eclipse\OpenOCD>
如前文所说,我使用的是 CMSIS-DAPv1, 但是 OpenOCD 使用的是 CMSIS-DAP v2 的接口,所以出现了找不到入口的情况。查阅官方文档发现 OpenOCD 从 0.11.0 开始支持 CMSIS-DAPv2, 如果没有显式指定 CMSIS-DAP 版本的话会优先尝试 v2 接口,如果失败再尝试 v1 接口。然而从上面的报错情况来看 OpenOCD 尝试 CMSIS-DAPv2 失败之后就直接退出了,并没有尝试 CMSIS-DAPv1。所以我们需要显式指定使用 CMSIS-DAPv1 的接口,在 cmsis-dap.cfg 文件中增加 cmsis_dap_backend hid
指令即可:
#
# ARM CMSIS-DAP compliant adapter
#
# http://www.keil.com/support/man/docs/dapdebug/
#
adapter driver cmsis-dap
cmsis_dap_backend hid
# Optionally specify the serial number of CMSIS-DAP usb device.
#cmsis_dap_serial 02200201E6661E601B98E3B9
再次运行 OpenOCD 可以发现不会报错了,而且显示 CMSIS-DAP FW Version = 1.2.0。如果是从 guntoolchains.com 下载的 OpenOCD,就不需要显式指定使用 CMSIS-DAPv1。
接下来在 eclipse 中配置 OpenOCD。点击 Project->properfies->MCU->OpenOCD,选择 OpenOCD 的安装路径。
点击 Run->Debug configurations->GDB OpenOCD Debugging->New launch Configuration 建立新的 Debug 配置。可配置项如下:
OpenOCD 的可执行文件路径:D:\Applications\eclipse\OpenOCD\bin/openocd.exe
Config options: -s ${openocd_path}/../share/openocd/scripts -f interface/cmsis-dap.cfg -f target/lpc84x.cfg
然后配置 SVD 文件和选择要调试的 elf 文件。
配置完成。点击 Apply->Debug 进入调试。
其实到这里就已经可以用 OpenOCD+CMSIS-DAP 调试了。可是我又不想修改 cmsis-dap.cfg 文件, Debug 配置里的选项也有点长,干脆新建一个配置文件更清爽,修改 OpenOCD 的配置也更方便。首先将 cmsis-dap 恢复原状,然后在 OpenOCD 的 bin 目录中新建 openocd.cfg 文件,里面内容如下:
source [find interface/cmsis-dap.cfg]
cmsis_dap_backend hid
transport select swd
source [find target/lpc84x.cfg]
adapter speed 2000
lpc84x.cfg 实际用的是 lpc1xxx.cfg, 里面设定的速度是逆天的 10kHz,加载 elf 居然差不多要 1 分钟。所以在文件的末尾把 swd 的速度调 2MHz。最后把 Debug 设置里的 Config options 改成 -f ${openocd_path}/openocd.cfg
。
LPC845 校验和警告
注意到用 OpenOCD 调试 LPC845 时会出现如下的两条警告:
Warn : Boot verification checksum in image (0x00000000) to be written to flash is different from calculated vector checksum (0xefffb451).
Warn : OpenOCD will write the correct checksun. To remove this warning modify build tools on developer PC to inject correct LPC vector checksum.
这是因为 LPC 系列的 MCU 需要在中断向量表中写入 checksum 保证用户代码有效。原理可以查看 UM11029 (LPC84x User manual) 第 5.3.4 节 Criteria for Valid User Code。简单来说就是要在中断向量表第 7 个位置(0x0000001C)处写入 checksum,以保证中断向量表的前 8 个向量地址的值累加和为 0。注意,有些 MCU 的 checksum 是写在 0x00000014 的,实际的位置要看 MCU 的 User manual 或者仔细阅读 FAQ。我参考了 NXP 社区的 FAQ 后,具体做法如下:
第一步,修改启动文件 startup_LPC845.S 的中断向量表,将第 8 个向量地址从保留值 0 改成变量 Checksum
。
__Vectors:
.long __StackTop /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long NMI_Handler /* NMI Handler */
.long HardFault_Handler /* Hard Fault Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long Checksum /* LPC MCU Checksum */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long SVC_Handler /* SVCall Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long PendSV_Handler /* PendSV Handler */
.long SysTick_Handler /* SysTick Handler */
第二步,修改链接文件 LPC845_flash.ld,在末尾增加 Checksum
定义。至于为什么每个向量地址还要加 1?是因为对于 Cortex-M 处理器,向量表中向量地址的最低位需要置 1,用以表示这是 Thumb 代码。想要知道更多细节可以看看《Arm Cortx M0 M0+ 权威指南》这本书。
PROVIDE(__stack = __StackTop);
PROVIDE(Checksum = 0 - (__StackTop + (Reset_Handler + 1) + (NMI_Handler + 1) + (HardFault_Handler + 1)));
.ARM.attributes 0 : {*(.ARM.attributes) }
ASSERT(__StackLimit>= __HeapLimit, "region m_data overflowed with stack and heap")
Clean Project 之后再重新 Build Project 发现生成的 hex 文件在 0x0000001c 处的值不再是 0,用 OpenOCD 调试也不会有 Checksum 不符的警告。
本文参考: