前言
最近想系统学习嵌入式 Linux,但苦于预算有限,买不起开发板(二手也很贵/(ㄒoㄒ)/~~),于是决定尝试使用 QEMU 作为替代方案。
一、QEMU
目前中文互联网上适合新手入门的 QEMU 资料较少(要么过于简略要么过于深奥)。幸运的是,作为入门学习阶段实体开发板的替代品,只要能顺利启动并使用 QEMU 进行模拟就足够了。
在这里只需要知道,QEMU的作用就是在你现有的平台上(如x86)模拟你目标平台(如ARM)的一个工具,和我们使用VMware模拟整个操作系统是类似的原理。
二、环境准备
1.搭建 Linux 环境
对于qemu可以有几种不同的安装使用方式,可以在windows或Linux上安装官方程序,也可以自己下载源码进行编译。在这我们的学习重点不是qemu,所以尽可能简单快速的完成基础环境搭建就可以了。
如果你已经在使用 Linux 系统,可以跳过此步。 对于 Windows 用户,可以通过以下方式获得 Linux 环境:
VMware Workstation Player(当前有免费版本) 或VirtualBox:创建 Ubuntu 虚拟机。
WSL2 (Windows Subsystem for Linux 2):微软提供的 Linux 子系统。目前安装非常简便,只需在 Microsoft Store 中搜索并安装 “Ubuntu 22.04 LTS” 即可。安装后启动 Ubuntu 并按提示完成初始化设置。如果找不到 WSL 选项,可能需要参考官方文档启用 WSL 功能。(如果实在不行可能需要自行百度一下或者选用VM)。
安装好后启动根据提示启动即可,未安装WSL会弹窗提示你安装。
2.安装 QEMU 及相关工具
启动后在命令行中使用apt安装所需工具。
# 安装 QEMU 和 ARM 工具链 sudo apt update sudo apt install -y qemu-system-arm gcc-arm-none-eabi gdb-multiarch # 验证 QEMU 版本(必须 >= 5.2) qemu-system-arm --version # 可能显示: QEMU emulator version 7.2.0 (Debian 1:7.2+dfsg-7ubuntu1)成功后可以进一步确认 QEMU 对目标平台的支持。
# 查看 QEMU 支持的 i.MX6ULL 机器类型 qemu-system-arm -M help | grep imx # 输出:imx6ul-evk i.MX6UL Evaluation Kit # 查看机器详细信息 qemu-system-arm -machine imx6ul-evk,help # 查看 CPU 信息 qemu-system-arm -cpu cortex-a7,help # 查看内存映射 echo "info mtree" | qemu-system-arm -machine imx6ul-evk -monitor stdio -nographic如果有需要可以下载对应的资源。
# 查看 QEMU 如何定义 i.MX6ULL 的内存布局 # 需要下载 QEMU 源码 git clone https://gitlab.com/qemu-project/qemu.git cd qemu # 查看 i.MX6ULL 的硬件描述 grep -r "imx6ul-evk" hw/arm/ # 主要文件:hw/arm/fsl-imx6ul.c, hw/arm/imx6ul_evk.c # 查看具体内存映射 cat hw/arm/fsl-imx6ul.c | grep -A 20 "memory_region_init_ram"至此,QEMU 环境已准备就绪。
2.QEMU 启动流程解析
| 物理芯片启动流程 | QEMU 模拟流程 | |
|---|---|---|
| 1 | 上电复位 | QEMU 进程启动 |
| 2 | 读取 BOOT 引脚状态 | 创建虚拟 i.MX6ULL 实例 |
| 3 | 执行内部 BootROM | 跳过 BootROM执行 (默认行为) |
| 4 | BootROM 读取启动设备 | 初始化内存控制器(虚拟) |
| 5 | 加载 IVT、DCD 等头部 | 将用户提供的 ELF/二进制文件直接加载到指定地址 (如 0x87800000) |
| 6 | 配置 DDR、时钟 | 设置程序计数器 (PC) 为加载地址 |
| 7 | 跳转到应用程序入口 | 开始执行第一条指令 |
通过表格可以看出使用qemu模拟并不是一比一复刻硬件的启动流程,虽然 QEMU 默认跳过 BootROM,但我们可以模拟不同的启动源(内存,SD卡,SPI Flash等)。这里我们采用默认方式从内存加载启动。
3.启动 QEMU 进行模拟
准备好你的 ARM 程序(例如编译链接生成的imx6ull_qemu.elf文件),使用以下命令启动 QEMU:
# 启动 QEMU 模拟器,模拟 ARM 平台 qemu-system-arm \ -M mcimx6ul-evk \ # 指定机器类型为 i.MX6UL EVK 开发板 -cpu cortex-a7 \ # 设置 CPU 类型为 ARM Cortex-A7 -nographic \ # 禁用图形输出,所有交互通过命令行进行 -serial mon:stdio \ # 将串口重定向到标准输入输出,便于调试和控制 -S -s \ # -S: 启动时暂停 CPU,等待调试器连接;-s: 启用 GDB 调试服务器(默认监听端口 1234) -kernel imx6ull_qemu.elf # 加载内核镜像文件 imx6ull_qemu.elf这里加载的imx6ull_qemu.elf文件就是你使用arm-none-eabi-gcc等工具编译、链接你的汇编和 C 代码后生成的可执行文件 (ELF 格式)。
qemu内置了GDB服务器方便我们进行程序的调试,默认监听的端口时1234。我们可以在运行后新开一个窗口并启动GDB对我们的程序进行调试。
# 启动 GDB 并加载你的程序符号 gdb-multiarch imx6ull_qemu.elf # 设置目标架构为 ARM (gdb) set architecture arm # 连接到 QEMU 的 GDB 服务器 (默认端口 1234) (gdb) target remote localhost:1234成功后可以看到:
此时,你可以像调试本地程序一样使用 GDB 命令进行调试。