#### 参考资料

[FU540-C000-v1.0](https://static.dev.sifive.com/FU540-C000-v1.0.pdf)

[Getting-Started-Guide](https://static.dev.sifive.com/HiFive-Unleashed-Getting-Started-Guide-v1p1.pdf)

#### 简介

HiFive Unleashed是U540 Soc的Linux开发平台，是一个多核RISC-V SoC。硬件配置如下：

| 硬件         | 属性                                       | 手册对应章节 |
| ------------ | ------------------------------------------ | ------------ |
| 内存         | 8G DDR4                                    | 5, 12, 20    |
| 以太网端口   | 千兆                                       | 19           |
| JTAG接口     | 用于调试                                   | 23, 34       |
| ChipLink     | TileLink协议的片外串行化                   | 22           |
| SD卡槽       |                                            |              |
| PCIe         | FMC + 低速I/O扩展                          |              |
| E51 Core 0   | RV64IMAC，(M,U mode)，监控核               | 3            |
| U54 Core 1-4 | RV64GC，(M,S,U mode)，应用核               | 4            |
| L2 cache     | 2M                                         | 11           |
| 中断         | 平台级中断控制器PLIC，计时器中断，软件中断 | 8, 9, 10     |
| 串口         | uart0, uart1                               | 13           |
| QSPI 0-3     | 串行外部接口                               | 16           |
| PWM 0-1      | 脉冲宽度调制器                             | 14           |
| I2C 0        | 集成电路控制器                             | 15           |
| GPIO         | 通用I/O引脚                                | 17           |
| OTP          | 一次可编程存储器                           | 18           |

需要：开发板，USB线，电源适配器，可选配网线或FMC扩展卡

#### 时钟和复位(手册第7章)

时钟和复位是通过电源复位时钟中断(PRCI)架构来管理的。

#### 启动过程(手册第6章)

FU540-C000支持从多种源来启动，这是通过模式选择(MSEL[3:0])引脚来实现的。而3个QSPI接口则控制从哪里下载media(SPI flash或SD卡)。

| MSEL | FSBL的位置     | BBL的位置      | 作用                              |
| ---- | -------------- | -------------- | --------------------------------- |
| 0000 | -              | -              | 无限循环等待调试                  |
| 0001 | -              | -              | 跳至0x2000_0000(内存映射OSPI0)    |
| 0010 | -              | -              | 跳至0x3000_0000(内存映射OSPI1)    |
| 0011 | -              | -              | 跳至0x4000_0000(未缓存的ChipLink) |
| 0100 | -              | -              | 跳至0x6000_0000(缓存的ChipLink)   |
| 0101 | QSPI0 x1 flash | QSPI0 x1 flash | -                                 |
| 0110 | QSPI0 x4 flash | QSPI0 x4 flash | 从flash 获取镜像                  |
| 0111 | QSPI1 x4 flash | QSPI1 x4 flash | -                                 |
| 1000 | QSPI1 x1 SD    | QSPI1 x1 SD    | -                                 |
| 1001 | QSPI2 x1 flash | QSPI2 x1 flash | -                                 |
| 1010 | QSPI0 x4 flash | QSPI1 x1 SD    | -                                 |
| 1011 | QSPI2 x1 SD    | QSPI2 x1 SD    | 从SD卡获取镜像                    |
| 1100 | QSPI1 x1 flash | QSPI2 x1 SD    | -                                 |
| 1101 | QSPI1 x4 flash | QSPI2 x1 SD    | -                                 |
| 1110 | QSPI0 x1 flash | QSPI2 x1 SD    | -                                 |
| 1111 | QSPI0 x4 flash | QSPI2 x1 SD    | 默认启动模式                      |

##### 1. 复位向量

一加电，所有的核都跳到ROM 0x1004处执行，ROM中的内容如下：

```
0x1000	MSEL的值
0x1004	auipc t0, 0		# t0保存了当前指令的地址，即0x1004
0x1008	lw t1, -4(t0)	# t1保存的内存0x1000的值，即MSEL的值
0x100c	slli t1, t1, 0x3	# t1 = t1 << 3，即8*t1
0x1010	add t0, t0, t1		# t0 += t1
0x1014	lw t0, 252(t0)	# t0保存的内存地址0x1000+0x100+8*MSEL处的值
0x1018	jr t0			# 实际上最终跳转的位置由MSEL的值决定
```

当MSEL>4的时候，均是跳转到ROM 0x1_0000处执行，即ZSBL。

##### 2. ZSBL

ZSBL是零阶段的引导程序，它负责从GPT下载FSBL。编号为0的核首先配置时钟分频器，然后寻找GUID为`5B193300-FC78-40CD-8002-E86C45580B47`的分区。它首先下载GPT头(位置在512字节～604字节)，然后依次扫描分区表直到找到分区，接下来将该分区的内容(即FSBL)下载到内存0x0800_0000处，最后跳转到该地址执行。

ZSBL是通过MSEL的值来决定FSBL所在的分区的。

##### 3. FSBL

FSBL是第一阶段的引导，它负责将内核载入内存。

- 通过配置和运行片上PLL将频率提升至1GHz。
- 配置DDR PLL，以太网PHY和控制器。
- 设置GEM，GXL，TX，PLL为125MHz并重置之。
- 如果有外部PHY，重置之。
- 从GUID号为`2E54B353-1271-4842-806F-E436D6AF69851`的分区下载BBL。
- Scan OTP for the chip serial number
- 将DTB复制到内存
- 跳转到`0x8000_0000`

FSBL通过MSEL的值来寻找BBL所在的分区。

##### 4. BBL

BBL在`0x8000_0000`，它提供SBI并模拟RISC-V指令。Linux在`0xffff_ffe0_0000_0000`处。

##### 5. 启动方法

- Flash Bit-Banged x1
- Flash 内存映射x1
- Flash 内存映射x4
- SD卡Bit-Banged x1

#### 软件开发流程

1. 安装需要的包

   ```shell
   sudo apt-get install autoconf automake autotools-dev bc bison \
   build-essential curl flex gawk gdisk git gperf libgmp-dev \
   libmpc-dev libmpfr-dev libncurses-dev libssl-dev libtool \
   patchutils python screen texinfo unzip zlib1g-dev
   ```

2. 安装free-u-sdk

   ```shell
   git clone https://github.com/sifive/freedom-u-sdk.git
   cd freedom-u-sdk
   git submodule update --init --recursive
   unset RISCV
   make
   ```
   编译时问题解决：

   - `Unescaped left brace in regex is illegal here in regex; marked by <-- HERE in m/\${ <-- HERE (\[^ \t=:+{}]+)}/ at /data/szx/Code/freedom-u-sdk/work/buildroot_initramfs/host/usr/bin/automake line 3936.`

     以上问题的解决方法：给大括号转义，变成如下形式`\{`

   - `./../misc/create_inode.c:395:18: error: conflicting types for ‘copy_file_range’`

     以上问题的解决方法：这是由于自定义函数和库函数重名了，解决方法就是给自定义函数换个名字。首先，通过grep命令找到所有定义和使用了copy_file_range函数的地方，然后把所有的copy_file_range函数更名为copy_file_chunk。2个文件共计8处需要修改。

   > 编译完毕，显示如下信息：
   >
   > This image has been generated for an ISA of rv64imafdc and an ABI of lp64d
   > Find the image in work/bbl.bin, which should be written to a boot partition
   >
   > To completely erase, reformat, and program a disk sdX, run:
   >   sudo make DISK=/dev/sdX format-boot-loader
   >   ... you will need gdisk and e2fsprogs installed

3. 把镜像复制到SD卡

   ```
   sudo umount /dev/exb	# 假设SD卡名叫exb,先要从文件系统中卸载掉
   sudo gdisk /dev/exb		# 为exb创建GPT
   # p打印分区信息，d删除分区，o清除所有分区数据，w写数据(即将更改作用于设备)
   sudo make DISK=/dev/exb format-boot-loader	# 将系统写入SD卡
   ```
   写卡时的问题与修复：

   - 写低速SD卡有可能会失败，多重复几次即可成功。

4. 在开发板上运行镜像

   1. 拔电源，关开关。(关开关并不能代替拔电源。)
   2. 确保风扇已连接。
   3. 将DIP开关拔到左边(左边为1,右边为0)，使MSEL处于1111模式。这是默认的启动模式。
   4. 插入安装了BBL+Linux的SD卡。
   5. 连接网线和USB线。
   6. 插上电源，风扇开始转动。
   7. 打开开关，30秒后LED灯开始闪烁。

   有两种方式连到开发板，ssh和串口。串口慢且不能接收文件，应尽量选择ssh方式。

   - ssh连接

     电源开启后，默认的freedom-u-sdk镜像会通过DHCP获取IP地址，并开启ssh服务。

     `ssh root@ip地址`登陆，密码：sifive

   - USB连接

     `sudo screen /dev/ttyUSB1 115200`

     用户名：root，密码：sifive

5. 在qemu中运行镜像

   `make qemu`

   编译时问题的解决：

   - `Unescaped left brace in regex is illegal here in regex; marked by <-- HERE in m/\${ <-- HERE ([^ \t=:+{}]+)}/ at /data/szx/Code/freedom-u-sdk/work/buildroot_rootfs/host/usr/bin/automake line 3936.`

     以上问题的解决方法依然是给大括号转义。

   - `./../misc/create_inode.c:395:18: error: conflicting types for ‘copy_file_range’`

     以上问题的解决方法依然是给本地函数重命名。

#### 连接器引脚分配

##### FMC

FPGA Mezzanine Card

##### 低速I/O扩展

##### MicroUSB

##### SD卡

##### JTAG
