FPGA 调试指引
很多客户拿到我们的 CPU 会第一时间做 FPGA 集成测试,根据本指引客户无需编译软件,即可直接用 run.sh 启动 Linux。而对硬件要求仅仅是 CPU + DDR 内存即可,run.sh 运行 Linux 包含以下内容:
- run.sh 介绍
- ddrinit.fpga.txt
- gdbinit.fpga.txt
- fpga.dts.txt
fpga 就是客户自定义的最小 soc 系统,需要客户自己建立 ddrinit.fpga.txt gdbinit.fpga.txt fpga.dts.txt 文件
run.sh 介绍
run.sh <ip地址:端口> <硬件板类型> <cpu数量>
举例:
run.sh 127.0.0.1:1025 fpga 1
run.sh 脚本做以下事情:
- 获取 rootfs.cpio.gz 的大小,并以此设置设备树文件的 initrd-start, initrd-end 字段
- 按需要运行 ddrinit.[board].txt 初始化程序,配置时钟,DDR
- 运行 gdbinit.[board].txt 下载 rootfs.cpio.gz, hw.dtb, Image 到内存
- 设置 pc 到指定内存执行
ddrinit.fpga.txt 介绍
cat ddrinit.ice_fpga.txt
# Set gdb environment
set height 0
# Don't confirm when quit
set confirm off
set *0x3fff78040 = 0xffff # xillinx FPGA 初始化 DDR PPL
shell $(sleep 3)
ddrinit 负责初始化 DDR 内存,PPL 等 soc 基础设置,请客户根据自己的情况自行调整
gdbinit.fpga.txt 介绍
➜ hw cat gdbinit.ice_fpga.txt
set confirm off
set height 0
# Invalidate & Clear IBP BTB BHT ICache & DCache
set $mcor = 0x70013
# Enable L2 Cache
set $mccr2 = 0xe0010009
# Enable L1 Cache
set $mhcr = 0x11ff
# Enable CPU Features
set $mxstatus = 0x638000
set $mhint = 0x16e30c
# 0x00000000 ~ 0x2 00000000 DDR, NAPOT rwx
set $pmpaddr0 = 0x0 >> 2 | ((0x200000000 - 1) >> 3)
# 0x3 f0000000 ~ 0x3 f8000000 plic, NAPOT rw
set $pmpaddr1 = 0x3f0000000 >> 2 | ((0x8000000 - 1) >> 3)
# 0x3 f8000000 ~ 0x4 00000000 peripherals, NAPOT rw
set $pmpaddr2 = 0x3f8000000 >> 2 | ((0x8000000 - 1) >> 3)
# 0x00000000 ~ 0x10000000 NAPOT no access
set $pmpaddr6 = 0x00000000 >> 2 | ((0x10000000 - 1) >> 3)
# 0x10000000 ~ 0x10000000000 TOR no access
set $pmpaddr7 = 0xffffffffff >> 2
# Be care! we must put background deny entries in the end of
# pmpaddrx with lowest priority and set lock bit for m state deny.
# Access needn't lock bit for the m state.
set $pmpcfg0 = 0x88980000001b1b1f
set $opensbi_addr = 0x00000000
set $vmlinux_addr = $opensbi_addr + 0x00200000
set $rootfs_addr = $opensbi_addr + 0x02000000
set $dtb_addr = $rootfs_addr - 0x00100000
# Load rootfs
restore ../rootfs.cpio.gz binary $rootfs_addr
# Load dtb
restore hw.dtb binary $dtb_addr
set $a1 = $dtb_addr
# Load kernel
restore ../Image binary $vmlinux_addr
# Load opensbi
restore fw_jump_0G.bin binary $opensbi_addr
set $pc = $opensbi_addr
gdbinit 是 CPU 通用设置,一般不需要客户修改,对于 910 客户依然需要正确设置 PMP,PMP 是对物理内存的权限管理寄存器,根据自身 IP 地址分布进行设置,一般需要设置 DDR 区域,PLIC 区域,外设 IO 区域,根据 riscv 规范可以用 NAPOT 和 TOR 两种方式。
fpga.dts.txt
/dts-v1/;
/ {
model = "T-HEAD c910 fpga";
compatible = "thead,c910_fpga";
#address-cells = <2>;
#size-cells = <2>;
memory@0 {
device_type = "memory";
reg = <0x0 0x200000 0x0 0xffe00000>;
};
cpus {
#address-cells = <1>;
#size-cells = <0>;
timebase-frequency = <6250000>;
cpu@0 {
device_type = "cpu";
reg = <0>;
status = "okay";
compatible = "riscv";
riscv,isa = "rv64imafdcvsu";
mmu-type = "riscv,sv39";
cpu0_intc: interrupt-controller {
#interrupt-cells = <1>;
compatible = "riscv,cpu-intc";
interrupt-controller;
};
};
cpu@1 {
device_type = "cpu";
reg = <1>;
status = "fail";
compatible = "riscv";
riscv,isa = "rv64imafdcvsu";
mmu-type = "riscv,sv39";
cpu1_intc: interrupt-controller {
#interrupt-cells = <1>;
compatible = "riscv,cpu-intc";
interrupt-controller;
};
};
};
soc {
#address-cells = <2>;
#size-cells = <2>;
compatible = "simple-bus";
ranges;
intc: interrupt-controller@3f0000000 {
#interrupt-cells = <1>;
compatible = "riscv,plic0";
interrupt-controller;
interrupts-extended = <
&cpu0_intc 0xffffffff &cpu0_intc 9
&cpu1_intc 0xffffffff &cpu1_intc 9
>;
reg = <0x3 0xf0000000 0x0 0x04000000>;
reg-names = "control";
riscv,max-priority = <7>;
riscv,ndev = <80>;
};
dummy_apb: apb-clock {
compatible = "fixed-clock";
clock-frequency = <50000000>;
clock-output-names = "dummy_apb";
#clock-cells = <0>;
};
serial@3fff73000 {
compatible = "snps,dw-apb-uart";
reg = <0x3 0xfff73000 0x0 0x400>;
interrupt-parent = <&intc>;
interrupts = <23>;
clocks = <&dummy_apb>;
clock-names = "baudclk";
reg-shift = <2>;
reg-io-width = <4>;
};
};
chosen {
bootargs = "console=ttyS0,115200 crashkernel=256M-:128M";
linux,initrd-start = <0x0 0x2000000>;
linux,initrd-end = <0x0 0x0>;
stdout-path = "/soc/serial@3fff73000:115200";
};
};
以上就是最小系统 dts 配置,(最多双核),几点注意:
- cpus -> timebase-frequency 用于设置 cpu 紧耦合 timer 定时器的频率
- riscv,isa = "rv64imafdcvsu" 用于设置 cpu ISA 类型,如果 c910 不配置 vector 模块,请把 v 字母去掉
- intc: interrupt-controller -> compatible = "riscv,plic0"; 需要根据 soc 地址分布正确设置它的 IO 地址空间
- dummy_apb: apb-clock 是设置提供串口 IP 的频率,这里取 apb 总线频率,串口驱动根据该设置,换算出正确的波特率
设置好以上三个文件,就可以尝试 bash run.sh 127.0.0.1:1025 fpga 1 了,如果串口没打印,参考上一章节 利用 Jtag 获取 dmesg,祝你调试愉快