Ultra96v2 で OpenAMP を動かすためにやったこと。


#概要
Ultra96V2 はArm Cortex-A53 Quad Core / Cortex-R5 Dual Coreを搭載しているので、Cortex-A53とCortex-R5の間でOpenAMPを使って通信するサンプルプログラムを動かしてみた。

#環境
FPGA: Ultra96 v2
Vivado: v2019.2 (64-bit)
Xilinx Vitis IDE: v2019.2

#参考にしたサイト
https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/150568961/OpenAMP+2019.2

https://www.xilinx.com/support/documentation/sw_manuals/xilinx2019_2/ug1186-zynq-openamp-gsg.pdf

https://qiita.com/iwatake2222/items/ff46792eb107d978cd0b#openamp%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%9Famp%E7%92%B0%E5%A2%83%E3%81%AE%E6%A7%8B%E7%AF%89


#手順概要
1. VivadoでFPGAの作成
2. ubuntu上でpetalinuxのbuild
3. vitisでCoretex-R5 用のfirmwareの作成
4. Ultra96 V2 上で実行する。

##手順1
#####手順2で使う、xsaファイルと、bitstreamファイルを作成する。

HWとしては、Zynq Ultra96+ MPSocのみを用意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535710/18e12e5e-22ed-0b7a-1f29-cf16646836d2.png)

Sources から右クリックして、HDL Wrapperをtop moduleとして設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535710/784973c3-b913-9eac-1701-485a37764cd2.png)


合成後に、
File -> Export -> Export Hardware
で、design_1_wrapper.xsaの作成

File -> Export -> Export BitStream File
で、design_1_wrapper.bitの作成

##手順2

#####petalinux-toolsがインストールされているサーバー上で、project作成

~~~
$ petalinux-create --type project --template zynqMP --name PjOpenAmp
~~~


手順1で作成した、design_1_wrapper.xsaをPjOpenAmpフォルダにコピー

~~~
$ cd PjOpenAmp/
$ petalinux-config --get-hw-description=./
~~~

#####Kernel configurationの確認(特に変更する必要はない)

~~~
$ petalinux-config -c kernel
~~~

・[*] Enable loadable module support --->

・Device Drivers --->
Remoteproc drivers --->
 \<M> Support for Remote Processor subsystem
 \<M> ZynqMP_r5 remoteproc support

(以下は手順書に書かれているが、私の環境では存在してなかったので無視)
・Device Drivers --->
Generic Driver Options --->
<*> Userspace firmware loading support

#####rootfsの変更
~~~
$ petalinux-config -c rootfs
~~~

- Filesystem Packages > misc > sysfsutils > libsysfsを、[\*]
- Filesystem Packages > libs > libmetal > libmetalを、[\*]
- Filesystem Packages > Petalinux Package Groups > packagegroup-petalinux-openamp > packagegroup-petalinux-openampを、[\*]
- Filesystem Packages > misc > openamp-fw-echo-testd > openamp-fw-echo-testdを、[\*]
- Filesystem Packages > misc > openamp-fw-mat-muld > openamp-fw-mat-muldを、[\*]
- Filesystem Packages > misc > openamp-fw-rpc-demo > openamp-fw-rpc-demoを、[\*]

#####Device Treeの修正

~~~project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi
/include/ "system-conf.dtsi"
/ {
    reserved-memory {
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;
        rproc_0_dma: rproc@0x3ed40000 {
            no-map;
            compatible = "shared-dma-pool";
            reg = <0x0 0x3ed40000 0x0 0x100000>;
        };
        rproc_0_reserved: rproc@0x3ed00000 {
            no-map;
            reg = <0x0 0x3ed00000 0x0 0x40000>;
        };
    };
    zynqmp-rpu {
        compatible = "xlnx,zynqmp-r5-remoteproc-1.0";
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;
        core_conf = "split";
        r5_0: r5@0 {
            #address-cells = <2>;
            #size-cells = <2>;
            ranges;
            memory-region = <&rproc_0_reserved>, <&rproc_0_dma>;
            pnode-id = <0x7>;
            mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
            mbox-names = "tx", "rx";
            tcm_0_a: tcm_0@0 {
                reg = <0x0 0xFFE00000 0x0 0x10000>;
                pnode-id = <0xf>;
            };
            tcm_0_b: tcm_0@1 {
                reg = <0x0 0xFFE20000 0x0 0x10000>;
                pnode-id = <0x10>;
            };
        };
    };
    zynqmp_ipi1 {
        compatible = "xlnx,zynqmp-ipi-mailbox";
        interrupt-parent = <&gic>;
        interrupts = <0 29 4>;
        xlnx,ipi-id = <7>;
        #address-cells = <1>;
        #size-cells = <1>;
        ranges;
        /* APU<->RPU0 IPI mailbox controller */
        ipi_mailbox_rpu0: mailbox@ff90000 {
            reg = <0xff990600 0x20>,
                  <0xff990620 0x20>,
                  <0xff9900c0 0x20>,
                  <0xff9900e0 0x20>;
            reg-names = "local_request_region",
                        "local_response_region",
                        "remote_request_region",
                        "remote_response_region";
            #mbox-cells = <1>;
            xlnx,ipi-id = <1>;
        };
    };
};
~~~

