はじめに
Ultra96-V2には、APUにCortex-A53が4個、RPUにCortex-R5が2個搭載されています。
これまで自分は、RPUは使わず、APUにPetalinux + Ubuntu20.04のシステムをロードして使っていました。
そこで今回、APUからRPUにプログラム(Lチカ)をロードして実行するということをやってみます。
環境・ツール
- Petalinux 2020.2
- APU ユーザランド: Ubuntu20.04
- Xilinx Vitis IDE v2022.2.0 (RPUコア用ベアメタルプログラム開発用)
前提条件
Vivadoで生成したUltra96-V2のハードウェアファイル(.xsa)が用意されている。
RPU用Lチカプログラムの作成
Vitisを起動し、[File -> New -> Application Project...]を選択しプロジェクトを作成。
プロジェクトが生成されたら、helloworld.cを編集。
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "sleep.h"
#include "xgpiops.h"
int main()
{
init_platform();
XGpioPs instXGpioPs;
XGpioPs_Config *configxGpioPs;
configxGpioPs = XGpioPs_LookupConfig(XPAR_PSU_GPIO_0_DEVICE_ID);
XGpioPs_CfgInitialize(&instXGpioPs, configxGpioPs, configxGpioPs->BaseAddr);
XGpioPs_SetDirectionPin(&instXGpioPs, 20, 1);
XGpioPs_SetDirectionPin(&instXGpioPs, 19, 1);
XGpioPs_SetDirectionPin(&instXGpioPs, 18, 1);
XGpioPs_SetDirectionPin(&instXGpioPs, 17, 1);
XGpioPs_SetOutputEnablePin(&instXGpioPs, 20, 1);
XGpioPs_SetOutputEnablePin(&instXGpioPs, 19, 1);
XGpioPs_SetOutputEnablePin(&instXGpioPs, 18, 1);
XGpioPs_SetOutputEnablePin(&instXGpioPs, 17, 1);
while(1)
{
XGpioPs_WritePin(&instXGpioPs, 20, 1);
sleep(1);
XGpioPs_WritePin(&instXGpioPs, 19, 1);
sleep(1);
XGpioPs_WritePin(&instXGpioPs, 18, 1);
sleep(1);
XGpioPs_WritePin(&instXGpioPs, 17, 1);
sleep(1);
XGpioPs_WritePin(&instXGpioPs, 17, 0);
sleep(1);
XGpioPs_WritePin(&instXGpioPs, 18, 0);
sleep(1);
XGpioPs_WritePin(&instXGpioPs, 19, 0);
sleep(1);
XGpioPs_WritePin(&instXGpioPs, 20, 0);
sleep(1);
}
}
次に、アプリケーション用にDDRメモリを予約するために、lscript.ldファイルのメモリレジスタを更新する。
psu_r5_ddr_0_MEM_0の値を以下のように編集。
[Project -> Buuild Project]を実行。
ビルドが成功すると、led_blink.elfが生成される。
Petalinux側の対応
PetalinuxにLチカファームウェアを追加するレシピを作成
Petlinux アプリケーション レシピを作成する
$ cd {Petalinux Project Path}
$ petalinux-create -t apps --template install -n led-blink --enable
Vitisで作成したled_blink.elfをproject-spec/meta-user/recipes-apps/led-blink/files/ 以下にコピーする。
また、led-blink.bbを以下のように編集。
#
# This file is the led-blink recipe.
#
SUMMARY = "Simple led-blink application"
SECTION = "PETALINUX/apps"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://led_blink.elf \
"
S = "${WORKDIR}"
INSANE_SKIP_${PN} = "arch"
FILES_${PN} += "/lib/firmware/"
do_install() {
install -d ${D}/lib/firmware
install -m 0644 ${S}/led_blink.elf ${D}/lib/firmware/led_blink.elf
}
Device Treeの修正
続いて、project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsiに以下を記述。
/ {
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
rpu0vdev0vring0: rpu0vdev0vring0@3ed40000 {
no-map;
reg = <0x0 0x3ed40000 0x0 0x4000>;
};
rpu0vdev0vring1: rpu0vdev0vring1@3ed44000 {
no-map;
reg = <0x0 0x3ed44000 0x0 0x4000>;
};
rpu0vdev0buffer: rpu0vdev0buffer@3ed48000 {
no-map;
reg = <0x0 0x3ed48000 0x0 0x100000>;
};
rproc_0_reserved: rproc@3ed00000 {
no-map;
reg = <0x0 0x3ed00000 0x0 0x40000>; // Vitisで指定したのと同じ領域
};
};
zynqmp-rpu {
compatible = "xlnx,zynqmp-r5-remoteproc-1.0";
#address-cells = <2>;
#size-cells = <2>;
ranges;
core_conf = "split";
reg = <0x0 0xFF9A0000 0x0 0x10000>;
r5_0: r5@0 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
memory-region = <&rproc_0_reserved>, <&rpu0vdev0buffer>, <&rpu0vdev0vring0>, <&rpu0vdev0vring1>;
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>;
};
};
};
Kernel configurationの確認
$ petalinux-config -c kernel
・Device Drivers --->
Remoteproc drivers --->
<*> Support for Remote Processor subsystem
<M> ZynqMP_r5 remoteproc support
rootfsの設定
$ petalinux-config -c rootfs
- apps ---> led-blink [*]
- Filesystem Packages ---> misc ---> sysfsutils ---> libsysfs [*]
- Filesystem Packages ---> libs ---> libmetal ---> libmetal [*]
- 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 [*]
Petalinuxのビルドとimageの作成
$ petalinux-build
$ petalinux-package --boot --fsbl images/linux/zynqmp_fsbl.elf --pmufw images/linux/pmufw.elf --fpga images/linux/system.bit --u-boot --force
Ultra96-V2上での実行
$ lsmod
zynqmp_r5_remoteproc 20480 0
$ cd /lib/firmware
$ echo led_blink.elf > /sys/class/remoteproc/remoteproc0/firmware
$ echo start > /sys/class/remoteproc/remoteproc0/state
これで、自作したLチカプログラムをRPUコアにロードし、実行することができた。
プログラムの停止は以下のようにする。
$ echo stop > /sys/class/remoteproc/remoteproc0/state
テスト用アプリの実行
ついでにテスト用アプリも動かしてみる。
$ echo image_echo_test > /sys/class/remoteproc/remoteproc0/firmware
$ echo start > /sys/class/remoteproc/remoteproc0/state
$ echo_test
$ echo stop > /sys/class/remoteproc/remoteproc0/state
$ echo image_matrix_multiply > /sys/class/remoteproc/remoteproc0/firmware
$ echo start > /sys/class/remoteproc/remoteproc0/state
$ mat_mul_demo
$ echo stop > /sys/class/remoteproc/remoteproc0/state