先说一个反常识的事实:你每天用的手机、电脑里的 CPU,它们的「语言」是被垄断的。 x86 每颗授权费上千万美元,ARM 架构授权也要几百万起。而 RISC-V——第五代精简指令集,2010 年诞生于伯克利,2015 年开放基金会成立,如今已有数百亿颗出货——它选择把语言本身变成开源的。
这篇文章带你把 RISC-V 从「听说过」走到「写过汇编、点过灯、跑过系统」。不需要芯片背景,会一点 C 语言就够。
一、为什么需要 RISC-V:一场架构的「 Fedora 运动」
理解 RISC-V,先理解它反对什么。
x86 有 40 多年历史包袱:为了兼容 1978 年的 8086,它背着一堆现代程序永远用不到的指令。ARM 好一些,但授权费高墙摆在那里:小公司想自定义一条指令?先聊聊钱。
RISC-V 的策略简单粗暴:
- 只规定「语言」,不管「说话的人」:指令集完全开放,任何人可以设计兼容芯片,不交授权费;
- 模块化:基础指令集极小,功能靠「积木块」按需拼装;
- 不允许历史包袱:每条指令都必须有存在理由,委员会为此砍掉了大量「看起来有用」的指令。
看懂这张图,你就懂了 RISC-V 命名的含义:
- RV32I:32 位基础整数指令集,只有 47 条指令,是唯一必须实现的部分;
- M:乘除法扩展;A:原子操作(多核同步必备);F/D:单/双精度浮点;C:16 位压缩指令(省内存);V:向量扩展(AI 运算)。
所以「RV32IMC」= 32 位 + 整数 + 乘除 + 压缩,一颗典型 MCU 的配置。做tiny MCU可以只留 RV32I,做 AI 芯片可以加 V——同一套架构,从传感器盖到超算。欧洲 EPI 处理器、阿里平头哥、NASA 的 HPSC 芯片,说的都是这门语言。
二、程序员的视角:32 个寄存器
抛开硬件,RISC-V 在程序员眼里就是一个「有 32 个变量、一张内存大海」的机器。
其中藏着几个精妙设计:
x0 永远是 0。 听起来浪费一个寄存器?其实它是「白送的清零神器」:mv x5, x0(把 0 搬进 x5)、比较、跳转判断,全靠它。硬件省掉了一条专门的清零指令。
寄存器都有「艺名」。 汇编里没人写 x10,大家都写 ABI 名字:a0~a7 传函数参数,t0~t6 存临时值,s0~s11 存跨函数保留值,sp 是栈指针,ra 是返回地址。
调用约定是汇编实战第一课。 简单说:调用别人函数前,t 系列随便用(对方可能覆盖);你是被调函数想用 s 系列,必须先压栈保存、返回前恢复。搞混了这个,程序就会「偶尔正常、偶尔玄学」。
三、指令格式:为硬件省钱的「强迫症设计」
x86 指令长度 1 到 15 字节不等,译码器堪称 CPU 里最复杂的部件之一。RISC-V 强迫症发作:所有指令统一 32 位(C 扩展的 16 位除外),而且格式只有四种(R/I/S/B/U/J 型)。
更妙的是字段布局:所有指令的 opcode 都在第 0~6 位,rd(目标寄存器)总在同一位置。意味着硬件在知道指令类型之前,就能先解码公共字段——流水线成本大幅降低。
代价是立即数编码有点「错位」(比如 B 型的立即数位序是乱跳的),但这是编译器操心的事,硬件为此省下的晶体管是真实的。
常用指令混个脸熟(每个都值得记住):
| 指令 | 作用 | 一句话记忆 |
|---|---|---|
add x5, x6, x7 |
x5 = x6 + x7 | 三地址运算 |
addi x5, x6, 1 |
x5 = x6 + 1 | 带立即数版本 |
lw x5, 8(x6) |
从内存读 32 位 | ls = load/store |
sw x5, 8(x6) |
写 32 位到内存 | s 系列 |
beq x5, x6, label |
相等就跳 | b 系列=分支 |
jal x1, label |
跳转并存返回地址 | jal = jump and link |
jalr x0, x1, 0 |
跳到 x1(函数返回) | ret 的真身 |
ecall |
陷入内核 | 系统调用入口 |
四、特权架构:一台机器的三种身份
前面说的是「用户态视角」,但想让 Linux 跑起来,还差一层:权限。
- M-Mode(机器模式):权限天花板,CPU 一上电就在这里。引导固件(如 OpenSBI)、中断控制器、时钟都归它管;
- S-Mode(管理者模式):操作系统住这层,页表(satp 寄存器)、系统调用处理、进程调度;
- U-Mode(用户模式):你的 App。想读硬件?没门,触发
ecall异常,被内核接管。
这个分层和 x86/ARM 思想一致,但 RISC-V 把它写得更「教科书」:每层的权责、每个 CSR(控制状态寄存器)的行为都有精确定义。CSR 就是每层模式的仪表盘:mstatus 存全局状态、mepc 存异常返回地址、mtvec 存异常入口、mie/mip 管中断……裸机开发一半的时间在和它们打交道。
顺便一提 PMP(物理内存保护):M-Mode 给每块物理内存设权限,让 U/S 模式只能碰自己的地盘——这是安全启动的基础。
五、实战第一站:QEMU 上跑第一个程序
学 RISC-V 最爽的一点:不用买开发板。装好工具链就能开始:
# Ubuntu/WSL 下一行装齐
sudo apt install gcc-riscv64-unknown-elf qemu-user
写个 hello.c,交叉编译、模拟运行:
riscv64-unknown-elf-gcc hello.c -o hello -static
qemu-riscv64 ./hello
# Hello, RISC-V!
想看汇编?riscv64-unknown-elf-objdump -d hello,搜 .text 段,你会发现每条指令整整齐齐 4 字节,printf 的参数正是通过 a0~a1 传入的——书上说的调用约定,肉眼可见。
进阶玩法:qemu-riscv64 -g 1234 ./hello 配合 gdb 远程调试,单步看每条指令怎么改变寄存器。「调试器眼里的 CPU」是理解体系结构最快的方式。
六、实战第二站:裸机点灯与串口
真正上强度的部分:脱离操作系统,直接面对硬件。
裸机程序没有 main 函数、没有 libc,CPU 复位后从 0x0 或 0x80000000 开始执行你的第一行指令。以经典的 QEMU virt 板 + Sifive 样例为例,最小工程三个文件:
start.S —— 入口:
.section .text.init
.global _start
_start:
la sp, _stack_top # 手动设置栈指针
call main
1: j 1b # main 返回就死循环
main.c —— 点灯(QEMU virt 板的 golden LED):
#define GOLDEN_LED ((volatile unsigned int*)0x100000)
void main(void) {
*GOLDEN_LED = 0xf; // 内存映射 I/O:写地址=控硬件
while (1);
}
link.ld —— 链接脚本,告诉链接器代码放哪、栈在哪。
编译时加 -nostdlib -ffreestanding,烧进 QEMU 系统级模拟(qemu-system-riscv32 -M virt -bios none -kernel blink.elf),LED 图形界面就开始闪。
这里的核心概念是「内存映射 I/O」:CPU 没有专门的「控制外设」指令,外设寄存器就是一段特殊内存地址,sw 写进去,硬件就动了。理解这一点,所有 MCU 的寄存器手册对你豁然开朗。
串口 printf 是裸机的第二课:配置 UART 寄存器(波特率、FIFO 使能),然后循环轮询状态位、往发送寄存器写字符。有了串口输出,你就有了裸机世界的「眼睛」,后面调 RTOS、调中断全靠它。
七、实战第三站:中断、RTOS 和 Linux
中断:CPU 平时顺序执行,外设来事时硬件自动:保存 PC 到 mepc、跳到 mtvec 指向的入口、进入 M-Mode。你写个中断向量表,处理完 mret 返回。定时器心跳、按键响应、串口收包,全是这套机制。
RTOS:FreeRTOS、RT-Thread、Zephyr 都有 RISC-V 移植。基于 QEMU 或一块 30 元的国产开发板(如 CH32V203、ESP32-C3),就能跑多任务、信号量、消息队列。RTOS 移植的核心工作,本质就是上面两节:初始化栈、保存/恢复寄存器上下文、接好 mtvec。
Linux:需要 RV64GC(G = IMAFD 的简称 + C),MMU 也是硬性要求。QEMU 先模拟一套(qemu-system-riscv64 -M virt + OpenSBI + U-Boot + 内核镜像),玩家可以用 buildroot 自己裁一个几百 KB 的系统。真机上,一斤重的 VisionFive 2(约 400 元)就是目前最火的 RISC-V Linux 开发板。
八、芯片生态:谁在造 RISC-V
| 阵营 | 代表 | 特点 |
|---|---|---|
| 国产 MCU | 乐鑫 ESP32-C 系列、沁恒 CH32V、兆易 GD32V | 便宜、生态全,ESP32-C3 模块 10 元以内 |
| 高性能 | 平头哥玄铁 C910、SiFive P870 | 十几核 A76 级性能 |
| Linux 单板 | VisionFive 2、香橙派 RV2 | SBC 玩家入门首选 |
| 特殊领域 | NASA HPSC、西部数据控制器 | 高可靠 / 超大量定制 |
与 ARM 怎么选? 现实建议:做产品要成熟工具链和低风险,ARM 依然是稳的选择;做学习、做定制指令、做需要长期自主可控的产品,RISC-V 优势明显。而且趋势是——ESP32-C 系列已经卖到几亿颗,RISC-V 的「能用」问题早已解决,剩下的是「好用」的生态差距,正在快速抹平。
九、四步通关路线
- 打基础(1~2 周):精读《RISC-V Reader》(中文版《手把手教你设计 CPU》也可),配合 RISC-V 规范卷一。不用背,理解设计取舍即可;
- 写汇编(2 周):QEMU 用户态模拟 + objdump 反汇编,把 C 代码编译成汇编逐行对照,搞懂调用约定;
- 玩裸机(1 个月):QEMU virt 板裸机工程——点灯、串口、定时器中断、上下文切换,每步都有能跑的代码;
- 上系统(1~2 个月):FreeRTOS 移植分析 → buildroot 裁剪 Linux → 买块 VisionFive 2 真机折腾。
推荐资源:QEMU 官方文档、B 站「Sifive 裸机系列」、GitHub 上的 riscv-os-tutorial 类仓库、RT-Thread 官方文档。
写在最后
RISC-V 最迷人的地方,不是免费,而是它的「可理解性」:x86 手册上万页,RISC-V 规范核心只有几百页,一个人真能读完。当你可以从晶体管层面理解「一条指令如何变成屏幕上的字符」时,你对计算机的理解会跨过一个台阶。
开源的世界里,最好的学习方式永远是动手。今天就装上 QEMU,写下你的第一行 RISC-V 汇编吧。
li a0, 1 # 唯一的开始