FPGA 部署Rocket Chip 跑Linux
在过去的四个月时间里,一直尝试着在FPGA部署RISC-V处理器,并运行Linux操作系统,基本浏览了全网这方面所有教程,git clone
,make
的技能炉火纯青。
在FPGA部署Rocket Chip并运行Linux主要有两种方式,一种是伯克利官方仓库fpga-zynq,它需要借助ARM,通过前端服务器Frontend Server和ARM交互,进行串口显示。另一种是不借助ARM。
一、借助ARM
如下图所示,ARM端运行了PetaLinux,通过执行./fesvr-zynq pk hello
ARM运行fesvr-zynq
前端服务器,将pk(非常小的内核)和hello(rv-gcc编译的hello程序)搬到RV内存的特定地址,RV核执行之后,会将打印的结果告诉fesvr,最后通过ARM的串口显示。
通过执行./fesvr-zynq bbl
也是类似原理,BBL是伯克利加载启动器,和OpenSBI有相同的作用,但比它更简化。bbl生成时,会加上payload选项,包入linux的Image镜像。此前Linux镜像生成时,也会包入简单根文件系统。这样就集齐了Linux运行的吉祥三宝:bootloader、kernel、root file system。
该工程已在ZC706的板子上复现,预编译的比特流文件似乎有点问题,需要重新生成才奏效。这个工程的缺点也比较明显:
- Rocket Chip子仓库不在主分支上,是2018年的旁支,版本比较旧。
- Vivado需要用2016.2版本,Ubuntu也最好是16版本,否则会报莫名的版本错误。
- 需要借助ARM,不纯粹。
借助ARM运行RV Linux的工程还有几个:
- rc-fpga-zcu, vivado 2017.1 , ZCU102
- boom-riscv, vivado 2018.2 , ZC706
- labeled-RISC-V, vivado 2019.1, ZCU102
二、不借助ARM
Z系列的板子都会带ARM,还找到一些不借助ARM,直接从SD卡启动的工程,也做了一些比较:
开源项目 | 更新频率 | 支持开发板 | 复现难度 |
---|---|---|---|
Chipyard | 活跃 | VCU118 | 难 |
fpga-rocket-chip | 三年前 | Nexys A7 100T | 易 |
lowrisc-chip | 四年前 | Nexys A7 100T | 中 |
rocket-chip-vcu128 | 半年前 | VCU128 | 中 |
vivado-risc-v | 活跃 | KC705,VC707,Nexys A7 100T | 易 |
最终选择了最后一个仓库复现,社区很活跃,子仓库也是最新的,以打补丁的形式修改OpenSBI、Uboot、Linux kernel,容易进一步学习。
但要成功复现也不是想象中那么简单,运行环境如下:
- Ubuntu 20 LTS ,32G内存
- Vitis 2020.1以上
自己的虚拟机虽然是Ubuntu20,但只有8G内存。服务器虽然有32G内存,但Ubuntu是18.04,而且生成SD卡也不能在服务器上。这种因为环境造成的尬尴,Docker是最佳选择!
基本思路是,服务器装一个Ubuntu20的Docker环境,用来生成比特流文件;本地虚拟机用来生成SD卡需要的吉祥三宝:bootloader、linux kernel、root file system。
1、比特流文件
Docker的入门可以参考之前的博客 Docker 入门+实战
docker pull ubuntu:20.04
# 挂载整个工作目录,包含vivado软件
docker run -it --name yourname --user -v /home/username/:/home ubuntu:20.04
之后按照github上的流程安装好相关的依赖软件make apt-install
,make update-submodules
。最后选择kc705的板子
source /opt/Xilinx/Vivado/2020.1/settings64.sh
make CONFIG=rocket64b2 BOARD=kc705 bitstream
生成好的比特流文件会在workspace目录下的vivado工程里,之后需要通过本地的vivado烧到板子上。
有意思的一点是,生成的过程中,设备树文件会合并到bootrom.img,然后作为固件一起烧进比特流文件。
2、SD卡准备
准备好SD卡,大卡小卡皆可,运行./mk-sd-card
,主要流程是先下载Debian发行版的根文件系统,再分别生成uboot、opensbi、Linux kernel。opensbi会payload uboot,生成boot.elf和kernel一起放到SD卡的第一个分区,根文件系统放到SD卡的第二个分区。
最后写SD卡的过程会遇到一些错误,可以查看 issues 23:老显示SD占用,写不进数据, 需要手动umount /media/xxx/BOOT and rootfs 然后重新 ./mk-sd-card
。
3、最后一难
将SD卡插入卡槽,用vivado将bit流文件烧进板子,连接好串口,期待神圣的时刻:发现串口无打印!查看手册,发现是SW13的设置出错了,改成默认就行。
最后,见证奇迹的时候:
虽然代码不是我写的,移植不是我做的,但看到起来的那一刻,也是热泪盈眶。接下来,盘它!
//纪念第100篇灌水博文