打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
U-Boot 之二 详解使用 eclipse + J-Link 进行编译及在线调试

  在上一篇博文 U-Boot 之一 零基础编译 U-Boot 过程详解 及 编译后的使用说明 中,最后使用阶段遇到了一些错误,然后发现不能调试(靠打印信息)实在是难受,就开始摸索如何调试 U-Boot,于是就有了这篇博文。

  找了一下网上现有的资料,直接使用 GDB 命令行调试是一个选择,但是明显效率不高。于是开始探索直接使用 eclipse 对 U-Boot 进行编译及调试。发现网上有不少说明文章,但大多数都太老旧了,因此我决定重新整理一篇,使用的当前最新的工具环境如下:

  1. Ubuntu 20.04.3
  2. Eclipse IDE 2021-12 R Packages Eclipse IDE for Embedded C/C++ Developers
  3. U-boot 2021.10
  4. J-Link_Linux_V760b_x86_64.deb

下载安装 eclipse

  首先从官网下载最新的针对嵌入式 C/C++ 的 tar 包(现在 eclipse 针对不同开发环境提供了不同的包,我记得之前并没有分开):Eclipse IDE for Embedded C/C++ Developers,地址:https://www.eclipse.org/downloads/packages/release/2021-12/r/eclipse-ide-embedded-cc-developers,然后进行安装(解压):


解压之后,我们在 /opt/eclipse/eclipse 目录(我这里先建立了 eclipse 文件夹导致多了一级,大家可以直接解压到 /opt)下直接双击运行 eclipse 程序即可。这里我们直接下载嵌入式专用的版本,主要是出于以下几点:

  1. 根据官网提示 “The Eclipse Installer 2021‑12 R now includes a JRE for macOS, Windows and Linux.” ,我们不用再安装 Java 运行时 了。解压后直接使用就可以了。
  2. 包含了一些嵌入式使用的插件(例如 J-Link、OpenOCD 等调试插件 ),这省了我们在去安装这些插件。例如,选择 Eclipse IDE for C/C++ Developers,然后去安装各种插件。

进一步,我们可以选择建立一个 eclipse 的快捷方式,方便后续启动:

  1. 新建 sudo gedit /usr/share/applications/eclipse.desktop
  2. 输入以下内容:
    [Desktop Entry]
    Encoding=UTF-8
    Name=Eclipse
    Comment=Eclipse IDE
    Exec=/opt/eclipse/eclipse/eclipse
    Icon=/opt/eclipse/eclipse/icon.xpm
    Terminal=false
    StartupNotify=true
    Type=Application
    Categories=Application;Development;
    
  3. 赋予执行权限 sudo chmod u+x /usr/share/applications/eclipse.desktop
  4. 以上步骤之后我们就可以在桌面最左下角的菜单中找到 eclipse 了。当然还可以在进一步,将 /usr/share/applications/eclipse.desktop 复制到桌面,然后赋予执行权限(应该是还需要右键鼠标,选择 Allow Launching)。

附 tar 命令:

 # 压缩
 tar -czvf ***.tar.gz
 tar -cjvf ***.tar.bz2
 # 解压缩
 tar -xzvf ***.tar.gz
 tar -xjvf ***.tar.bz2
 # 参数
-c  :建立一个压缩档案的参数指令(create 的意思);
-x  :解开一个压缩档案的参数指令!
-t  :查看 tarfile 里面的档案!特别注意,在参数的下达中, c/x/t 仅能存在一个!不可同时存在!因为不可能同时压缩与解压缩。
-z  :是否同时具有 gzip 的属性,亦即是否需要用 gzip 压缩
-j  :是否同时具有 bzip2 的属性,亦即是否需要用 bzip2 压缩
-v  :压缩的过程中显示档案!这个常用,但不建议用在背景执行过程!
-f  :使用档名。注意,在 f 之后要立即接档名,不要再加参数!例如使用『 tar -zcvfP tfile sfile 』就是错误的写法,要写成『 tar -zcvPf tfile sfile 』才对!
-p  :使用原档案的原来属性(属性不会依据使用者而变)
-P  :可以使用绝对路径来压缩!
-N  :比后面接的日期(yyyy/mm/dd)还要新的才会被打包进新建的档案中!

下载安装 J-Link 驱动

  这个就相当简单了,SEGGER 提供了安装包,直接从 https://www.segger.com/downloads/J-Link/ 下载对应的的 linux 的安装包(例如我的 Ubuntu 对应 64-bit DEB Installer),然后双击安装就可以了。安装之后默认位置是 ./opt/SEGGER 目录下。


里面的可执行程序都没有对应的桌面图标,运行后在左侧的工具栏上也是黑乎乎的。使用时直接使用命令行或者到目录下双击对应的可执行程序即可。

