2、开发环境搭建:RISC-V GNU工具链编译、QEMU模拟器安装、Spike模拟器使用、Hello World程序验证

说实话,搭建开发环境这件事,很多初学者觉得枯燥。但我得说一句——环境搭不好,后面全是坑。我自己带过不少新人,十有八九的问题都出在工具链没配对上。所以这一章,咱们把RISC-V的四大件捋清楚:GNU工具链、QEMU、Spike,最后跑个Hello World验证一下。

2.1 RISC-V GNU工具链编译

GNU工具链,说白了就是编译器、汇编器、链接器那一套。RISC-V官方维护了一套叫riscv-gnu-toolchain的项目,支持RV32和RV64,也支持多种ABI。

我个人习惯用源码编译,虽然慢点,但可控。你如果图省事,也可以直接用apt装预编译包,但版本可能比较老。

2.1.1 下载源码

git clone https://github.com/riscv-collab/riscv-gnu-toolchain.git
cd riscv-gnu-toolchain
git submodule update --init --recursive

嗯,这里要注意——submodule更新这一步很关键。我曾经因为网络问题没拉全子模块,编译到一半报错,折腾了大半天。建议用代理或者换个时间段再试。

2.1.2 配置与编译

假设你要编译一个64位Linux版本的交叉工具链:

mkdir build && cd build
../configure --prefix=/opt/riscv --enable-multilib
make linux -j$(nproc)

这里--prefix指定安装路径,--enable-multilib表示同时支持RV32和RV64。编译时间取决于机器性能,我笔记本上大概跑了40分钟。

小提示:如果你只需要裸机(bare-metal)开发,可以改成make newlib,编译速度会快不少。

2.1.3 验证安装

/opt/riscv/bin/riscv64-unknown-linux-gnu-gcc --version

看到版本号输出,说明工具链装好了。你想想看,这一步要是卡住,后面所有实验都跑不了。所以务必确认。

2.2 QEMU模拟器安装

QEMU是个全能型模拟器,能模拟完整的RISC-V系统。我在项目中遇到过需要验证Linux内核的场景,QEMU就是首选。

2.2.1 安装方式

两种方式:

  • apt安装(推荐新手)sudo apt install qemu-system-riscv64
  • 源码编译(推荐进阶)
git clone https://github.com/qemu/qemu.git
cd qemu
./configure --target-list=riscv64-softmmu
make -j$(nproc)
sudo make install

我个人倾向源码编译,因为可以开启KVM加速,跑起来快很多。不过如果你只是跑个小程序,apt版完全够用。

2.2.2 快速测试

qemu-system-riscv64 -machine virt -nographic -m 256M -kernel /path/to/fw_jump.elf

这里-machine virt是QEMU自带的RISC-V虚拟开发板,-nographic表示不用图形界面。如果看到OpenSBI的启动信息,说明QEMU工作正常。

注意:QEMU的版本和工具链的ABI必须匹配。比如工具链是LP64D,QEMU也要支持双精度浮点。否则跑起来会莫名其妙地崩溃。

2.3 Spike模拟器使用

Spike是RISC-V官方的ISA模拟器,比QEMU轻量得多。它不模拟外设,只模拟CPU核心。说白了,就是用来跑裸机程序和做指令集验证的。

2.3.1 安装Spike

git clone https://github.com/riscv-software-src/riscv-isa-sim.git
cd riscv-isa-sim
mkdir build && cd build
../configure --prefix=/opt/spike
make -j$(nproc)
sudo make install

安装完后,记得把/opt/spike/bin加到PATH里。

2.3.2 运行一个程序

spike pk hello.elf

pk是代理内核(Proxy Kernel),它负责处理系统调用。Spike本身不提供操作系统服务,所以需要pk来桥接。

曾经犯过一个低级错误——直接用spike跑一个Linux编译出来的ELF,结果报错说找不到入口。后来才意识到,Spike只能跑裸机或者pk格式的程序。

2.4 Hello World程序验证

好了,工具链和模拟器都装好了,咱们写个Hello World验证一下。

2.4.1 编写代码

// hello.c
#include <stdio.h>

int main() {
    printf("Hello, RISC-V World!\n");
    return 0;
}

2.4.2 编译

/opt/riscv/bin/riscv64-unknown-linux-gnu-gcc -o hello.elf hello.c

这里用的是Linux版本的交叉编译器。如果你装的是newlib版,编译器名字会变成riscv64-unknown-elf-gcc

2.4.3 在QEMU上运行

qemu-system-riscv64 -machine virt -nographic -m 256M -kernel hello.elf

等等,这样直接跑不行。因为QEMU需要完整的启动流程,包括OpenSBI和内核。对于单个ELF,我们需要用-append参数或者制作一个根文件系统。

更简单的办法:用Spike来跑。

spike pk hello.elf

如果看到输出:

bbl loader
Hello, RISC-V World!

恭喜你,环境搭建成功了!

核心要点:
  • 工具链编译时注意submodule完整性
  • QEMU适合跑完整系统,Spike适合跑裸机程序
  • 验证环境时,先用Spike跑pk格式,再用QEMU跑完整系统

2.5 本章知识体系

下面这张图,是我画的环境搭建整体流程。你跟着这个路线走,基本不会迷路。

RISC-V开发环境搭建流程 RISC-V GNU工具链 编译Hello World程序 Spike模拟器运行 QEMU模拟器运行 输出Hello World验证 裸机/ISA验证 系统级验证

这张图很直观:工具链是基础,编译出ELF后,你可以选择Spike做快速验证,或者QEMU做完整系统测试。两条路最终都汇聚到Hello World输出。

好了,环境搭好,后面就可以愉快地写RISC-V汇编和C代码了。记住,工具链版本和模拟器版本一定要对齐,这是血的教训。


专注资料整理