fpga-pynq/README.md

359 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Rocket Chip在ZYNQ上的实现
该仓库包含在Vivado 2016.2上的各种Zynq FPGA开发板ZyboZedboardZC706PYNQ-z2上运行RISC-V rocket chip所需的文件。 因为Vivado版本问题推荐使用Ubuntu16.04操作系统)
### 如何使用该README
该README主要包含4部分
[0 - 前言](#foreword):简单介绍该工程的原理。
[1 - 快速开始](#quickinst)使用编译好的文件极速上手无需下载各种工具在windows操作系统上即可完成。如果您只是想用该系统测试RISC-V程序或者验证该系统的功能就不必进行以下步骤。如果您需要修改rocket-chip RISC-V核、修改FPGA电路结构或者修改ARM linux内核配置等等那么以下步骤有助于熟悉一整套工作流程。
[2 - RISC-V工具链riscv-tools编译](#toolchain)安装RISC-V工具链用于编译rocket chip生成RISC-V核。
[3 - 工程编译的详细步骤](#compile):从头开始一步步编译整个工程。
[附录](#appendices):主机和开发板传输文件的方法。
注:以下的`$REPO`均代表`fpga-pynq`仓库所在的本地目录建议执行以下命令将REPO加入环境变量替换仓库在本地的目录
```
$ export REPO=仓库在本地的目录
```
## 目录
+ [0 - 前言](#foreword)
+ [1 - 快速开始](#quickinst)
+ [2 - RISCV工具链riscv-tools编译](#toolchain)
+ [3 - 工程编译的详细步骤](#compile)
+ [创建工程](#setup)
+ [生成比特流文件](#bitstream)
+ [编译FSBL](#fsbl)
+ [编译u-boot](#u-boot)
+ [Building u-boot for the Zynq ARM Core](#u-boot)
+ [创建boot.bin](#boot.bin)
+ [编译zynq ARM的linux内核](#arm-linux)
+ [生成设备树文件](#arm-dtb)
+ [启动](#booting)
+ [附录](#appendices)
+ [说明](#note)
## 0)<a name="foreword"></a> 前言
#### 1Zynq相关的基础知识
Zynq-7000系列基于赛灵思SoC架构在一个芯片上集成了双核或单核ARM Cortex A9的处理系统PS和赛灵思可编程逻辑PL
##### 1.1Zynq的一般启动流程此处仅介绍非安全模式、不用JTAG的启动方式
1.1.1由于刚刚上电Zynq的PL部分没有被初始化所以首先要启动PS端的ARM核执行BootROM代码。ARM核内部的BootROM存储第0阶段启动代码这段代码的功能是配置一个ARM核并从其中一个启动设备NAND、NOR、SD flash中加载FSBLFirst Stage Bootloader到片上内存OCMon-chip memory加载到片上内存的FSBL的大小在192KB以内。
1.1.2然后执行FSBL。FSBL的功能是对PS的外设初始化如果提供了PL部分的bitstream会用它初始化PL部分加载第二阶段BootLoader或者裸机应用程序到DDR内存中然后跳转到DDR内存中执行。在该工程中FSBL烧写bitstream、加载u-boot、跳转到u-boot执行
1.1.3然后执行u-boot代码将linux内核、文件系统、设备树加载到内存中启动linux操作系统。
##### 1.2Zynq bitstream的本地烧写方法
1.2.1通过FSBL烧写bitstream前面已经介绍。该工程采用此种方式
1.2.2通过u-boot烧写bitstream将bitstream加载到内存中然后使用fpga loadb对PL进行编程例如
```
U-Boot> fatload mmc 0 0x4000000 bitstream.bit
U-Boot> fpga loadb 0 0x4000000 <bitstream file size>
```
1.2.3通过linux烧写bitstream启动Linux后将bitstream文件写入devcfg设备即可对PL进行编程例如
```
$cat bitstream.bit > /dev/xdevcfg
```
#### 2Rocket chip
Rocket Chip是基于Chisel开发的一款开源SoC生成器它包含了由RISC-V corecache以及互连interconnect等构成的模块库以此为基础构成一个完整的SoC并可以生成可综合的RTL代码。
#### 3前端服务器FESVR : Front-End Server
FESVR是一个C ++库用于管理主机和rocket chip之间的通信。为了调试它提供了一个简单的API来复位发送数据以及在rocket chip上加载、运行程序。 具体来说FESVR使用主机目标接口HTIF一种通信协议与rocket chip通信。HTIF是一种非标准的伯克利协议它使用FIFO非阻塞接口进行通信。可以使用HTIF协议读、写rocket chip的内存加载、启动、停止程序等等。
#### 4RISCV代理内核RISCV-PK
RISC-V代理内核是一个运行在RISC-V端的轻量级应用程序执行环境可以运行静态链接的RISC-V ELF二进制文件。它将与IO相关的系统调用代理到主机在本工程中指的是ARM端的linux系统来处理。
#### 5该工程执行RISC-V程序的原理
内存分配pynq-z2开发板有512MB DDR3内存其中一半256MB分配给ARM的linux使用一半分配给rocket chip使用。
启动ARM linux之后通过运行在linux上的前端服务器加载代理内核pk和可执行程序hello到rocket chip的内存中加载完后前端服务器发送复位信号给rocket chip启动代理内核然后代理内核执行hello程序将hello程序与IO相关的系统调用主要是终端打印代理到主机处理hello程序执行完后代理内核发送信号通知前端服务器结束执行。
1)<a name="quickinst"></a> 快速开始
------------------
*用预先编译好的镜像运行hello world程序在rocket chip上 (注:此环节无需安装任何工具)*
1点击[fpga-pynq](https://gitee.com/huozf123/fpga-pynq)打开该仓库主页,然后依次点击*克隆/下载 -> 下载ZIP*,将该仓库文件(不带子模块)下载到本地,然后解压该文件。
2格式化SD卡文件系统格式为FAT32将`$REPO/pynq-z2/fpga-images-pynq`目录下的四个文件拷贝至SD卡。
3弹出SD卡将其插入开发板将开发板的启动跳线设置为“SD”然后打开开发板的电源。 使用网线连接电脑和开发板打开电脑终端用SSH登录ARM端的linux系统用户名密码均为*root*并在rocket chip上运行hello程序
$ ssh root@192.168.1.5
root@zynq:~# ./fesvr-zynq pk hello
hello!
这一步需要提前将电脑有线网卡IP地址设置为192.168.1.*0<\*<256且不为5即和192.168.1.5同一网段且不为192.168.1.5子网掩码设置为255.255.255.0
## 2)<a name="toolchain"></a> RISCV工具链riscv-tools编译
1克隆整个工程到本地
为了方便大家快速获取源码已将全部源码包括子模块打包上传到百度网盘可以直接下载。(网盘中的工程版本不是最新版本少量最新的改动可能没有包含进来可以直接从gitee手动下载zip然后把新文件放进去即可
```
链接https://pan.baidu.com/s/1mTCcKG0EiFdxq4C5HTey3w
提取码1234
```
```
$ cat fpga-pynq.0* > fpga-pynq.tar.gz #组装文件
$ md5sum fpga-pynq.tar.gz > md5 #计算MD5校验码
$ cmp md5 md5sum #比对校验码,如果此处没有任何输出,则为正确
$ tar -zxvf fpga-pynq.tar.gz #解压文件
```
或者从github获取源码
```
$ git clone https://github.com/huozf123/fpga-pynq.git
$ cd fpga-pynq
$ git submodule update --init --recursive #快速开始不需要执行该指令,自己编译工程才需要
```
如果机器上已经有编译好的工具链则只需将其加入环境变量即可这一步可以跳过
2安装依赖
```
$ sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev libusb-1.0-0-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev device-tree-compiler pkg-config libexpat-dev
```
3编译工具链此处需要指定工具链要安装的目标路径绝对路径
此处需要GCC版本>=4.8,详情请参照[README](https://github.com/riscv/riscv-tools#readme)。)
```
$ export RISCV=工具链要安装的目的路径
$ export PATH=${RISCV}/bin:$PATH
$ cd $REPO/rocket-chip/riscv-tools/
$ ./build.sh
```
3)<a name="compile"></a> 工程编译的详细步骤
-------------------------
*前提安装好的Vivado 2016.2 一个可以运行scala代码的JVM测试使用的java版本为1.8.0_271如果编译rocket chip过程中遇到java错误可能是java版本的原因*
首先添加Vivado相关的环境变量执行替换掉“你的vivado安装目录”
```
$ source 你的vivado安装目录/Vivado/2016.2/settings64.sh
$ source 你的vivado安装目录/SDK/2016.2/settings64.sh
```
因为Vivado、SDK存在bug所以需要执行以下命令替换“你的vivado安装目录”
```
$ sudo apt-get install libgoogle-perftools-dev
$ export SWT_GTK3=0
$ sudo sed -i "11,15s/^/#/" 你的vivado安装目录/Vivado/2016.2/.settings64-Vivado.sh #注释该文件第11-15行
```
然后初始化子模块,执行:
$ cd $REPO/pynq-z2/
$ make init-submodules
### 3.1) <a name="setup"></a> 创建工程
首先,执行如下命令生成工程。 (注:运行期间请保持网络畅通)
$ cd $REPO/pynq-z2/
$ make project
### 3.2) <a name="bitstream"></a> 生成比特流文件
然后我们通过如下命令打开vivado:
$ make vivado
然后点击左下角的*Generate Bitstream*按钮, Vivado将自动生成比特流文件。该文件位置为
`$REPO/pynq-z2/pynq_rocketchip_ZynqFPGAConfig/pynq_rocketchip_ZynqFPGAConfig.runs/impl_1/rocketchip_wrapper.bit`
下一步,点击*File -> Export -> Export Hardware*。这将创建以下目录:
`$REPO/pynq-z2/pynq_rocketchip_ZynqFPGAConfig/pynq_rocketchip_ZynqFPGAConfig.sdk`
该目录包含的各种文件向SDK提供有关硬件的信息。
### 3.3) <a name="fsbl"></a> 编译FSBL
在Vivado界面点击*File -> Launch SDK* 打开SDK
1) 点击 *File -> New -> Application Project*
2) 在弹出的新窗口中输入FSBL作为Project name其他项保持默认
3) 点击*Next*,然后依次点击*Zynq FSBL* 和*Finish*。然后SDK将继续自动编译FSBL。
4) 编译完成后,继续下一步。
### 3.4) <a name="u-boot"></a> 编译u-boot
打开一个新的终端,进入目标开发板的目录,执行如下命令:
$ source 你的vivado安装目录/Vivado/2016.2/settings64.sh
$ source 你的vivado安装目录/SDK/2016.2/settings64.sh
$ export REPO=repo在本地的目录
$ cd $REPO/pynq-z2/
$ make arm-uboot
编译好的u-boot所在位置为`$REPO/pynq-z2/soft_build/u-boot.elf`。
### 3.5) <a name="boot.bin"></a> 创建boot.bin
回到SDK界面点击 *Xilinx Tools -> Create Zynq Boot Image*
1) 点击*Output BIF file path*后面的*Browse..*,然后找到并选择`$REPO/pynq-z2/deliver_output`。
2) 点击右下角的*Add*,并在弹出的对话框中点击*Browse*找到如下文件First Stage BootLoader
`$REPO/pynq-z2/pynq_rocketchip_ZynqFPGAConfig/pynq_rocketchip_ZynqFPGAConfig.sdk/FSBL/Debug/FSBL.elf`
*Partition type*选择bootloader然后点击*OK*。
3) 再一次点击 *Add*,并在弹出的对话框中点击*Browse*找到如下文件bitstream
`$REPO/pynq-z2/pynq_rocketchip_ZynqFPGAConfig/pynq_rocketchip_ZynqFPGAConfig.runs/impl_1/rocketchip_wrapper.bit`
*Partition type* 选择datafile然后点击*OK*。
4) 再一次点击 *Add*,并在弹出的对话框中点击*Browse*找到如下文件uboot
`$REPO/pynq-z2/soft_build/u-boot.elf`
*Partition type* 选择datafile然后点击*OK*。
5) 点*Create Image*。这将产生 `BOOT.bin` 文件在 `$REPO/pynq-z2/deliver_output` 目录下。
进行完以上5个步骤之后如果再次修改其中的文件通过如下命令快速生成boot.bin文件最终写入到SD卡中的boot.bin文件名不区分大小写
$ cd $REPO/pynq-z2/
$ make deliver_output/boot.bin
### 3.6) <a name="arm-linux"></a> 编译zynq ARM的linux内核
然后编译linux内核
$ cd $REPO/pynq-z2/
$ make arm-linux
### 3.7) <a name="arm-dtb"></a> 生成设备树文件
生成linux的dtb
$ make arm-dtb
### 3.8) <a name="booting"></a> 启动
此时,`$REPO/pynq-z2/deliver_output` 目录下包含如下文件:
* `BOOT.bin` - 包含FSBL、bitstream、u-boot。
* `uImage` - zynq ARM端的Linux内核。
* `devicetree.dtb` - Linux需要的设备树文件。
* `uramdisk.image.gz` - ARM linux的文件系统。
最终只需将linux根文件系统复制到该目录下即可完成SD卡内所有文件的准备工作进入目标开发板的目录执行
$ cd $REPO/pynq-z2/
$ cp fpga-images-pynq/uramdisk.image.gz ./deliver_output/
现在将`deliver_output/`中的如下四个文件拷贝到SD卡中然后将SD卡插入到pynq-z2开发板中将开发板右上角跳线帽调整到SD端即从SD卡启动。SD卡内的目录结构如下
SD_ROOT/
|-> boot.bin
|-> devicetree.dtb
|-> uImage
|-> uramdisk.image.gz
此时已经完成了所有工作,打开开发板电源,使用网线(用户名密码均为*root*连接至开发板并运行hello程序
$ ssh root@192.168.1.5
root@zynq:~# ./fesvr-zynq pk hello
hello!
<a name="appendices"></a> 附录
------------
### 主机与开发板传输文件
#### 通过以太网传输文件
最简单的方法使用scp在线传输文件
$ scp file root@192.168.1.5:~/
注意:上电期间对文件系统的修改不会自动写入`uramdisk.image.gz`文件中,如需永久修改文件系统参见如下:
#### 修改linux文件系统
1首先需要安装uboot tools
```
sudo apt-get install u-boot-tools -y
```
2将SD卡通过读卡器插入主机。
3解压文件系统
$ cd $REPO/pynq-z2
$ make ramdisk-open
解压后的文件系统位置为:`$REPO/pynq-z2/ramdisk`,可以在此处修改文件系统中的文件。
(注:如果执行时出现`make: *** [fpga-images-pynq/boot.bif] Error 128`错误,请执行`cp ../zedboard/fpga-images-zedboard/boot.bif ./fpga-images-pynq/`命令)
4修改完成后压缩文件系统覆盖旧的文件系统
$ cd $REPO/pynq-z2/
$ make ramdisk-close
(注:文件系统的位置为:`$REPO/pynq-z2/fpga-images-pynq/uramdisk.image.gz`该文件大小不能超过10MB否则无法启动
5将文件系统`$REPO/pynq-z2/fpga-images-pynq/uramdisk.image.gz`拷贝到SD卡。
#### 通过给sd卡分区并自动挂载到arm linux文件系统中实现永久存储掉电不丢失
如果本地仓库没有$REPO/sd-partition这个目录则需要进入[这里](https://gitee.com/hustos/fpga-pynq/raw/master/sd-partition/get-files.png)点击“下载zip”
![](https://gitee.com/hustos/fpga-pynq/raw/master/sd-partition/get-files.png)
下载好后将文件传到ubuntu系统中并解压并将该目录复制到本地仓库中。
1先给sd卡分区可以在windows下分成两个区或在ubuntu系统下使用fdisk工具分区为了方便起见特地制作了sd卡分区脚本只需要把sd卡接到ubuntu系统执行以下命令即可
*注意:第二行命令的"/dev/sd?"要改为自己sd卡所在的路径我的路径为"/dev/sdc"分区后sd卡内容会全部丢失请提前做好备份一定要检查无误后再执行*
```
$ cd $REPO/sd-partition
$ ./make-fs.sh /dev/sd?
```
2此时sd卡有两个分区第一个分区不到100M另一个分区是剩下的空间第一个分区里面要放置四个文件*boot.bin devicetree.dtb uImage uramdisk.image.gz*第二个比较大的分区放置自己要挂载到arm linux系统上的文件。
*说明arm linux的根文件系统做了少许改动自动挂载sd第二个分区添加软连接在`/home/root/sd-card`以快速访问该分区),改动后文件位于[$REPO/sd-partition/uramdisk.image.gz](https://gitee.com/hustos/fpga-pynq/blob/master/sd-partition/uramdisk.image.gz)*
## <a name="note"></a> 说明
此工程基于[fpga-zynq](https://github.com/ucb-bar/fpga-zynq),如果需要更加深入的了解,请参考[fpga-zynq](https://github.com/ucb-bar/fpga-zynq)。