You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

QEMU模拟树莓派4(aarch64)UART异常排查求助

问题描述

按照某树莓派AArch64内核教程构建了kernel8.img,放入2024-07-04版本Raspios镜像后,用以下QEMU命令模拟Raspi4b时仅显示黑屏:

qemu-system-aarch64 \
        -machine raspi4b \
        -cpu cortex-a72 \
        -smp 4 -m 2G \
        -dtb bcm2711-rpi-4-b.dtb \
        -drive format=raw,file=2024-07-04-raspios-bookworm-arm64-full.img

尝试添加-semihosting --semihosting-config enable=on,target=native或-serial mon:stdio参数无效;改用以下命令仍无输出:

qemu-system-aarch64 -M raspi4b \
    -display none \
    -serial null \
    -serial stdio \
    -kernel kernel8.img

通过GDB调试发现:加载raw二进制时未执行kernel_main,加载ELF则卡在uart_send发送首个字符环节。确认教程代码针对Raspi3b,其辅助及GPIO寄存器基址与Raspi4b不同,且代码在Raspi3b模拟下可正常运行。

求助:上述命令存在哪些问题?如何验证QEMU是否模拟UART及查看其输出?(要求模拟Raspi4b,不使用-machine virt)


解答

一、现有QEMU命令的问题

1. 第一个启动命令的核心问题

  • 直接启动Raspios镜像时,镜像自带的bootloader会优先加载自身的kernel8.img,而非你替换的版本。必须手动修改镜像中boot/config.txt文件,添加kernel=kernel8.img指定加载自定义内核,否则QEMU不会加载你的编译产物。
  • 未指定-kernel参数时,QEMU完全依赖镜像内的原生引导流程,Raspios的bootloader不会自动识别替换的内核文件。

2. 第二个启动命令的问题

  • 代码针对Raspi3b编写,而Raspi4b的外设基址完全不同:Raspi3b外设基址为0x3F000000,Raspi4b为0xFE000000。UART、GPIO的寄存器地址均基于该基址,硬编码的旧地址会导致UART初始化失败,进而卡在发送字符环节。
  • 缺少指定Raspi4b的设备树文件(-dtb bcm2711-rpi-4-b.dtb),虽QEMU模拟Raspi4b时部分兼容,但缺少DTB会影响外设初始化的正确性。

二、验证QEMU的UART模拟及查看输出的方法

1. 修正命令与代码,获取UART输出

  • 先修改代码中的外设基址:将所有0x3F000000开头的寄存器地址替换为0xFE000000(例如UART0基址从0x3F201000改为0xFE201000,GPIO基址从0x3F200000改为0xFE200000)。
  • 使用修正后的启动命令(直接加载自定义内核):
    qemu-system-aarch64 -M raspi4b \
        -cpu cortex-a72 \
        -smp 4 -m 2G \
        -dtb bcm2711-rpi-4-b.dtb \
        -kernel kernel8.img \
        -display none \
        -serial stdio
    
    该命令将UART输出直接重定向到终端,若代码修改正确,即可看到内核输出内容。

2. 验证QEMU的UART模拟功能

  • 用官方Raspi4b的正常Raspios镜像启动,添加-serial stdio参数,若能看到完整的系统启动日志,说明QEMU的UART模拟功能正常。
  • 借助GDB断点调试:在uart_init函数处设置断点,检查寄存器地址的写入值是否正确,确认GPIO引脚是否被配置为UART功能(Raspi4b的UART0引脚定义与Raspi3b一致,但寄存器地址不同)。

3. 绕过UART的快速调试方法

  • 添加半宿主参数,修改代码使用半宿主API(如sys_write0)输出内容,绕过硬件UART初始化问题,先验证内核是否能正常执行:
    qemu-system-aarch64 -M raspi4b \
        -cpu cortex-a72 \
        -smp 4 -m 2G \
        -kernel kernel8.img \
        -display none \
        -semihosting --semihosting-config enable=on,target=native
    
    若半宿主输出正常,说明内核可正常运行,问题确实出在UART硬件地址不匹配。

内容的提问来源于stack exchange,提问作者k1r1t0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 03:27:27