Unit testing 在执行裸机程序后,如何在没有用户干预的情况下干净地退出QEMU?

Unit testing 在执行裸机程序后,如何在没有用户干预的情况下干净地退出QEMU?,unit-testing,arm,qemu,bare-metal,Unit Testing,Arm,Qemu,Bare Metal,我正在为ARM系统组装一个交叉编译单元测试平台,并在主机上使用qemu系统ARM运行测试。具体来说,我使用qemu模拟Stellaris LM3S6965评估板,因为它包含一个Cortex M3处理器,就像我的目标环境一样。qemu中的二进制运行是使用用于ARM的GNU工具构建的 没有涉及操作系统。测试套件作为裸机应用程序运行,qemu处于-nographic模式。工具链和试验台本身工作正常。测试成功地运行到完成,并在qemu内产生测试结果 问题在于将qemu封装到一个自动构建工具中(在本例中为

我正在为ARM系统组装一个交叉编译单元测试平台,并在主机上使用
qemu系统ARM
运行测试。具体来说,我使用qemu模拟Stellaris LM3S6965评估板,因为它包含一个Cortex M3处理器,就像我的目标环境一样。qemu中的二进制运行是使用用于ARM的GNU工具构建的

没有涉及操作系统。测试套件作为裸机应用程序运行,qemu处于
-nographic
模式。工具链和试验台本身工作正常。测试成功地运行到完成,并在qemu内产生测试结果

问题在于将qemu封装到一个自动构建工具中(在本例中为Rake)。除了键盘命令之外,我还没有找到一种好方法,可以在测试套件运行并输出结果后使qemu退出。这会导致生成环境挂起/依赖于用户干预

我到处寻找,没有找到关于如何在程序终止后完成简单退出的好消息来源。我确实发现了一些建议,建议使用
-no reboot
选项运行qemu,然后从模拟器中运行的程序触发系统重置。我试过这个。它起作用了…有点。在执行
main()
之后,我将适当的值写入模拟处理器的重置向量,这确实会触发重置。运行测试套件后,qemu报告捕获到系统重置。但是,它将此报告为硬件错误,转储寄存器内容,然后退出(下面的错误消息)。虽然这确实可以在测试套件运行后完成退出,但由于qemu退出时出现错误,因此会中断自动构建脚本

qemu: hardware error: System reset
我希望避免将键盘命令插入构建以模拟用户干预。我还希望避免依赖qemu以错误状态退出

看来我已经接近一个干净的出口了,但还不太清楚。搜索qemu错误消息(如上)除了相关的bug报告外,没有生成任何相关文档


在我丢失的裸机程序中返回
main()
后,是否有机制导致qemu退出?此
-无重新启动
+系统重置策略是否有效?如果是这样,还需要什么才能让qemu干净地退出?

通常,您需要在硬件上执行任何可能导致系统关闭(断电)的操作;QEMU将使其成为“退出QEMU”。不幸的是,并不是我们模拟的所有硬件都实现了断电机制(有时它没有连接到QEMU模型中,尽管这通常是一个很容易修复的错误)。

对我来说,最干净的选择是获取接近我们已经使用的QEMU的稳定版本的源代码。以下是Qemu源代码的1.1.2版

我在
armv7m\u nvic.c
中修改了Cortex M3+Stellaris LM3S6965评估板重置向量处理的仿真。我将调用
hw\u error()
替换为调用
qemu\u system\u reset\u request()
。此内部系统调用将重置虚拟机,但也会响应
-no reboot
命令行选项以实现完全关闭,如我在原始问题中所述


这些在抓取后对我有用。我遇到了几个构建错误,但web搜索很快解决了每个问题。

我建议对ARM处理器使用Angel界面。这对调试非常有帮助。你可以在网上读到一些关于它的东西。特别是查看操作angel\u SWIreason\u ReportException(0x18)和参数ADP\u Stopped\u ApplicationExit,QEMU将理解您的应用程序已结束

不要忘记使用-semihosting参数运行QEMU,如下所示:

qemu-system-arm -nographic -semihosting -kernel your_binary
下面是告诉QEMU停止的代码(您必须使用一些汇编程序):


您也可以在我使用它的地方查看我的项目。

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寄存器复位()。 写入该寄存器的
SYSRESETREQ
位将向外部系统发出请求复位的信号

写入
AICRCR
需要将
0x5FA
写入
VECTKEY
字段,否则处理器将忽略写入操作

该行使ARMv7M qEmu复位

SCB->AIRCR = (0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk;
SCB->airr=(0x5FA下面,它使用不同的组件工作,我使用的是zephyr:


据我所知,仿真Stellaris LM3S6965 eval board/Cortex处理器没有软件控制的断电选项(典型的嵌入式系统)。唯一接近的是睡眠和低功耗模式。鉴于此,我是被迫在脚本控制下注入键盘命令,还是生活在qemu错误状态/寄存器转储出口中?是否有一种通用方法以某种方式触发qemu系统arm中的断电?以下是aarch64版本:
SCB->AIRCR = (0x5FA << SCB_AIRCR_VECTKEY_Pos) | SCB_AIRCR_SYSRESETREQ_Msk;
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