如何在没有用户干预的情况下执行裸机程序后干净退出 QEMU?
How to cleanly exit QEMU after executing bare metal program without user intervention?
我正在为 ARM 系统组装一个交叉编译单元测试平台,并 运行使用 qemu-system-arm
在主机上进行测试。具体来说,我使用 qemu 来模拟 Stellaris LM3S6965 评估板,因为它包含一个 Cortex M3 处理器,就像我的目标环境一样。 qemu 中的二进制 运行 是使用 GNU Tools for ARM 构建的。
不涉及OS。测试套件是 运行 作为裸机应用程序,在 -nographic
模式下使用 qemu。工具链和测试平台本身运行良好。并且测试成功 运行 完成并在 qemu 中生成测试结果也很好。
问题在于将 qemu 包装在自动构建工具中(在本例中为 Rake)。除了键盘命令之外,我还没有找到让 qemu 在测试套件 运行s 后退出并吐出结果的好方法。这会导致构建环境挂起/依赖用户干预。
我四处寻找,没有找到关于如何在程序终止后完成简单退出的好资源。我确实找到了 运行ning qemu 和 -no-reboot
选项的一些建议,然后从模拟器中的程序 运行ning 触发系统重置。我试过这个。它有效……有点。在 main()
执行后,我将适当的值写入仿真处理器的重置向量,这确实会触发重置。 运行 测试套件 qemu 报告捕捉到系统重置后。但是,它将此报告为硬件错误,转储寄存器内容,然后愤怒地退出(下面的错误消息)。虽然这确实在测试套件 运行s 之后完成了退出,但由于 qemu 以错误条件退出,它会破坏自动构建脚本。
qemu: hardware error: System reset
我想避免将键盘命令插入到构建中以模拟用户干预。我也想避免依赖 qemu 以错误状态退出。
看来我离干净的出口很近了,但还差得远。搜索 qemu 错误消息(上图)除了相关的错误报告外没有产生任何相关文档。
在我缺少的裸机程序中,是否存在导致 qemu 在 main()
returns 之后退出的机制?这个 -no-reboot
+ 系统重置策略会起作用吗?如果是这样,还需要什么才能让 qemu 干净地退出?
通常你需要在硬件上做任何会导致系统关闭(断电)的事情; QEMU 将使它执行'exit QEMU'。不幸的是,并非我们模拟的所有硬件都实现了断电机制(有时它没有连接到 QEMU 模型中,尽管这通常是一个容易修复的错误)。
对我来说最干净的选择是获取与我们已经使用的版本接近的 Qemu 稳定版本的源代码。以下引用Qemu源码1.1.2版本
我在 armv7m_nvic.c
中修改了 Cortex M3 + Stellaris LM3S6965 评估板的复位向量处理仿真。我用 qemu_system_reset_request()
调用替换了 hw_error()
调用。这个内部系统调用将重置虚拟机,但也会响应 -no-reboot
命令行选项以进行干净关闭,如我最初的问题中所讨论的那样。
这些build instructions worked for me after grabbing a snapshot of Qemu 1.1.2。我遇到了几个构建错误,但网络搜索很快解决了每个问题。
我建议为 ARM 处理器使用 Angel 接口。对调试很有帮助。您可以在 ARM Info Center 上阅读有关它的内容。特别是查看操作 angel_SWIreason_ReportException (0x18) 和参数 ADP_Stopped_ApplicationExit,QEMU 将了解您的应用程序已结束。
不要忘记 运行 QEMU 带有 -semihosting 参数,像这样:
qemu-system-arm -nographic -semihosting -kernel your_binary
这里是告诉 QEMU 停止的代码(你必须使用一些汇编程序):
register int reg0 asm("r0");
register int reg1 asm("r1");
reg0 = 0x18; // angel_SWIreason_ReportException
reg1 = 0x20026; // ADP_Stopped_ApplicationExit
asm("svc 0x00123456"); // make semihosting call
你也可以在 github 我使用它的地方查看我的项目。
aarch64 半主机退出
给了A32,这里是A64:
.global main
main:
/* 0x20026 == ADP_Stopped_ApplicationExit */
mov x1, #0x26
movk x1, #2, lsl #16
str x1, [sp,#0]
/* Exit status code. Host QEMU process exits with that status. */
mov x0, #0
str x0, [sp,#8]
/* x1 contains the address of parameter block.
* Any memory address could be used. */
mov x1, sp
/* SYS_EXIT */
mov w0, #0x18
/* Do the semihosting call on A64. */
hlt 0xf000
这是 GitHub 上的示例:
当前的 ARMv7M qEmu(基于 TI Stellaris LM3S6965 微控制器)支持从 AICRCR 寄存器(Application Interrupt and Reset Control Register)重置。
写入此寄存器的 SYSRESETREQ
位会向外部系统发出请求复位的信号。
写入AICRCR
需要将0x5FA
写入VECTKEY
字段,否则处理器忽略写入。
此行使 ARMv7M qEmu 重置。
SCB->AIRCR = (0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk;
要防止 qEmu 无限重启,您可以添加 qEmu 参数 -no-reboot
。
正在关注 ,it worked using different assembly, and i was working with zephyr qemu cortex m3:
static inline void _exit_qemu() {
register u32_t r0 __asm__("r0");
r0 = 0x18;
register u32_t r1 __asm__("r1");
r1 = 0x20026;
__asm__ volatile("bkpt #0xAB");
}
和
qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -vga none -net none -pidfile qemu.pid -serial mon:stdio -semihosting -kernel build/zephyr/zephyr.elf
我正在为 ARM 系统组装一个交叉编译单元测试平台,并 运行使用 qemu-system-arm
在主机上进行测试。具体来说,我使用 qemu 来模拟 Stellaris LM3S6965 评估板,因为它包含一个 Cortex M3 处理器,就像我的目标环境一样。 qemu 中的二进制 运行 是使用 GNU Tools for ARM 构建的。
不涉及OS。测试套件是 运行 作为裸机应用程序,在 -nographic
模式下使用 qemu。工具链和测试平台本身运行良好。并且测试成功 运行 完成并在 qemu 中生成测试结果也很好。
问题在于将 qemu 包装在自动构建工具中(在本例中为 Rake)。除了键盘命令之外,我还没有找到让 qemu 在测试套件 运行s 后退出并吐出结果的好方法。这会导致构建环境挂起/依赖用户干预。
我四处寻找,没有找到关于如何在程序终止后完成简单退出的好资源。我确实找到了 运行ning qemu 和 -no-reboot
选项的一些建议,然后从模拟器中的程序 运行ning 触发系统重置。我试过这个。它有效……有点。在 main()
执行后,我将适当的值写入仿真处理器的重置向量,这确实会触发重置。 运行 测试套件 qemu 报告捕捉到系统重置后。但是,它将此报告为硬件错误,转储寄存器内容,然后愤怒地退出(下面的错误消息)。虽然这确实在测试套件 运行s 之后完成了退出,但由于 qemu 以错误条件退出,它会破坏自动构建脚本。
qemu: hardware error: System reset
我想避免将键盘命令插入到构建中以模拟用户干预。我也想避免依赖 qemu 以错误状态退出。
看来我离干净的出口很近了,但还差得远。搜索 qemu 错误消息(上图)除了相关的错误报告外没有产生任何相关文档。
在我缺少的裸机程序中,是否存在导致 qemu 在 main()
returns 之后退出的机制?这个 -no-reboot
+ 系统重置策略会起作用吗?如果是这样,还需要什么才能让 qemu 干净地退出?
通常你需要在硬件上做任何会导致系统关闭(断电)的事情; QEMU 将使它执行'exit QEMU'。不幸的是,并非我们模拟的所有硬件都实现了断电机制(有时它没有连接到 QEMU 模型中,尽管这通常是一个容易修复的错误)。
对我来说最干净的选择是获取与我们已经使用的版本接近的 Qemu 稳定版本的源代码。以下引用Qemu源码1.1.2版本
我在 armv7m_nvic.c
中修改了 Cortex M3 + Stellaris LM3S6965 评估板的复位向量处理仿真。我用 qemu_system_reset_request()
调用替换了 hw_error()
调用。这个内部系统调用将重置虚拟机,但也会响应 -no-reboot
命令行选项以进行干净关闭,如我最初的问题中所讨论的那样。
这些build instructions worked for me after grabbing a snapshot of Qemu 1.1.2。我遇到了几个构建错误,但网络搜索很快解决了每个问题。
我建议为 ARM 处理器使用 Angel 接口。对调试很有帮助。您可以在 ARM Info Center 上阅读有关它的内容。特别是查看操作 angel_SWIreason_ReportException (0x18) 和参数 ADP_Stopped_ApplicationExit,QEMU 将了解您的应用程序已结束。
不要忘记 运行 QEMU 带有 -semihosting 参数,像这样:
qemu-system-arm -nographic -semihosting -kernel your_binary
这里是告诉 QEMU 停止的代码(你必须使用一些汇编程序):
register int reg0 asm("r0");
register int reg1 asm("r1");
reg0 = 0x18; // angel_SWIreason_ReportException
reg1 = 0x20026; // ADP_Stopped_ApplicationExit
asm("svc 0x00123456"); // make semihosting call
你也可以在 github 我使用它的地方查看我的项目。
aarch64 半主机退出
.global main
main:
/* 0x20026 == ADP_Stopped_ApplicationExit */
mov x1, #0x26
movk x1, #2, lsl #16
str x1, [sp,#0]
/* Exit status code. Host QEMU process exits with that status. */
mov x0, #0
str x0, [sp,#8]
/* x1 contains the address of parameter block.
* Any memory address could be used. */
mov x1, sp
/* SYS_EXIT */
mov w0, #0x18
/* Do the semihosting call on A64. */
hlt 0xf000
这是 GitHub 上的示例:
当前的 ARMv7M qEmu(基于 TI Stellaris LM3S6965 微控制器)支持从 AICRCR 寄存器(Application Interrupt and Reset Control Register)重置。
写入此寄存器的 SYSRESETREQ
位会向外部系统发出请求复位的信号。
写入AICRCR
需要将0x5FA
写入VECTKEY
字段,否则处理器忽略写入。
此行使 ARMv7M qEmu 重置。
SCB->AIRCR = (0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk;
要防止 qEmu 无限重启,您可以添加 qEmu 参数 -no-reboot
。
正在关注
static inline void _exit_qemu() {
register u32_t r0 __asm__("r0");
r0 = 0x18;
register u32_t r1 __asm__("r1");
r1 = 0x20026;
__asm__ volatile("bkpt #0xAB");
}
和
qemu-system-arm -cpu cortex-m3 -machine lm3s6965evb -nographic -vga none -net none -pidfile qemu.pid -serial mon:stdio -semihosting -kernel build/zephyr/zephyr.elf