1. 课程导学与环境搭建
各位同学,欢迎来到《QEMU RISC-V 外设模拟与驱动开发实战》的第一章。我是这门课的主讲,做了十几年嵌入式底层开发,从 ARM 到 RISC-V,从裸机到 Linux 内核,踩过的坑比写过的代码还多(笑)。今天咱们先不急着写代码,把地基打牢。
这一章的目标很明确:搞懂 QEMU 是什么、RISC-V 凭什么火、以及怎么把开发环境一把梭哈配好。我保证,跟着我走完这一章,你就能在电脑上跑起一个 RISC-V 的 Linux 内核,并且能用 GDB 调试它。
1.1 QEMU 到底是什么?
QEMU,全称 Quick EMUlator。说白了,它是一个虚拟机,但又不是普通的虚拟机。你想想看,VMware 跑的是 x86 上的 x86,QEMU 能干的是在 x86 上模拟一个 ARM、RISC-V、MIPS 甚至是个单片机。
我个人习惯把 QEMU 分成两种模式:
- 系统模拟(System Emulation):模拟一整台电脑,包括 CPU、内存、硬盘、网卡、串口。你可以在这上面装操作系统。
- 用户模式(User Mode):只模拟 CPU,直接运行单个 Linux 程序。轻量,但功能有限。
咱们这门课,主要用系统模拟模式。为什么选 QEMU?因为真实硬件太贵、太慢、太难调试。我在项目中遇到过好几次,板子还没回来,驱动代码已经写完了,全靠 QEMU 提前验证。等板子到了,一次点亮,那种感觉,嗯,很爽。
核心观点:QEMU 不是玩具,它是嵌入式开发者的「时间机器」。它让你在硬件就绪之前,就能把软件调通。
1.2 RISC-V 架构概述
RISC-V 是个开源指令集架构(ISA)。注意,是「指令集」,不是「芯片」。它定义了 CPU 能理解哪些指令,至于怎么造芯片,那是各家厂商的事。
为什么 RISC-V 这几年这么火?我总结了几点:
| 特性 | 说明 |
|---|---|
| 开源免费 | 不需要像 ARM 那样交授权费,随便用 |
| 模块化 | 基础指令集(RV32I/RV64I)固定,扩展指令集(M/A/F/D/C)按需选配 |
| 简洁优雅 | 基础指令只有几十条,比 x86 和 ARM 干净得多 |
| 生态成熟 | Linux、GCC、LLVM、QEMU 都已原生支持 |
咱们课程用的是 RV64GC 架构。G 代表通用扩展集(IMAFD),C 代表压缩指令扩展。说白了,这就是 RISC-V 的「标准配置」,Linux 内核跑在上面毫无压力。
小提示:如果你之前只接触过 ARM 或 x86,刚开始看 RISC-V 的汇编可能会觉得「指令好少」。别慌,少意味着简单,简单意味着容易学透。
1.3 开发环境安装与验证
好,理论说完了,咱们动手。环境搭建是新手最容易卡住的地方。我曾经见过一个同学,装 QEMU 装了一整天,最后发现是路径里有中文。嗯,这种坑咱们今天一并填平。
1.3.1 安装 QEMU
QEMU 的安装方式取决于你的操作系统。我个人推荐用包管理器,干净利落。
Ubuntu/Debian 系:
sudo apt update
sudo apt install qemu-system-misc
Fedora/RHEL 系:
sudo dnf install qemu-system-riscv
macOS(Homebrew):
brew install qemu
装完之后,验证一下:
qemu-system-riscv64 --version
如果能看到版本号,比如 QEMU emulator version 8.x.x,恭喜你,第一步走通了。
1.3.2 安装 RISC-V 交叉编译工具链
咱们要在 x86 电脑上编译出 RISC-V 能跑的程序,所以需要交叉编译器。
sudo apt install gcc-riscv64-linux-gnu
sudo apt install gdb-multiarch
验证一下:
riscv64-linux-gnu-gcc --version
gdb-multiarch --version
注意:gdb-multiarch 是支持多架构的 GDB,咱们用它来调试 RISC-V 程序。不要装成普通的 gdb,那个只能调 x86。
1.3.3 编写第一个 RISC-V 程序
咱们写一个最简单的 C 程序,验证整个工具链是否通畅。
新建文件 hello.c:
#include <stdio.h>
int main() {
printf("Hello, RISC-V World!\n");
return 0;
}
编译:
riscv64-linux-gnu-gcc -static -o hello.riscv hello.c
用 QEMU 用户模式运行:
qemu-riscv64 ./hello.riscv
如果终端打印出 Hello, RISC-V World!,说明你的交叉编译环境和 QEMU 用户模式都正常工作了。
1.3.4 启动 RISC-V Linux 内核
这才是重头戏。咱们用 QEMU 系统模式启动一个完整的 RISC-V Linux 内核。
你需要准备两个文件:
- 内核镜像:
Image或vmlinux - 根文件系统:
rootfs.ext4或rootfs.cpio
启动命令如下:
qemu-system-riscv64 \
-machine virt \
-cpu rv64 \
-m 256M \
-kernel Image \
-drive file=rootfs.ext4,format=raw,id=hd0 \
-device virtio-blk-device,drive=hd0 \
-append "root=/dev/vda rw console=ttyS0" \
-nographic
解释一下关键参数:
| 参数 | 含义 |
|---|---|
-machine virt |
使用 QEMU 的通用 RISC-V 虚拟平台 |
-cpu rv64 |
指定 64 位 RISC-V CPU |
-m 256M |
分配 256MB 内存 |
-nographic |
不使用图形界面,全部用串口终端交互 |
-device virtio-blk-device |
挂载 virtio 块设备(咱们后面章节会重点讲这个) |
启动后,你会看到 Linux 内核的启动日志刷刷地滚,最后出现一个登录提示符。输入 root 登录,你就进入了一个完整的 RISC-V Linux 系统。
避坑指南:我曾经因为内核镜像和 QEMU 版本不匹配,卡在启动阶段半小时。建议用同一套发行版提供的 QEMU 和内核,比如 Debian 的 riscv64 移植版,省心很多。
1.4 本章知识体系
为了让你对整个章节的结构有个直观印象,我画了一张图。这张图展示了咱们从「开发机」到「目标系统」的完整链路。
从这张图你可以看到,咱们的整个工作流是:在开发机上用交叉工具链编译程序,然后通过 QEMU 模拟器在目标系统上运行。这三者缺一不可,也是后续所有章节的基础。
1.5 本章小结
这一章咱们干了三件事:
- 理解了 QEMU 和 RISC-V 的核心概念——知道它们是什么、为什么用、怎么用。
- 搭建了完整的开发环境——QEMU、GCC、GDB 全部装好并验证通过。
- 跑通了第一个 RISC-V 程序——从用户模式到系统模式,全链路打通。
环境搭好了,后面的路就好走了。从下一章开始,咱们会深入 QEMU 的虚拟平台,看看它到底模拟了哪些外设,以及我们怎么为这些外设编写驱动程序。
记住,嵌入式开发没有捷径,但有好工具。QEMU 就是那个好工具。用好它,你的开发效率能翻倍。