手把手教你在FPGA上移植NVDLA+Tengine并且跑通任意神经网络(2)

手把手教你在FPGA上移植NVDLA+Tengine并且跑通任意神经网络(2)

  • 一.前言
  • 二.构建内核linux 4.19
    • 2.1 Petalinux 2019.1
  • 2.2 构建内核linux4.19
      • 2.2.1 创建 Petalinux工程
      • 2.2.2 设置根文件启动方式
      • 2.2.3 外挂文件系统
      • 2.2.4 编译
      • 2.2.5 KMD移植
      • 2.2.6 设备树构建
    • 2.3 SD卡分区
    • 2.4 ubuntu16.04根文件系统移植
    • 2.5 编译UMD
  • 三.小结

一.前言

模型推理过程
接着上一篇:手把手教你在FPGA上移植NVDLA+Tengine并且跑通任意神经网络(1)
这一篇将主要讲述如何移植ubunt16.04根文件系统+linux4.19内。并且在ZC706 FPGA上正确的加载驱动。经过上文在VIVADO SDK中的验证我们已经可以确定NVDLA模块的功能正确性。但是在日常应用中,需要拥有人机交互和自动配置的需求,官方开源了整套的SW软件栈。那么移植OS操作系统并且移植KMD是我们绕不开的一步了。

二.构建内核linux 4.19

2.1 Petalinux 2019.1

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工具包括:

  • 命令行界面
  • 应用、器件驱动程序、库生成器以及开发模板
  • 可引导的系统镜像生成器
  • 调试代理程序
  • GCC工具集
  • 集成的QEMU全系统仿真器
  • 自动化工具
  • 支持Xilinx系统调试器

上文VIVADO用到是2019.1版本,这里Petalinux应该用和VIVADO同样的版本否则会出现想不到的bug。

Petalinux2019.1安装教程:https://blog.csdn.net/mcupro/article/details/91973744

2.2 构建内核linux4.19

Petalinux 2019.1 对应的 linux 版本是4.19知道这一点非常重要。因为官方提供的Linux版本为4.13,很多库函数的接口API有所变动。所以应当相应位置上做出更改,否则内核加载会不成功。具体修改部分请看后文。

2.2.1 创建 Petalinux工程

(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。

2.2.2 设置根文件启动方式

之后,将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中系统会把外设设备树加载进来。比如说你在硬件分配了以太网外设,如果系统不建立相应的设备树和驱动。那么开机的时候操作系统会找不到相应的外设网口。
手把手教你在FPGA上移植NVDLA+Tengine并且跑通任意神经网络(2)_第1张图片
然后保存,退出,系统会编译一段时间(虚拟机内存分配尽可能多,否则在这一步可能会卡死)。

修改此处后,linux根目录系统rootfs将配置到SD中,而非默认的raminitfs,后者是将根目录系统镜像在boot阶段加载到内存中,一旦裁剪的kernel较大(大概超过120M),那么系统boot不起来;

2.2.3 外挂文件系统

下一步,裁剪kernel:

petalinux-config -c kernel

General setup,取消Initial RAM filesystem and RAM disk support,退出,保存配置。

这样文件系统就需要从SD卡启动,另一方面这个选项强制使BOOT从存储的第二个分区寻找文件系统,这样方便我们把文件系统替换为Ubuntu,仅将跟文件系统拷贝到第二分区即可。

2.2.4 编译

这里需要先编译一下,因为这样能够使我们看到工具自动生成的设备树,方便我们找到NVDLA的标签,因为在之后我们需要覆盖掉其compatible属性,以及给他分配物理内存,虚拟内存等等。

petalinux-build

2.2.5 KMD移植

官方仓库的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 \
"
...

2.2.6 设备树构建

有关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

2.3 SD卡分区

准备一张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分区。

2.4 ubuntu16.04根文件系统移植

镜像文件百度网盘地址:
链接: 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

2.5 编译UMD

具体方法请看这篇文章,这里就不再赘述了。
https://editor.csdn.net/md/?articleId=127922123

三.小结

到这里NVDLA的硬件和软件环境就算搭建好了,接下来就算移植Tengine框架,将NVDLA功能嵌入其中了。

你可能感兴趣的:(nvdla,fpga开发,神经网络,人工智能)