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

参考にしたサイト

手順概要

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

手順1

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

HWとしては、Zynq Ultra96+ MPSocのみを用意

Sources から右クリックして、HDL Wrapperをtop moduleとして設定

合成後に、
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を作成

New Application Project で+を押して、手順1で作成したdesign_1_wrapper.xsaを選択してNext

CPUにpsu_coretexr5_0を選択してNext(重要!)

Template でOpenAMPecho-testを選択してFinish

補足(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