配置 eclipse

  eclipse 的配置分为全局、工作区、项目,优先级前者最低后者最高(后者会覆盖前者)。对于一些通用的配置(例如我们安装的 J-Link 驱动,无论工作区还是项目,应该都用一个),eclipse 推荐直接在全局或者工作区中配置,项目直接继承使用全局或工作区的配置就可以了。 启动 eclipse 会提示选择工作区,默认可以选择不再提示。


启动之后,直接 菜单 --> Window --> Preferences 打开配置界面,我们主要是配置更改 MCU 这个目录(这个好像是由于我们用的嵌入式版 eclipse 自带了 CDT 插件才有这个)下的内容,其他的配置项则根据自己的需要自行修改即可。具体如下:

我这里仅仅配置了编译工具链和 J-Link 的安装位置。之所以这里选择对全局配置项进行配置,主要还是方便在后续建立项目之后,项目自动继承这些配置,方便减少很多操作。

  这里再次说明,由于我们选择的是嵌入式专用的 eclipse(Eclipse IDE for Embedded C/C++ Developers ),因此,我们不需要安装 CDT 插件等操作。否则光是配置 eclipse 内容就挺多!

安装 CMSIS-Packs

  CMSIS Pack 是 ARM 为 Cortex-M 核定义的一个规范,是一种有效的封装技术,目前支持近 9000 种不同的微控制器。它们为软件组件、设备参数和评估板支持提供了一种交付机制。软件包(文件集合)包括:

  • 源代码、头文件和软件库
  • 文档和源代码模板
  • 设备参数以及启动代码和编程算法
  • 示例工程

  用过 MDK-ARM(Keil)的应该很熟悉,这个东西不仅可以在 MDK-ARM(Keil)中使用,现在 eclipse、IAR 都集成了 CMSIS Pack,通过 CMSIS Pack 我们可以在线安装一些芯片的包。

   这里我们之所以安装 CMSIS Pack(确切的说是安装 CMSIS Pack 中提供的芯片的包),是因为从中我们可以获取到芯片的 SVD 文件,而 SVD 文件中记录了芯片中各种外设的寄存器,在调试时非常有用!如果不使用 SVD 文件,调试器将无法获取芯片中外设的寄存器,只能显示 ARM 核中的几个寄存器。

   eclipse 中安装非常简单,但是由于访问的是国外的服务器,速度相当慢(那些包都挺大的),而且经常出现某些芯片下载不下来报错。如果出现报错直接选择忽略即可。具体操作如下图所示:


  CMSIS Pack 的安装位置可以在 菜单--> Window-->Preferences --> C/C++ --> MCU Packages 下找到及更改。查看其中的内容,其实就是 Keil 中的那一套东西,因此一种变通的方法是将下载好的内容直接放到上面的目录中即可。SVD 文件就位于 CMSIS-Packs\Keil\STM32F7xx_DFP\2.14.1\CMSIS\SVD 目录下。

注意,上面的这个目录应该是个隐藏文件夹!

编译 U-Boot

新建项目

  准备好以上环境及工具之后,就可以直接建立项目了,对于 U-Boot ,我们选择 Makefile Project with Existing Code。我这里把步骤尽量把步骤合并到一张图,以节约篇幅。具体步骤如下图所示:


  其中,我们选择的编译工具链是 Arm Cross GCC。这里的选择主要是让 eclipse 能够主动使用适合我们的一些配置。如果选择其他的,后续也可以再次进行更改(步骤会多一些)。

注意,如果选择在配置章节说的已经在配置了全局或者工作区,下面有些配置其实可以不用更改。我这里就以没有配置来进行演示(覆盖全局配置),对于全局配置有影响的地方单独说明一下。

  点击 Finish 之后,默认在选择的源代码目录下新建两个(隐藏)文件:.cproject.project,这两个就是 eclipse 记录的项目配置信息文件(我之前以为会和 Windows 上的一些软件(例如 vs)似得放到选择的工作区目录下,要不然我选择工作区干啥!)。

