我编译了一个简单的二进制文件(hello.bin)并将其存储在存储卡上。
我正在运行带有 i.mx 6 四核处理器的 NXP Sabre 开发套件。我已经启动了 U-boot 并尝试访问二进制文件并使其运行。
hello.bin 可用,因为以下命令有效:
=> fatload mmc 1:4 0x20005000 hello.bin
reading hello.bin
按照我的理解,文件应该加载到 RAM 的地址 0x20005000
所以我想测试二进制文件是否存在
=> md 0x20005000
20005000: 464c457f 00010101 00000000 00000000 .ELF............
20005010: 00280002 00000001 00010315 00000034 ..(.........4...
20005020: 000028f4 05000400 00200034 00280009 .(......4. ...(.
20005030: 00240025 70000001 00000454 00010454 %.$....pT...T...
看起来不错,因为起始位与我复制到 SD 卡的文件相匹配。
当我尝试启动二进制文件时,设备报告未定义的指令:
=> go 0x20005000
## Starting application at 0x20005000 ...
undefined instruction
pc : [<20005158>] lr : [<4ff71403>]
reloc pc : [<e7897158>] lr : [<17803403>]
sp : 4f56dd50 ip : 00000000 fp : 00000002
r10: 4f56f938 r9 : 4f56deb0 r8 : 4ffc3c40
r7 : 4ff713d9 r6 : 00000002 r5 : 20005000 r4 : 4f56f93c
r3 : 20005000 r2 : 4f56f93c r1 : 4f56f93c r0 : 00000000
Flags: nzCv IRQs off FIQs off Mode SVC_32
Resetting CPU ...
得到了另一位朋友的帮助,我发现它非常有帮助,所以我将其发布:
您可以使用 Yocto 工具链,但无法链接到 C 库(默认情况下完成),因此您必须向 GCC 添加一些额外的选项,让它知道您也不能使用 U 中的
go
指令-引导跳转到您刚刚加载到内存中的 ELF 二进制文件,必须使用工具 objdump
将 ELF 二进制文件转换为“原始”二进制文件(您的情况下的 ARM 指令列表)。 ELF 二进制文件是一种特定的格式,封装了您的代码/数据和一些额外信息,ELF 的第一部分是二进制文件的描述,所以现在,当您在第一个地址处执行 go
时,您试图告诉 CPU 执行非 ARM 指令的指令。您基本上想要执行我们所说的 ELF 二进制文件的“.text”部分。
请在 https://www.denx.de/wiki/view/DULG/UBootStandalone#Section_5.12.1 查找示例。
go 不需要 ELF 二进制文件的开头,而是入口例程的地址。如果您想访问 U-Boot 例程,则必须重新定位二进制文件。
我编译了一个简单的二进制文件(hello.bin)并将其存储在存储卡上。
您忽略了许多重要的细节。
你是如何编译这个程序的,例如什么工具链,什么makefile?
您是否将此程序与库链接?
按照我的理解,文件应该加载到 RAM 的地址 0x20005000
你是如何得到这个“理解”的?
通常独立程序的加载地址取决于几个因素。
首先必须考虑可用内存的地址(在目标板上)。
其次,除非独立程序是可重定位的(在您的情况下不太可能),否则必须将程序加载到链接程序时定义的加载/起始地址。
程序的加载地址和起始地址可以从其映射文件(即链接器输出)中获取。
当我尝试启动二进制文件时,设备报告未定义的指令:
这就是“执行”ELF header 时发生的情况。
由于该文件显然包含 ELF 标头,因此其文件扩展名应该是 .elf 而不是 .bin.
这个可执行文件是如何获得误导性的名称的?
您可能没有构建独立的二进制图像文件。
U-Boot 源代码的 examples/standalone/ 目录包含示例代码和用于构建独立二进制文件的 makefile,例如一个 hello_world.bin.
请务必为 您的主板正确定义 CONFIG_STANDALONE_LOAD_ADDR!
默认加载地址肯定不合适。
=> bdinfo,命令告诉我有关 DRAM 组的一些信息,从 0x10000000(7 个零)开始,到 0x4000000 结束。
(首先,不要在评论中添加重要信息。使用编辑功能将其添加到您的原始帖子中。)
您提供的“信息”没有任何意义(即结束地址小于起始地址)。避免解释信息,而是简单地呈现(复制粘贴)实际输出。
然后我使用 fatload mmc 1:4 0x10005000 hello.bin 代替,这似乎可以工作。我猜我正在写信给一个超出范围的地址。
fatload
命令仅将文件内容复制到内存中。该副本的真正成功是通过验证内存来确认的,而不是通过命令的完成来确认。go 0x10005000 还是不行。
尝试任意加载/起始地址并不是一种有效的调试技术。
“似乎有效” 或 “仍然无效” 的总和是对结果的低质量描述。
请参阅如何以聪明的方式提出问题。