Build Vitis platform for Ultra96v2 (Vitis 2020.2)

前回の[Vitis-AI v1.4 on Ultra96v2](https://qiita.com/lp6m/items/4117a3bab185afedfd5f)ではAvnetが用意してくれているスクリプトを使用してVitisプラットフォームを作成し、Xilinxの[DPU-TRD](https://github.com/Xilinx/Vitis-AI/tree/v1.4/dsa/DPU-TRD)プロジェクトを使用してDPUの動作環境を生成しました。

前回の作業はコマンドラインベースで楽だったのですが、いくつかの問題がありました。
- avnetのHWプラットフォームには不要なコア（AXI BRAMなど）が含まれている
- VitisのGUIフローを使用していないため、他カーネルの追加作業などがしずらい
前回の作業で生成されたVivadoプロジェクトのブロックデザインは以下のようになっており、自分には不必要なコアなどが含まれているのが気になりました。
![Screenshot from 2021-12-06 01-16-49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/cc86e745-ae2f-fdea-f4b7-c2dfacb85655.png)

そこで今回は1からUltra96向けのVitisプラットフォームを生成しようと思います。

# Environment
- Host: Ubuntu 18.04
- Target: Ultra96v2
- Vitis/Vivado/Petalinux 2020.2

VivadoでUltra96v2のボードファイルを使用するため、[Board files](https://github.com/Avnet/bdf)をDownload zipからダウンロードして、`/tools/Xilinx/Vivado/2020.2/data/boards/board_files/`に配置します。

```
 ls /tools/Xilinx/Vivado/2020.2/data/boards/board_files/
README.md     adm-pcie3-ku3  au280             kc705   kcu1500         microzed_7010  picozed_7010_fmc2  picozed_7030_fmc2  ultrazed_3eg_iocc    vc707   vcu108  vcu128   vmk180  zc702   zcu104  zcu1275  zcu216
ac701         au200          deprecated        kcu105  li-imx274-mipi  microzed_7020  picozed_7015_fmc2  sp701              ultrazed_3eg_pciecc  vc709   vcu110  vcu129   xbzu1   zc706   zcu106  zcu1285  zed
adm-pcie-7v3  au250          download_zip.png  kcu116  locate_zip.png  minized        picozed_7020_fmc2  ultra96v2          ultrazed_7ev_cc      vck190  vcu118  vcu1525  xm105   zcu102  zcu111  zcu208   zedboard
```
# Build HW Platform
[FPGAの部屋 Ultra96-V2 の Vitis 2020.1 アクセラレーション・プラットフォームを作る1（ハードウェア・コンポーネント編）](https://marsee101.blog.fc2.com/blog-entry-4912.html)を参考にしながら進めます。

ブロックデザインは参考記事と同じようにしました。
![Screenshot from 2021-12-02 23-39-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/0b9f4c35-03bd-4dc0-51e2-b45763c052af.png)

VitisのProject Settingsから`Project is an extensible Vitis platform`を有効にします。
![Screenshot from 2021-12-02 23-40-52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/6fb180bd-8a81-0e7e-f507-59dd66129476.png)

Clocking Wizardの設定は、DPU向けに周波数を参考記事から変更しています。100/150/200/300/400の5種類にしています。DPUは元となるクロックと、元の2倍のクロックをDSPで使用するので、100/200, 150/300, 200/400の3種類の設定ができるようにしました。
![Screenshot from 2021-12-06 01-32-44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/f157be41-aa3a-e71b-eeba-7f3beabd3812.png)

`プラットフォームの生成`では、使用しているVivadoのバージョンが異なるからか、画面が違ったものになっていました。
AXI Portの設定
![Screenshot from 2021-12-02 23-42-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/cf5c96f9-2441-b452-8667-0d329d523239.png)
Clockの設定
ちなみに、ID=0のクロックが存在しないとVitisで怒られることになります。
![Screenshot from 2021-12-02 23-43-18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/f58fb88a-e488-abe8-5743-ae24a10c91b3.png)
記事同様、Generate Bitstream, Export XSAを実行します。

# Build SW Platform
[Ultra96-V2 の Vitis 2020.1 アクセラレーション・プラットフォームを作る2（ソフトウェア・コンポーネント編）](https://marsee101.blog.fc2.com/blog-entry-4914.html)を参考にします。しかし、そのままでは残念ながらwifiが使用できませんでした。
Petalinux、デバイスツリーの知識が乏しく、wifi、usb-lan、VARTのインストールが可能なSWプラットフォームの構築にかなり苦労してしまいました。少なくとも以下の方法であれば構築ができることは確認しています。

## Download BSP
[AvnetのUltra96v2 Portal](https://www.avnet.com/wps/portal/us/products/avnet-boards/avnet-board-families/ultra96-v2/)から`PetaLinux Board Support Packages-> Ultra96-V2 – PetaLinux 2020+ BSP (Sharepoint site)`のリンクに飛び、`Documents->Projects->public_release->2020.2->BSP`から`u96v2_sbc_base_2020_2.tar.gz`をダウンロードして解凍します。解凍すると`u96v2_sbc_base_2020_2.bsp`が得られます。
このBSPを使用すると、Avnetのボード向けのUser Layerが公開されている[meta-avnet](https://github.com/Avnet/meta-avnet/tree/2020.2)がユーザレイヤとして既に組み込まれたpetalinuxプロジェクトを生成することが可能です。このBSPを使用せずに、自分でmeta-avnetをユーザレイヤとして追加してSWプラットフォームを構築したかったのですが、どうもうまくいきませんでした。。詳細については追えていません。

## Build Petalinux Project
まずプロジェクトをBSPを基に作成します。

```sh
petalinux-create -t project -s ../u96v2_sbc_base_2020_2.bsp --name ultra96v2_min2_201
cd ultra96v2_min2_201
```

次にベースとなるHWプラットフォームを指定します。SWプラットフォームの構築作業でexportしたxsaファイルを指定します。

```sh
petalinux-config --get-hw-description ../../ultra96v2_min2_201/ultra96v2_min2_201.xsa
```

参考記事では`petalinux-config -c rootfs`, `petalinux-config -c kernel`などでコンフィグを変更していますが、確認してみたところ参考記事で適用されている変更は既に変更されていたため変更は不要でした。

次に、`./project-spec/meta-avnet/recipes-bsp/device-tree/files/u96v2-sbc/system-bsp.dtsi`から不要な部分を削除します。基のBSPが使用しているHWプラットフォームには様々なIPが搭載されているので、それらのIP向けのデバイスツリー定義が記述されていますが、今回は不要かつそのままではビルド・ブート時にエラーになるため変更します。`system-bsp.dtsi`ファイルは以下のようにしました。こちらのデバイスツリー定義は参考記事のものとは少し異なります。

```
/include/ "system-conf.dtsi"
/ {
	chosen {
		bootargs = "earlycon console=ttyPS0,115200 clk_ignore_unused root=/dev/mmcblk0p2 rw rootwait cma=512M";
	};

   sdio_pwrseq: sdio_pwrseq {  /* This needs to be able to manipulate the chip_en and the resetn properly */
      compatible = "mmc-pwrseq-simple";
      /* post-power-on-delay-ms = <10>; */
      reset-gpios = <&gpio 7 1>; // MIO[7] for WILC3000 RESETN, Active low
      /* reset-gpios = <&gpio 78 1>;  // Some prototype boards only! device pin A3 for RESETN, Active low */
      chip_en-gpios = <&gpio 8 1>; 
   };

   // Remove V1 Power ON/OFF controller from U96 V1 DT
   /delete-node/ ltc2954;

	aliases {
		i2c0 = &i2c1;
   };
   
   xlnk {
      compatible = "xlnx,xlnk-1.0";
   };

};

&amba {
	zyxclmm_drm {
		compatible = "xlnx,zocl";
		status = "okay";
	};
};

&sdhci1 {
   bus-width= <0x4>;
   /* non-removeable; */
   /* mmc-pwrseq = <&sdio_pwrseq>; */
   max-frequency = <50000000>;
   /delete-property/cap-power-off-card; // This is not compatible with the WILC3000 and means the WILC will always be powered on
   status = "okay";
   #address-cells = <1>;
   #size-cells = <0>;
   wilc_sdio@1 {
      compatible = "microchip,wilc3000", "microchip,wilc3000";
      reg = <0>;
      // interrupt-parent = <&gpio>; // Microchip driver DOES NOT use gpio irq any more!
      // interrupts = <76 2>; /* MIO76 WILC IRQ 1V8 */ // Microchip driver DOES NOT use gpio irq any more!
      // irq-gpios = <&gpio 76 0>; // Microchip driver DOES NOT use gpio irq any more!
      bus-width= <0x4>;
      status = "okay";
   };
   // Remove TI child node from U96 V1 DT
   /delete-node/wifi@2;
};

&sdhci0 {
    disable-wp;
};
```

ビルド作業を行います。長時間かかるので気長に待ちます。`-c avnet-image-full`の部分が肝心な部分で、これを含めないとwifiが使えない環境になってしまいます。
ビルドではchromiumのビルドなども行われますが不要なので本当は必要最小限のモジュールだけの構成にしたかったのですが、今回はそのままにしました。

```sh
petalinux-build -c avnet-image-full
```

完了すれば、参考記事同様、次のVitisプラットフォームのビルドで必要なファイルを`images/linux/pkg`以下にコピーします。

```sh
mkdir pkg
mkdir pkg/pfm
mkdir pkg/pfm/boot
cp bl31.elf pkg/pfm/boot/
cp image.ub pkg/pfm/boot/
cp pmufw.elf pkg/pfm/boot/
cp u-boot.elf pkg/pfm/boot/
cp system.dtb pkg/pfm/boot/
cp zynqmp_fsbl.elf pkg/pfm/boot/fsbl.elf
```

## SW Platform Check
ビルドしたSWプラットフォームが希望どおりに動作するかを確認します。この時点でwifiやUSB LANが使用できないと、後戻りすることになってしまう為です。
BOOT.BIN生成

```sh
petalinux-package --boot --fsbl ./images/linux/zynqmp_fsbl.elf --fpga ./images/linux/system.bit --uboot --force
```
SDカードの第1パーティションをFAT,第2パーティションをext4でフォーマットしてそれぞれBOOT,rootfsと名前を付けました。
![Screenshot from 2021-12-06 02-00-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/1ae824ec-f502-f6ea-7c5c-4cdf35bca8d8.png)

```sh
cd images/linux
cp BOOT.BIN /media/lp6m/BOOT/
cp image.ub /media/lp6m/BOOT/
cp boot.scr /media/lp6m/BOOT/
sudo tar xvf rootfs.tar.gz -C /media/lp6m/rootfs/
sync
```

wifi, USB-LAN, ssh, VARTのインストールなどが問題なく行えることを確認しています。
パッケージ管理システムが壊れていたり必要なパッケージがないと悲しくなります。
<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="ja" dir="ltr">VARTのインストールに失敗する・・/bin/shが必要ってなんだ <a href="https://t.co/0aPfOMSgtt">pic.twitter.com/0aPfOMSgtt</a></p>&mdash; lp6m (@lp6m1) <a href="https://twitter.com/lp6m1/status/1464969231783849987?ref_src=twsrc%5Etfw">November 28, 2021</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ちなみにUSB-LANは[USBLAN100R](https://www.planex.co.jp/products/usb-lan100r/)を使用しています。

## Build sysroot
次にVitisでアプリケーションをビルドするために使用するsysrootを生成します。
ビルドは`petalinux-build -c avnet-image-full`で行なったのでsysrootの生成は`petalinux-build --sdk -c avnet-image-full`で行うべきだと思ったのですが、前回記事で使用した[avnetのvitisプラットフォーム作成におけるsysroot生成スクリプト](https://github.com/Avnet/vitis/blob/2020p2_u96v2_sbc_base_20210426_105325/projectMakefile.mk#L152)では単に`petalinux-build --sdk`で実行されていたので、今回はそれに倣いました。

また、avnetのsysroot生成スクリプトでは[sysrootの生成前にrootfsに必要なパッケージを含めるようにconfigを変更しています](https://github.com/Avnet/vitis/blob/2020p2_u96v2_sbc_base_20210426_105325/projectMakefile.mk#L143)。ここで実行されている[add_petalinux_packages.sh](https://github.com/Avnet/vitis/blob/2020p2_u96v2_sbc_base_20210426_105325/add_petalinux_packages.sh)をコピーしてきて実行してrootfsのconfigを変更してから、sysrootをビルドします。

```sh
./add_petalinux_packages.sh
petalinux-build --sdk
```
ビルドが完了すれば`images/linux`の中に`sdk.sh`が生成されています。
参考記事同様に、sysrootを`images/linux/pkg/pfm`にインストールします。

```sh
./sdk.sh
# install directoryをフルパスで入力する
```
最後に、これも参考記事同様に`pkg/linux.bif`を作成します。

```
/* linux */
 the_ROM_image:
 {
    [pmufw_image] <pmufw.elf>
    [bootloader, destination_cpu=a53-0] <fsbl.elf>
    [destination_device=pl] <bitstream>
    [destination_cpu=a53-0, exception_level=el-3, trustzone] <bl31.elf>
    [destination_cpu=a53-0, exception_level=el-2] <u-boot.elf>
 }
```

# Build Vitis Platform
[Ultra96-V2 の Vitis 2020.1 アクセラレーション・プラットフォームを作る3（Vitis 2020.1 でアクセラレーション・プラットフォーム作成）](https://marsee101.blog.fc2.com/blog-entry-4915.html)を参考にしながら作業を行います。作業は参考記事と全く同じです。
![Screenshot from 2021-11-20 02-53-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243354/b596c0f2-d918-c6f7-7cb7-2ca7dc3acee8.png)

作業完了後、このプラットフォームをVitisから参照できるように、Vitisのインストールディレクトリ以下にコピーしておきます。

```sh
sudo cp -r ./ultra96v2_min2_201/export/ultra96v2_min2_201/ /tools/Xilinx/Vitis/2020.2/platforms/
```


# まとめ
wifi, USB-LAN, ssh, VARTのインストールが可能なultra96v2向けのVitisプラットフォームを作成することができました。
次回はGUIフローを使用してDPUをこのプラットフォーム上に配置してみようと思います。

# 参考記事
- [Zybo+VitisでSDSoC相当の高位合成やってみた](https://proc-cpuinfo.fixstars.com/2019/11/vitis-hls-on-zybo/)
Vitisのプラットフォーム構築がどういう作業であるかがよくわかりました。

- [How to create Ultra96v2 Linux-based Platform in Xilinx Vitis 2020.2](https://highlevel-synthesis.com/2021/08/14/how-to-create-ultra96v2-linux-based-platform-in-xilinx-vitis-2020-2/)
作業が完了してから見つけたのですが、同じような作業を行なっています。ただしwifiの使用可否については言及されていません。

- [Petalinux 2020.2 BSP for Ultra96v2 with Wifi & VNC Server](https://www.hackster.io/LogicTronix/petalinux-2020-2-bsp-for-ultra96v2-with-wifi-vnc-server-4764ea)

- [Ultra96-V2 の Vitis 2020.1 アクセラレーション・プラットフォームを作る1（ハードウェア・コンポーネント編）](https://marsee101.blog.fc2.com/blog-entry-4912.html)
- [Ultra96-V2 の Vitis 2020.1 アクセラレーション・プラットフォームを作る2（ソフトウェア・コンポーネント編）](https://marsee101.blog.fc2.com/blog-entry-4914.html)
- [Ultra96-V2 の Vitis 2020.1 アクセラレーション・プラットフォームを作る3（Vitis 2020.1 でアクセラレーション・プラットフォーム作成）](https://marsee101.blog.fc2.com/blog-entry-4915.html)
- [Ultra96-V2 の WiFi で超苦労した話](https://qiita.com/ikwzm/items/2b50d1228282ebf150dd)

これらの記事がなければ実現できなかったので、参考記事を公開していただいた方に深く感謝しています。