项目配置

  点击右键菜单最下面的 Properties (也可以通过 菜单 --> Project --> Properties)之后,就打开了项目的配置页面,接下来就是更改一些项目专用的配置了。下面我们一步步说明需要做哪些更改:

  1. 新增环境变量。具体操作如下图所示:


    环境变量下原有的两个 CMDPWD 我们不用管它(PATH 变量默认也应该有,不知为何我这里没有)。我们最终需要新增三个环境变量 ARCHCROSS_COMPILEPATH(如果没有的话),其中, ARCHCROSS_COMPILE 就是我们使用命令行编译时指定的。PATH 主要是告诉 eclipse 我们是用的工具的位置。
      这里需要特殊注意 PATH 的值。我们需要先通过上面的 Variables 找到系统 PATH 变量,然后点击 OK,此时,eclipse 就会导入系统环境变量的值。我们需要编辑它,在其中添加我们自己的编译工具链位置(我这里是 /usr/share/gcc-arm-none-eabi-10.3.2021.10/bin,注意,bin 目录不止一个),否则在编译时会提示找不到相关工具。注意,如果在上面说的全局设置中已经添加了编译器的路径,这里不用再次添加。 最终添加后如下所示:

    我们添加的编译器路径用于让 eclipse 找到编译器,其他原有的系统环境变量可以让 eclipse 找到 make 程序。此外,最下面的 Append xxx 这句不要去掉。

  2. 更改我们使用的编译工具链以及选择使用的芯片。


    如果没有配置全局编译器路径,这里必须单独配置;如果设置了这里就会自动读取全局设置的编译工具链,查看一下是否正确即可。如果这里选择了芯片,在调试的时候会省略一些配置。

  3. [可选] 不使用 CDT 内建的编译工具链的相关设置(因为我们更换了编译工具链),注意,这里不更换也没啥问题!

  4. 新增我们自己的编译工具链的头文件路径。每一个编译工具链下都会有 include 文件夹用来存放编译器使用的各种头文件。需要注意的是, include 可能会有好几个,最好都添加上。如果在全局中配置了编译器路径,eclipse 就会自动识别指定的编译工具的相关头文件,这里就可以不用设置。

  5. [可选] 开启并行编译。就是指定 make -jn 参数(n 根据处理器来定) 。eclipse 配置如下:

  6. [可选] 增加 make stm32f769-disco_defconfig步骤。完整的构建 U-Boot 的步骤中,第一步是生成 .config 文件,而后是 make menuconfig,最后才是 make。如果不添加到 eclipse ,则需要先用命令行执行以上步骤,否则 eclipse 会提示错误。


    具体添加如下:

    之后,我们就可以在 菜单 --> Project --> Build Targets --> Build 中直接点击上面的配置,执行这一步了。

  7. [可选] 修改 make clean。默认情况下,我们执行 Clean 时,使用是 make clean,而我们编译 U-Boot 一般使用 make distclean。这个是 eclipse 默认的设置,我们可以通过如下位置进行修改:


    此外,还可以参考第 6 步中新建一个 Build Targets,只是使用起来没有上面这个方式简单。我第 6 步的图示中已经建立好了!

编译

经过以上步骤,完整的 U-Boot 编译环境就搭建好了,接下来就可以在 eclipse 中构建 U-Boot 了。

调试 U-Boot

J-Link 连接开发板

  调试之前肯定是先把 J-Link 连接到开发板(开发板上有个 20 针脚的 JTAG/SWD 调试接口),确保连接正确。测试连接具体可以使用我们安装的 J-Link 驱动里相应的工具:JFlashExe,新建一个 STM32F769 芯片的项目,然后连接一下:


提示 Connected successfully 即可。

eclipse 调试相关配置

  连接没有问题之后,接下来就是配置 eclipse 了:菜单 --> Run --> Debug Configuration...,总的来说配置并不麻烦,我这里使用是 J-Link,因此,选择 GDB SEGGER J-link Debugging,然后点击上面的新建图标(或者直接双击 GDB SEGGER J-link Debugging)就会出现一个新的配置,具体步骤如下图所示:


  需要注意的就是选择 C/C++ Application 这一项,我们需要从众多执行程序中选择出我们最终需要 u-boot(这个是最终编译出的带调试信息的,不是 u-boot.bin。具体见博文U-Boot 之三 U-Boot 源码文件解析及移植过程详解)。接下来就是配置界面中剩下的DebuggerStartupSourceCommonSVD Path 这 5 个 Tab 页面内容,下面我直接上图来说明每个页面需要的配置:

  1. MainDebuggerStartup

    如果已经在全局配置中设置了J-Link 的路径,这里默认是会自动读取全局的配置的 J-Link,不用更改也可以。当然这里再选择一下肯定没有问题。芯片类型如果在构建时选择了芯片,这里也会自动填上选择的芯片。还有就是 Startup --> Setbreakpoint at: 这个默认是 mian,但是 U-Boot 默认没有 main,这里根据实际情况选择。直接 reset,简单粗暴!还有可以使用 _main
  2. SourceCommonSVD Path

    如果按照前面说的安装了 CMSIS-Packs,那么这里就可以找到对应芯片的 SVD 文件,选择 SVD 文件之后,我们在调试时就可以查看外设寄存器的值,否则将无法查看!如下图所示:

      注意,eclipse 寄存器分为两部分:Registers 窗口中是 ARM Cortex 核的寄存器(例如,R0、PC),Peripherals 下面就是我们的 SVD 文件中描述的外设寄存器。

