Qemu 模拟 Raspberry-Pi 在 GDB 调试器中从 0x0000 而不是 0x8000 开始执行,Rust 裸机代码

问题描述 投票:0回答:1

我已经开始了裸机嵌入式编程之旅,我正在尝试运行我的“Hello, world!”使用 Qemu 模拟树莓派 2 的代码示例。

根据不同来源的文档和教程,我成功地用 Rust 编译了

armv7a-none-eabi
的代码,将代码的开头放在
.elf
文件中的地址 0x8000 处,因为我读到树莓派的代码开始于这个地址。我的代码初始化 UART mini、UART mini 的 GPIO 14 和 15,并将符号发送到 UART mini 数据寄存器。

由于没有任何反应,我尝试使用 GDB 进行调试。然而,当用GDB连接到QEMU时,代码指针位于0x0000而不是0x8000,这让我觉得确实出了问题。

我像这样启动 Qemu:

qemu-system-arm -M raspi2b -kernel target/binary/my_custom_code.img -nographic -s -S

然后,我启动GDB:

gdb target/armv7a-none-eabi/debug/my_custom_code.elf

我连接到 Qemu 进程:

(gdb) target remote localhost:1234
Remote debugging using localhost:1234
0x00000000 in ?? ()

此后,什么也没有发生。任何

step
next
都会抛出“无法找到当前函数的边界”错误,并且
continue
会挂起。我可以放置断点,但我猜这是因为我在 gdb 中加载了我的文件,而不是因为我连接到了正确运行的程序。

此外,当我尝试运行

info reg
时,我没有获得
BCM2837-ARM
的标准寄存器名称,这让我更加认为 qemu 没有正确运行树莓派或我的程序。

最后,我尝试使用迷你 UART 从树莓派向控制台显示文本,但由于它不起作用,我开始使用 GDB 进行调试,现在看起来没有任何东西运行正常。

我在

NixOS v24.05.20231209.666fc80
上完成所有这些工作,使用的 shell 使用包
gcc-arm-embedded
qemu
gdb

我的树莓派模拟或者我的GDB进程有问题吗?为什么代码指针不在 0x8000 处?我是否错过了有关将迷你 UART 连接到 Qemu 控制台的其他内容?

如果需要,我很乐意提供更多信息。

raspberry-pi arm qemu
1个回答
0
投票

QEMU 的树莓派模型启动二进制文件的方式与固件在真实硬件 pi 上的启动方式不完全相同。你有两个选择:

(1) 根据内核记录的要求(包括能够在任意地址加载之类的内容),使您的二进制文件期望像 Linux 内核一样启动,并将二进制文件传递给 -kernel 选项作为原始二进制文件、zImage 或类似文件

(2) 使您的二进制文件成为 ELF 文件,将二进制文件加载到正确的位置,并将 ELF 文件传递给 -kernel 或“通用加载器”。 QEMU 将遵循 A-profile Arm ELF 文件的 ELF 入口点。请注意,所有 CPU 将同时在同一位置启动,如果您不关心辅助 CPU,则您的二进制文件必须将它们整理出来并将其放入暂存笔中!

无论哪种方式,您都需要确保您的映像包含重置向量和其他中断/异常入口点处的代码,并具有一些汇编代码,以便在进入非汇编之前根据 Rust 的任何要求设置 CPU代码(例如,它可能期望启用 FPU)。如果您能找到有关如何执行此操作的现有教程,或者至少改编一个已知的工作 C 示例,而不是尝试通过自己遇到的问题来解决所有问题,您会发现速度要快得多。

对于 gdb,您需要使用理解 Arm 架构的 gdb。这通常不是标准的“gdb”,它仅在主机体系结构支持的情况下进行编译。您可以使用 gdb 命令“set arch arm”对此进行测试;如果 gdb 说“目标架构设置为“arm””,则它具有 Arm 支持;如果它显示“未定义的项目:“arm””,那么它就不会,您需要使用编译了 Arm 支持的 gdb。这可能是一个名为“gdb-multiarch”的二进制文件或包(它支持许多架构) )或者它可能是专门构建的带有跨 gdb 手臂支持的 gdb:您需要检查您的发行版如何打包它。

© www.soinside.com 2019 - 2024. All rights reserved.