接着上一篇:手把手教你在FPGA上移植NVDLA+Tengine并且跑通任意神经网络(1)
这一篇将主要讲述如何移植ubunt16.04根文件系统+linux4.19内。并且在ZC706 FPGA上正确的加载驱动。经过上文在VIVADO SDK中的验证我们已经可以确定NVDLA模块的功能正确性。但是在日常应用中,需要拥有人机交互和自动配置的需求,官方开源了整套的SW软件栈。那么移植OS操作系统并且移植KMD是我们绕不开的一步了。
Petalinux是Xilinx公司推出的嵌入式Linux开发套件,包括了Linux Kernel、u-boot、device-tree、rootfs等源码、库,以及Yocto recipes,可以让客户很方便的生成、配置、编译及自定义。Petalinux支持Zynq UltraScale+ MPSoC、Zynq-7000全可编程SoC,以及MicroBlaze,可与Xilinx硬件设计工具Vivado协同工作,大大简化了Linux系统的开发工作。
使用PetaLinux工具,开发人员可以定制u-boot、Linux内核或Linux应用,开发者还可以通过网络或JTAG在随附的全系统仿真器 (QEMU) 或物理硬件上添加新的内核、器件驱动程序、应用和库,以及启动并测试软件协议栈,完成从系统启动到执行的所有操作。在主机端提供的PetaLinux工具包括:
上文VIVADO用到是2019.1版本,这里Petalinux应该用和VIVADO同样的版本否则会出现想不到的bug。
Petalinux2019.1安装教程:https://blog.csdn.net/mcupro/article/details/91973744
Petalinux 2019.1 对应的 linux 版本是4.19知道这一点非常重要。因为官方提供的Linux版本为4.13,很多库函数的接口API有所变动。所以应当相应位置上做出更改,否则内核加载会不成功。具体修改部分请看后文。
(petalinux) tjx@tjx-virtual-machine:~/petalinux-project$ petalinux-create -t project --template zynq -n smalldla
INFO: Create project: smalldla
INFO: New project successfully created in /home/tjx/petalinux-project/smalldla
对于template,如果使用zynq-7000系列芯片,选择zynq,如果是zynq +UltraScale MPSoC,则选择zynqMP。
之后,将Vivado export hardware输出的.hdf文件拷贝到新建的petalinux工程目录下:
(petalinux) tjx@tjx-virtual-machine:~/petalinux-project/smalldla$ cp /home/tjx/Vivado/DLA/DLA.sdk/nvsmall_wrapper.hdf .
(petalinux) tjx@tjx-virtual-machine:~/petalinux-project/smalldla$ petalinux-config --get-hw-description=./
在Image Packaging Configuration|Root Filesystem Type,选中SD card。
在DTG Setings 选择你的FPGA办卡型号。因为每个SOC办卡的设备树不同。在DTG Seting中系统会把外设设备树加载进来。比如说你在硬件分配了以太网外设,如果系统不建立相应的设备树和驱动。那么开机的时候操作系统会找不到相应的外设网口。
然后保存,退出,系统会编译一段时间(虚拟机内存分配尽可能多,否则在这一步可能会卡死)。
修改此处后,linux根目录系统rootfs将配置到SD中,而非默认的raminitfs,后者是将根目录系统镜像在boot阶段加载到内存中,一旦裁剪的kernel较大(大概超过120M),那么系统boot不起来;
下一步,裁剪kernel:
petalinux-config -c kernel
General setup,取消Initial RAM filesystem and RAM disk support,退出,保存配置。
这样文件系统就需要从SD卡启动,另一方面这个选项强制使BOOT从存储的第二个分区寻找文件系统,这样方便我们把文件系统替换为Ubuntu,仅将跟文件系统拷贝到第二分区即可。
这里需要先编译一下,因为这样能够使我们看到工具自动生成的设备树,方便我们找到NVDLA的标签,因为在之后我们需要覆盖掉其compatible属性,以及给他分配物理内存,虚拟内存等等。
petalinux-build
官方仓库的KMD程序的组织结构不适合作为Petalinux2019.1的模块。请使用这个仓库下的kmd。
https://github.com/LeiWang1999/ZYNQ-NVDLA/tree/master/kmd
新建一个Petalinux的Module,这里注意一定不要漏掉–enable,否则build的时候不会把Module程序一起编译:
(petalinux) tjx@tjx-virtual-machine:~/petalinux-project/smalldla$ petalinux-create -t modules -n opendla --enable
INFO: Create modules: opendla
INFO: New modules successfully created in /home/tjx/petalinux-project/smalldla/project-spec/meta-user/recipes-modules/opendla
INFO: Enabling created component...
INFO: sourcing bitbake
INFO: oldconfig rootfs
INFO: opendla has been enabled
上文提到了因为内核版本的不同这里需要将相关API接口进行修改。需要修改的部分有如下几处。
1.在nvdla_gem.c里面,修改了dma_declare_coherent_memory这个函数的内容,首先ZYNQ 7045的片上存储有限,根据尝试,这里只需要分配128MB的空间即可,第一个0x38000000是物理地址、第二个0x38000000是虚拟地址,第三个0x08000000指的是大小,笔者使用板卡型号为zynq7000,如果你使用的是Zynq MPSoc,可以自行把这三个值替换为:0x40000000,0x40000000,0x40000000。在Petalinux2019.1的Kernel版本中,DMA_MEMORY_MAP这个标志已经被废弃了,需要删除:
2.dma函数接口逻辑 4.19相比于4.13需要逻辑取反
dma = dma_declare_coherent_memory(drm->dev, 0xC0000000, 0xC0000000,
0x40000000, DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
if (!(dma & DMA_MEMORY_MAP)) {
err = -ENOMEM;
goto unref;
}
#更改为
dma = dma_declare_coherent_memory(drm->dev, 0x38000000, 0x38000000,
0x08000000, DMA_MEMORY_EXCLUSIVE);
if (dma) {
err = -ENOMEM;
goto unref;
}
2.添加define
在openda.h 中添加NVDLA small 的宏定义
#ifndef __OPENDLA_H_
#define __OPENDLA_H_
#define DLA_2_CONFIG
#ifdef DLA_2_CONFIG
#include
#else
#include
#endif
#endif
3.编写makefile
配置makefile和recipe,打开/project-spec/meta-user/recipes-modules/opendla/files/目录下的makefile文件,并将nvdla/sw/kmd/各级子目录下makefile中构成opendla.ko的.o对象添加其中,
opendla-m := opendla.o
###append all of sources###
opendla-objs := nvdla_core_callbacks.o nvdla_gem.o scheduler.o engine.o bdma.o conv.o sdp.o cdp.o pdp.o rubik.o cache.o common.o engine_data.o engine_isr.o engine_debug.o
###########################
4.编写.bb文件
之后,打开/project-spec/meta-user/recipes-modules/opendla/下的?.bb,为之前新增加的源文件添加声明。
SRC_URI = "file://makefile \
file://cdp.c \
...
file://opendla.h \
...
file://COPYRIGHT \
"
...
有关Linux设备树的详细内容,请参考这篇博客。
打开project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi,修改成如下内容:
/include/ "system-conf.dtsi"
/ {
reserved-memory {
#address-cells = <1>;
#size-cells = <1>;
ranges;
nvdla_reserved: buffer@0x38000000 {
compatible = "shared-dma-pool";
no-map;
reg = <0x38000000 0x08000000>;
};
};
};
&NV_nvdla_wrapper_0{
compatible = "nvidia,nv_small";
memory-region = <&nvdla_reserved>;
};
之后,重新编译:
petalinux-build
如果没有错误,接下来生成BOOT.BIN文件:
petalinux-package --boot --fsbl images/linux/zynq_fsbl.elf --fpga --u-boot --force
准备一张8GB以上的SD卡,由于之前配置了从SD卡启动,则这里我们要对SD卡分区,具体方法请参考博主写的另外一篇博客
https://mp.csdn.net/mp_blog/creation/editor/121355230。
对SD卡分两个区,第一个分区(如sdc1)的格式是FAT32,取名为BOOT、第二个分区(sdc2)的格式是EXT4,取名为ROOTFS,分区大小随意,BOOT分区可以小一点,ROOTFS分区可以大一点。注意,这里的分区必须严格是第一个和第二个区块,否则是BOOT不起来的。
把刚才生成的/images/linux/下BOOT.BIN, image.ub直接拷贝到SD卡的BOOT分区。
镜像文件百度网盘地址:
链接: https://pan.baidu.com/s/1Dil7HaOeXhF1hGV7MfbuBg
提取码: tg2w
下载我准备好的ubuntu-16.04.2-minimal-armhf-2017-06-18根文件系统镜像,解压并且覆盖到SD卡里即可。
sudo tar xfvp armhf-rootfs-ubuntu-xenial.tar -C /media/tjx/rootfs
但是,这样替换了rootfs之后,我们编译出来的opendla的modules并没有添加进来,打开petalinux文件夹下的\images\linux\rootfs.tar.gz,把里面的.\lib\modules解压出来,新增到ubuntu的\lib内部。
然后,把SD卡插到开发板上运行,测试一下insmod之后是否会多出中断信号和驱动。
root@arm:~# insmod /lib/modules/4.19.0-xilinx-v2019.1/extra/opendla.ko
root@arm:~# cat /proc/interrupts
CPU0 CPU1
16: 1 0 GIC-0 27 Edge gt
17: 0 0 GIC-0 43 Level ttc_clockevent
18: 4106 3966 GIC-0 29 Edge twd
19: 0 0 GIC-0 37 Level arm-pmu
20: 0 0 GIC-0 38 Level arm-pmu
21: 43 0 GIC-0 39 Level f8007100.adc
24: 0 0 GIC-0 35 Level f800c000.ocmc
25: 291 0 GIC-0 59 Level xuartps
26: 16 0 GIC-0 51 Level e000d000.spi
27: 427 0 GIC-0 54 Level eth0
28: 4915 0 GIC-0 56 Level mmc0
29: 0 0 GIC-0 45 Level f8003000.dmac
30: 0 0 GIC-0 46 Level f8003000.dmac
31: 0 0 GIC-0 47 Level f8003000.dmac
32: 0 0 GIC-0 48 Level f8003000.dmac
33: 0 0 GIC-0 49 Level f8003000.dmac
34: 0 0 GIC-0 72 Level f8003000.dmac
35: 0 0 GIC-0 73 Level f8003000.dmac
36: 0 0 GIC-0 74 Level f8003000.dmac
37: 0 0 GIC-0 75 Level f8003000.dmac
38: 0 0 GIC-0 40 Level f8007000.devcfg
44: 0 0 GIC-0 41 Edge f8005000.watchdog
45: 0 0 GIC-0 61 Level 40000000.NV_nvdla_wrapper
IPI1: 0 0 Timer broadcast interrupts
IPI2: 1267 2841 Rescheduling interrupts
IPI3: 4 3 Function call interrupts
IPI4: 0 0 CPU stop interrupts
IPI5: 0 0 IRQ work interrupts
IPI6: 0 0 completion interrupts
root@arm:~# ls /dev/dri/
card0 renderD128
具体方法请看这篇文章,这里就不再赘述了。
https://editor.csdn.net/md/?articleId=127922123
到这里NVDLA的硬件和软件环境就算搭建好了,接下来就算移植Tengine框架,将NVDLA功能嵌入其中了。