U-Boot 调试修改

开启调试选项

  默认情况下,U-Boot 的编译已经进行了优化,且默认并不开启调试的,因此我们需要更改一下 U-Boot 的配置。第一个是需要取消 General Setup --> Optimise for size,在一个就是开启 General Setup --> Configure standard U-Boot features (expert users) -> enable debug information for tools,具体如下图所示:


  这里需要注意,如果使用 make distclean 会清理所有文件,这就会导致以上的配置被清理!所以除非必要,否则还是使用 make clean 好一些。目前来看 make menuconfig 这一步还是需要在终端中执行。

  警告:目前我在测试中发现,去掉 General Setup --> Optimise for size 可能导致程序无法运行,暂时没找到解决方法!我目前是在仅开启了 General Setup --> Configure standard U-Boot features (expert users) -> enable debug information for tools 的情况进行调试的。就是偶尔会出现断点位置不正确,不影响正常调试!

  这里有个比较严重的问题,去掉 General Setup --> Optimise for size 之后,会导致程序变大,从而原来默认的 SPL 的大小(0x8000)不能容纳实际 SPL 大小,进一步导致了 U-Boot 无法启动。因此,这里我们必须要修改 U-Boot 的基地址。目前,有如下地方需要修改(图里面的 stm32f769-eval 是我移植的,上文暂时还没有更换):

修改设备树配置

  接下来还有个问题:在启动调试之后,调试的程序在调试时只能执行一部分代码,此后就会失败,而且如果不调试想要直接运行是无法直接启动!具体现象如下图所示:


根本原因是由于调试的程序有没有设备树!默认情况下,U-Boot 的可执行程序是 bin 后拼接上 dtb 组成的,而我们调试的程序只有 bin,没有 dtb!解决方法如下有如下两种:

  • 将设备树直接编译进 U-Boot 的 bin 文件中,而不是将 设备树单独出来!U-Boot 本身就有这方面的配置,具体如下:

    如果执行过 make distclean 那么每次都需要重新配置上面的选项。
  • 在 eclipse 中指定设备树地址。如果使用的是 U-Boot 默认的分离设备树模式,那么在编译成功之后,会在源码的根目录下生成 u-boot.dtb ,这个就是设备数编译之后的文件,而我们可执行程序的结束地址可以从源码的根目录下的 u-boot.map 文件中的 __end 符号找到。

    有了 u-boot.dtb__end 之后,我们就可以在 eclipse 中通过命令来解决:

    如果 U-Boot 的可执行程序大小有变化,每次都需要更改这里!而且在刚开始启动调试时,eclipse 会报一个错误,稍等一会即可正常进入调试。

  经过以上两种方法的任意一种,再次启动调试时,就可以正常执行 board_inti_f 这个函数了!注意,由于这个函数里包含很多接口,执行速度可能有些慢!

重定位配置

  接下来的问题就是内存重定位,U-Boot 中存在一段内存重定位的代码,重定位之后将导致调试失败!这主要是因为,在重定位之后,eclipse 正确加载符号表中的各符号。


  目前,我还没有找到比较好的解决方法,官网推荐的方法是 使用 gdb 命令行来手动加载符号表 。命令非常简单:add-symbol-file u-boot 重定位后的地址。重定位后的地址就位于 gd 中的成员变量 unsigned long relocaddr; 中。

调试

  经过上面的配置之后,我们就可以使用 eclipse 对 U-Boot 进行调试了。这里需要注意的是,我们调试的如果是 U-Boot 本身,需要现将 SPL 烧写好,当然我们也可以调试 SPL。启动调试如下图所示:

参考

  1. https://boundarydevices.com/debugging-using-segger-j-link-jtag/
  2. https://www.cnblogs.com/humaoxiao/p/4166230.html
  3. https://m2m-tele.com/blog/2021/09/19/how-to-debug-u-boot/
  4. https://community.element14.com/products/devtools/single-board-computers/riotboard/b/blog/posts/automate-uboot-build-with-eclipse
  5. https://programmerclick.com/article/68662419084/
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
U-BOOT的启动流程及移植
利用Eclipse CDT建立 windows下面C++开发环境
windows 下 eclipse配置外部工具利用javah编译生成头文件
汇川PLC和PLC之间ModebusTCP通讯_汇川plcmodbustcp通讯_Big
U-boot介绍及编译的流程
使用jad及eclipse插件进行.class文件的反编译
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服