整个学习过程是参考正点原子启明星开发板的2020.2版本嵌入式Linux开发指南,在学习uboot移植的时候遇到了问题。
新建工程和配置环境啥的和教程里都一样,就不罗嗦了,这里重点讲和教程不一样的地方(或者说教程里有问题的地方)。
新建工程后编译时遇到的报错
在按照教程新建uboot的vitis工程后出现如下报错:
这里截图截的不太对,具体的问题是在编译到gpio-uclass.c这个文件时报错,说找不到 dt-bindings/gpio/gpio.h 这个头文件。这个其实挺邪门,uboot工程里大几百个头文件,这个和其他的一样平平无奇的躺在那,凭啥就你找不到?
不过我点开了这个头文件,发现里面只有寥寥几行宏定义,并且只有gpio-uclass.c里include了这个头文件,于是我就干脆把那些宏定义复制进了gpio-uclass.c里面,如下所示:
然后编译就通过了(离谱),并且编译出的elf文件可以正常从sd卡启动(不排除有隐藏bug的可能,但是以我十年c语言编程的经验()来看,把一些宏定义从头文件copy到c文件对程序应该产生不了太大影响)。至于编译的时候为什么找不到那个文件我还是不懂。
无法通过vitis正常调试
然后按照原子的教程,可以通过vitis直接将编译好的程序用jtag下载到板上然后可以调试打断点之类的。按照教程,选择u-boot.elf文件下进板子里,如下图所示:
然后可以下进去,但是无法正常调试,显示的反汇编结果如下所示:
也没法正常设置断点:
先说结论,debug时要选择下载的程序应该是u-boot,而不是u-boot.elf,如下图所示:
接下来是调试历程
自己实在解决不了,去问了deepseek,根据他的提示一步一步测试,使用readelf -wl u-boot.elf
命令测试,发现没有任何输出,deepseek说没有输出表明该文件里不包含调试信息。在起初我还以为是我的编译的方法有问题,导致没有生成相应的调试信息,然后按照这个思路去查,然后抓耳挠腮了两三天,后来终于在和deepseek的交谈中发现了玄机,他这么和我说:
3. 验证调试信息
重新编译后,检查
u-boot
(不是u-boot.elf
):arm-xilinx-linux-gnueabi-readelf -S u-boot | grep debug
arm-xilinx-linux-gnueabi-nm u-boot | grep board_f
期望输出:
[27] .debug_info PROGBITS 00000000 001160 00055d 00 0 0 1
00000000 T board_f
我才知道调试信息在u-boot里面,而不是u-boot.elf。然后我还问了他这两个文件的区别:
为什么
u-boot
能用而u-boot.elf
不行?
- 文件本质区别:
- **`u-boot`**:这是 U-Boot 编译生成的 **原始二进制文件**(通常为 `u-boot` 或 `u-boot.bin`),默认保留所有符号和调试信息。- **`u-boot.elf`**:可能是通过 `objcopy` 或其他工具生成的 **ELF 格式文件**,但某些构建流程默认会剥离调试信息(例如使用 `objcopy --strip-debug`),导致调试符号丢失。
- 教程的常见误区:
- 很多教程会混淆 `u-boot` 和 `u-boot.elf`,尤其是 Xilinx 生态中,`.elf` 常用于引导加载或 FPGA 配置,但 U-Boot 的构建流程可能对这两种文件的处理不同。- 如果教程未明确说明生成调试文件的步骤,直接推荐 `u-boot.elf`,很可能是基于过时的流程或错误假设。