RISC-V启动的基础逻辑
当我们谈论RISC-V的设计特色,讨论得最多的往往是它开源开放的属性、模块化的指令集设计,还有灵活的特权级架构。但很少有人会深入拆解它的启动流程,去品味这套架构在启动阶段设计里藏着的巧思。我自己在做RISC-V嵌入式开发的过程里,对比过ARM、MIPS这些传统架构的启动流程,越研究越觉得RISC-V的启动设计不简单——它没有像x86那样复杂的BIOS标准,也没有走ARM那套固定BL阶段的设计路线,反而用一套极简的架构逻辑,适配了从微控制器到服务器CPU的全场景需求。这种简洁又灵活的设计思路,恰恰是RISC-V架构设计哲学最好的体现,今天就和大家聊聊我对RISC-V启动部分的一些思考。
一、RISC-V启动的基础逻辑:从特权级开始讲起
要理解RISC-V的启动流程,首先得搞懂它的特权级设计,这是整个启动流程的基础。RISC-V把系统运行权限划分成了三个特权级:从高到低分别是机器模式M(Machine Mode)、监管模式S(Supervisor Mode)和用户模式U(User Mode)。和传统架构不同,RISC-V规定所有芯片复位之后,硬件必须跳转到M模式开始执行,这是整个RISC-V架构唯一的强制要求,剩下的所有流程都可以由软件设计者灵活定义,没有任何强制标准。
这种设计看起来简单,实则藏着大智慧。对于最简单的微控制器来说,比如我们常用的GD32VF103这类MCU,整个系统就只需要运行M模式下的单任务程序,不需要操作系统,那复位之后直接在M模式运行应用程序就可以了,不需要做任何特权级切换,整个启动流程一步到位,代码量可以做到非常小。而对于跑Linux的应用处理器来说,M模式只需要完成最基础的硬件初始化,然后把权限移交给S模式运行内核,最后再把用户空间交给应用程序,整个分层清晰简洁。对比ARM架构那种复杂的异常级别跳转,RISC-V的特权级启动逻辑少了很多不必要的规则,硬件设计更简单,软件适配也更灵活。
在传统架构里,启动地址往往是固定写死在硬件里的,比如ARM一般固定在0x0地址,x86固定在BIOS入口。而RISC-V只规定了复位之后PC会跳转到一个硬件自定义的入口地址,具体地址由芯片设计者决定,规范不做强制要求。这种灵活的设计让不同场景的芯片都可以自定义最优的启动位置:MCU可以把入口直接放在片上ROM,应用处理器可以放在BootROM,服务器芯片可以放在SPI Flash的映射地址,完全不需要受架构规范的约束,这种开放性给了芯片设计者极大的自由度。
二、多阶段启动的设计演进:从极简到复杂的平滑扩展
虽然RISC-V规范没有强制要求多阶段启动,但现在主流的RISC-V系统,尤其是需要运行操作系统的系统,基本都采用了多阶段启动的架构,这其实是行业实践总结出来的最优路径,和RISC-V本身的灵活设计完美契合。现在最常见的就是三级启动架构,我们来拆解每个阶段的作用,就能看出设计的巧思。
第一阶段是片上BootROM(BROM)阶段,这是芯片出厂的时候就烧录在片上ROM里的,不可修改,是芯片启动的第一站。BROM的空间非常有限,一般只有几KB到几十KB,不可能放下完整的启动代码,所以它的任务非常简单:只做最基础的硬件初始化,比如CPU核心的时钟配置、DDR内存的初始化,然后从外部存储设备(Nand Flash、SD卡、SPI Flash)把第二阶段的启动程序加载到RAM里,然后跳过去执行。因为空间有限,BROM只会做最必须的操作,不会做多余的事情,这种设计刚好解决了片上存储容量有限的问题,把复杂的逻辑放到外部存储里,平衡了芯片成本和功能需求。
第二阶段就是我们常说的SPL(Secondary Program Loader)阶段,也就是二级加载程序。这个阶段的核心任务是准备好运行主启动程序的环境。一般来说,SPL会完成DDR的进一步初始化、外设时钟配置、电源管理初始化,然后把U-Boot或者操作系统镜像加载到DDR的指定位置,然后跳转到镜像执行。为什么要把这个阶段单独拆出来?因为U-Boot这类完整的启动程序体积比较大,BROM放不下,所以需要一个中间阶段先把内存准备好,再加载大程序。在RISC-V的多芯片SoC系统里,SPL还会负责各个核心的唤醒和配置,做好启动前的同步准备。
对比ARM架构的BL1、BL2阶段,RISC-V的SPL没有强制的功能定义,完全由软件开发者决定要做什么,需要的话可以把更多初始化工作放到SPL,不需要的话也可以简化流程直接跳转到主程序,这种灵活性让它可以适配不同复杂度的芯片。比如在很多低功耗RISC-V MCU里,根本不需要DDR,片上SRAM就足够运行程序,那SPL阶段完全可以省略,BROM直接跳转到用户程序,整个流程两步就能走完,省去了不必要的开销。
第三阶段就是主程序执行阶段,如果是带操作系统的系统,一般就是U-Boot负责引导内核,U-Boot会完成硬件设备枚举、环境变量加载、设备树解析,然后把Linux内核加载到内存,把启动参数传递给内核,最后跳转到内核入口,启动流程就完成了。如果是裸机系统,那第三阶段直接就是用户的应用程序,不需要额外的引导流程,启动一步到位。
现在也有不少更灵活的启动模式,比如针对RISC-V多核心SoC设计的多启动模式,可以支持从SD卡SPI接口启动,也支持从SDIO直接在外部内存执行,还支持通过RISC-V调试模块启动,给开发和生产都提供了很大的便利。开发阶段可以通过调试接口直接加载程序启动,不需要烧录Flash,大大提升开发效率;量产阶段可以从外接存储自动加载,满足大规模生产的需求,这种灵活配置正是RISC-V启动设计的优势所在。
三、Linux内核启动的汇编设计:简洁就是美
我们拿RISC-V Linux内核的启动流程来举例子,就能更清楚地看到RISC-V启动设计的简洁性。对比x86和ARM复杂的汇编启动部分,RISC-V Linux的汇编启动非常短,核心逻辑不到一百行,就能完成所有必须的准备工作。
RISC-V Linux内核的汇编入口在arch/riscv/kernel/head.S,入口函数是_start_kernel,汇编阶段主要做这几件事:首先关闭所有中断,避免启动过程中被干扰;然后加载全局指针gp,做好代码运行的准备;接着禁用FPU,方便内核检测非法的浮点使用;对于多核心SMP系统,会先选出第一个启动的核心,其他核心先停留在启动等待区,等主核心启动完成之后再唤醒;然后清空BSS段,这是所有C程序运行前必须做的准备工作;接着保存核心ID(hart ID)和设备树(dtb)的地址,给后面的C代码使用;最后调用setup_vm函数创建临时页表,开启MMU,完成地址重定向,之后就跳转到C语言的start_kernel函数,正式开始内核初始化,汇编阶段就结束了。
整个流程逻辑清晰,没有多余的操作,所有步骤都是必须的,没有历史遗留的冗余代码。对比x86架构因为多年迭代留下来的各种兼容处理,还有ARM架构为了兼容不同版本旧内核留下的冗余逻辑,RISC-V作为新架构,启动流程完全从零开始设计,保留了最核心的逻辑,去掉了所有不必要的兼容处理,所以代码量非常小,执行速度也更快。这就是RISC-V架构设计“至繁归于至简”的最好体现——把几十年架构发展攒下来的历史包袱全部扔掉,只保留最必要的设计,反而得到了更高的效率。
四、RISC-V启动设计的思考:简洁开放胜过复杂标准
梳理完RISC-V的启动流程,我们能得到很多不一样的启发。RISC-V从诞生开始,就一直强调模块化和开放设计,这种思想在启动流程里体现得淋漓尽致。传统架构往往会制定非常复杂的强制标准,规定死每个阶段要做什么,地址要放在哪里,必须用什么流程,这种设计在成熟的生态里确实能保证兼容性,但也限制了灵活性,尤其是对于新兴的物联网、嵌入式场景,很多强制标准根本用不上,反而变成了负担。
而RISC-V只规定最核心的基础规则:复位从M模式开始,剩下的全部交给芯片设计者和软件开发者自己定义。需要复杂多阶段启动就做三级架构,不需要就直接一步到位;需要多启动模式就支持多种存储设备,不需要就只保留一种。这种设计思路让RISC-V从最简单的8位MCU,到复杂的服务器多核心CPU,都能适配,用同一套架构基础满足了完全不同的场景需求,这是传统架构很难做到的。
当然,这种灵活开放也不是没有缺点,因为缺乏统一的强制标准,不同厂商的RISC-V芯片启动流程差异比较大,开发的时候需要适配不同厂商的代码,一定程度上增加了开发工作量。但从长期发展来看,这种开放带来的收益远大于成本,它允许不同场景做不同的优化,不会为了统一标准牺牲性能和成本,对于现在越来越多元化的芯片场景来说,这种设计显然更符合未来的需求。
另外,RISC-V的启动设计也体现了开源生态的优势,所有启动代码都是开源的,开发者可以自由修改,根据自己的需求裁剪,不需要受闭源厂商的限制。比如我们做一个特殊的嵌入式产品,可以自己裁剪启动流程,把不需要的功能全部去掉,把启动时间压缩到几毫秒,满足实时启动的需求,这在传统闭源架构里是很难做到的。
很多人说RISC-V的优势就是开源免费,不用交授权费,但在我看来,RISC-V最大的优势其实是它全新的设计哲学,它吸收了过去几十年芯片架构发展的经验,扔掉了所有历史包袱,用最简洁的设计满足最广泛的需求。启动流程只是RISC-V设计的一个小小的切面,我们就能看到这种设计哲学的魅力:没有复杂的强制标准,只保留最核心的规则,把灵活性交给开发者,让不同场景都能找到最合适的实现方式。
随着RISC-V生态的不断发展,越来越多不同领域的芯片都开始采用RISC-V架构,这种简洁灵活的启动设计也会不断迭代,适配更多新的场景。但我相信,这种“简洁开放胜过复杂标准”的设计思路,会一直保留在RISC-V的基因里,也会给整个芯片行业带来更多启发,推动开源芯片生态走得更远。