#####petalinuxのbuildとboot imageの作成
あらかじめ手順1で作成したdesign_1_wrapper.bitを image/linuxフォルダにコピーしておく

~~~
$ petalinux-build
$ petalinux-package --boot --force --fsbl images/linux/zynqmp_fsbl.elf --fpga ./images/linux/design_1_wrapper.bit --u-boot
~~~

images/linux/以下に作成できた、image.ub, BOOT.BIN, rootfs.ext4をSDカードにコピー


#####補足
device treeのみbuildし直したい場合は、以下のコマンドで可能

~~~
$ petalinux-build -c device-tree
~~~


##手順3
#####vitisでCortex-R5のfirmwareをサンプルコードから作成する。
File -> New -> Application Project
my_echo_appを作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535710/453363f4-f2f8-d97f-d493-06a7306feff9.png)

New Application Project で＋を押して、手順1で作成したdesign_1_wrapper.xsaを選択してNext
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535710/97a4001f-e43c-60f0-eef0-52ed76937920.png)

CPUに***psu_coretexr5_0***を選択してNext(重要！)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535710/5960675a-4c09-8e64-2257-b085f90e7a34.png)

Template でOpenAMPecho-testを選択してFinish
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535710/484b73fa-733b-c16c-b9f9-2b3ab8293883.png)

#####補足(Windowsでvitisを使っている場合のみ)
Windows でvitis を使っている場合にOpenAMPecho-testの作成に失敗する。
こちらのサイトに解決策が書かれている
https://forums.xilinx.com/t5/OpenAMP/Vitis-2019-2-unable-to-select-libmetal-and-openamp/td-p/1063722

こちらのふたつのファイルを修正しないとエラーになる。
Edit: Vitis\2019.2\data\embeddedsw\ThirdParty\sw_services\libmetal_v2_0\src\run_cmake.bat
And: Vitis\2019.2\data\embeddedsw\ThirdParty\sw_services\openamp_v1_5\src\run_cmake.bat

以下のように修正する。
Replace: \${HDI_APPROOT}/tps/lnx64/cmake-3.3.2/bin/cmake $@ 2>&1
With:   %HDI_APPROOT%\tps\win64\cmake-3.3.2\bin\cmake.exe %* 2>&1

#####作成したプロジェクトをbuildする
my_echo_app_systemで右クリックして、build imageしてmy_echo_app.elfを作成する。
これが、Coretex-R5上でlinxuと通信するfirmwareになる。

##Ultra96 V2 上で実行する
手順2で作成したBOOT.BINとimage.ubをコピーしたSDカードで実行すると、以下のようなログが出る、

~~~
[    6.220027] zynqmp_r5_remoteproc zynqmp-rpu: RPU core_conf: split
[    6.226883]  r5@0: DMA mask not set
[    6.230465]  r5@0: assigned reserved memory node rproc@0x3ed40000
[    6.236779] remoteproc remoteproc0: r5@0 is available
~~~

remote proc driverがインストールされていることを確認

~~~
root@PjOpenAmp:~# lsmod
    Not tainted
zynqmp_r5_remoteproc 20480 0 - Live 0xffffff8000b2c000
remoteproc 40960 1 zynqmp_r5_remoteproc, Live 0xffffff8000b1b000
virtio_ring 20480 1 remoteproc, Live 0xffffff8000b11000
virtio 16384 1 remoteproc, Live 0xffffff8000b08000
uio_pdrv_genirq 16384 0 - Live 0xffffff8000b00000
~~~

手順3で作成したmy_echo_app.elfをtarget上の/lib/firmware以下にコピーしておく。

~~~
root@PjOpenAmp:~# cd /lib/firmware/
root@PjOpenAmp:/lib/firmware# echo my_echo_app.elf > /sys/class/remoteproc/remoteproc0/firmware
root@PjOpenAmp:/lib/firmware# echo start > /sys/class/remoteproc/remoteproc0/state
[  238.077073] remoteproc remoteproc0: powering up r5@0
[  238.121549] remoteproc remoteproc0: Booting fw image my_echo_app.elf, size 838624
[  238.133289]  r5@0: RPU boot from TCM.
[  238.136516] remoteproc remoteproc0: registered virtio0 (type 7)
[  238.146120] remoteproc remoteproc0: remote processor r5@0 is now up
root@PjOpenAmp:/lib/firmware# [  238.153126] virtio_rpmsg_bus virtio0: rpmsg host is online
[  238.157947] virtio_rpmsg_bus virtio0: creating channel rpmsg-openamp-demo-channel addr 0x0
root@PjOpenAmp:/lib/firmware# echo_test

 Echo test start

Master>probe rpmsg_char

 Open rpmsg dev virtio0.rpmsg-openamp-demo-channel.-1.0!
Opening file rpmsg_ctrl0.
checking /sys/class/rpmsg/rpmsg_ctrl0/rpmsg0/name
svc_name: rpmsg-openamp-demo-channel
.

 **************************************

  Echo Test Round 0

 **************************************

 sending payload number 0 of size 17
echo test: sent : 17
 received payload number 0 of size 17

~~~

以上で実行ができた。

#####補足
ここにecho_testのコードが置いてあるので、echo_testを修正することでlinux側のプログラムも自分で修正できそう。
https://github.com/Xilinx/meta-openamp