ZYNQ UltraScale+ MPSoC OpenAMP 2019.1
本文面旨在补充 适用于 Zynq-7000 和 Zynq UltraScale+ MPSoC 的UG1186“LibMetal 和 OpenAMP 用户指南” (2019.1)
目录
- ZYNQ UltraScale+ MPSoC OpenAMP 2019.1
- 快速尝试
- 文档和源代码
- 其他示例
- ZynqMP Linux Master 运行在 APU 上,内核空间中带有 RPMsg 和 2 个 RPU slaves
- ZynqMP Linux Master 在 APU 上运行,RPMsg 在用户空间和 2 个 RPU slaves
- ZynqMP Linux Master 在 APU 上运行,内核空间中带有 RPMsg 和一个 RPU slave。
- 在 APU Linux 上运行的 ZynqMP Linux Master 加载 OpenAMP RPU 固件
- ZynqMP Linux 加载 RPU,Linux OpenAMP 应用程序与 RPU OpenAMP 应用程序交互
- APU Linux 上的 ZynqMP 通过共享内存与 RPU 通信,无需 OpenAMP
- 功能变化
快速尝试
以下是启动 Linux 和使用预构建映像运行 openAMP 应用程序的基本步骤。
例如对于 ZCU102:
echo测试应用程序将数据包从运行在四核 Cortex-A53 上的 Linux 发送到运行 FreeRTOS 的单个 Cortex-R5,然后再将它们发回。
- 将文件 BOOT.BIN、image.ub 和 openamp.dtb 文件从预构建的 Petalinux BSP tarball 提取到 sd card
host shell$ tar xvf xilinx-zcu102-v2019.1-final.bsp --strip-components=4 --wildcards */BOOT.BIN */image.ub */openamp.dtb
host shell$ cp BOOT.BIN image.ub openamp.dtb <your sd card>
注意:另外,如果您已经使用为您的开发板提供的 BSP 创建了一个 Petalinux 项目,则还可以在 /pre-built/linux/images / 目录下找到预构建的镜像。
- 转到 u-boot 提示符并从 sd card 启动 Linux
Hit any key to stop autoboot: 0
ZynqMP> mmcinfo && fatload mmc 0 ${netstart} ${kernel_img} && fatload mmc 0 0x14000000 openamp.dtb
Device: sdhci@ff170000
...
reading image.ub
31514140 bytes read in 2063 ms (14.6 MiB/s)
reading openamp.dtb
38320 bytes read in 18 ms (2 MiB/s)
ZynqMP> bootm $netstart $netstart 0x14000000
注意:作为上述所有 sd-boot 步骤的替代方法,您可以 jtag-boot 板。为此,您需要连接 jtag 电缆、安装 jtag 驱动程序并使用提供的 BSP 创建 Petalinux 项目。然后,您将进入/pre-built/linux/images目录并将文件system.dtb替换为openamp.dtb,然后输入:“petalinux-boot --jtag --prebuilt 3”
- 在 Linux 登录提示符下,输入“root”作为用户名,输入“root”作为密码,然后运行 echo-test demo.
plnx_aarch64 login: root
Password:
root@plnx_aarch64:~# echo image_echo_test > /sys/class/remoteproc/remoteproc0/firmware
root@plnx_aarch64:~# echo start > /sys/class/remoteproc/remoteproc0/state
[ 177.375451] remoteproc remoteproc0: powering up ff9a0100.zynqmp_r5_rproc
[ 177.384705] remoteproc remoteproc0: Booting fw image image_echo_test, size 644144
[ 177.396832] remoteproc remoteproc0: registered virtio0 (type 7)
[ 177.399108] virtio_rpmsg_bus virtio0: rpmsg host is online
[ 177.412370] zynqmp_r5_remoteproc ff9a0100.zynqmp_r5_rproc: RPU boot from TCM.
[ 17Starting application...
Try to init remoteproc resource
Init remoteproc resource succeeded
Waiting for events...
7.422089] remoteproc remoteproc0: remote processor ff9a0100.zynqmp_r5_rproc is now up
[ 177.442121] virtio_rpmsg_bus virtio0: creating channel rpmsg-openamp-demo-channel addr 0x1
root@plnx_aarch64:~# echo_test
Echo test start
Open rpmsg dev!
文档和源代码
文件
- 以下文档描述了 libmetal API:
libmetal
源代码的 URL
Xilinx Openamp 和 Libmetal 相关代码
以下位置提供对代码的访问:
- OpenAMP 库和演示代码
- Libmetal 库和演示代码
- 构建 OpenAMP 和 Libmetal 的 Yocto recipe
- Xilinx 版本的 Linux 内核
- XSDK 和 XSCT 中使用的 RPU 裸机和 FreeRTOS 源代码
其他示例
ZynqMP Linux Master 运行在 APU 上,内核空间中带有 RPMsg 和 2 个 RPU slaves
启用 Linux 驱动程序和其他软件包
按照UG1186中的说明,启用Linux remoteproc驱动支持和其他openamp软件包。
设备树:
- 将以下内容添加到 <petalinux 项目>/project-spec/meta-user/recipes-bsp/device-tree/file/system-user.dtsi
/include/ "system-conf.dtsi"
/ {
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
rproc_0_dma_reserved: rproc@3ed40000{
no-map;
compatible = "shared-dma-pool";
reg = <0x0 0x3ed40000 0x0 0x100000>;
};
rproc_0_fw_reserved: rproc@3ed00000 {
no-map;
reg = <0x0 0x3ed00000 0x0 0x40000>;
};
rproc_1_fw_reserved: rproc@3ee00000{
no-map;
reg = <0x0 0x3ef00000 0x0 0x40000>;
};
rproc_1_dma_reserved: rproc@3ee40000 {
compatible = "shared-dma-pool";
no-map;
reg = <0x0 0x3ef40000 0x0 0x100000>;
};
};
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_fw_reserved>, <&rproc_0_dma_reserved>;
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>;
};
};
r5_1: r5@1 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
memory-region = <&rproc_1_fw_reserved>, <&rproc_1_dma_reserved>;
pnode-id = <0x8>;
mboxes = <&ipi_mailbox_rpu1 0>, <&ipi_mailbox_rpu1 1>;
mbox-names = "tx", "rx";
r5_1_tcm_a: tcm@ffe90000 {
reg = <0x0 0xFFE90000 0x0 0x10000>;
pnode-id = <0x11>;
};
r5_1_tcm_b: tcm@ffeb0000 {
reg = <0x0 0xFFEB0000 0x0 0x10000>;
pnode-id = <0x12>;
};
};
};
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@ff90600 {
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>;
};
};
zynqmp_ipi2 {
compatible = "xlnx,zynqmp-ipi-mailbox";
interrupt-parent = <&gic>;
interrupts = <0 30 4>;
xlnx,ipi-id = <8>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
/* APU<->RPU1 IPI mailbox controller */
ipi_mailbox_rpu1: mailbox@ff3f0b00 {
reg = <0xff3f0b00 0x20>,
<0xff3f0b20 0x20>,
<0xff3f0940 0x20>,
<0xff3f0960 0x20>;
reg-names = "local_request_region",
"local_response_region",
"remote_request_region",
"remote_response_region";
#mbox-cells = <1>;
xlnx,ipi-id = <2>;
};
};
};
*/
&i2c1 {
/* FIXME PL i2c via PCA9306 - u45 */
/* FIXME MSP430 - u41 - not detected */
i2c-mux@74 { /* u34 */
i2c@0 { /* i2c mw 74 0 1 */
/*
* IIC_EEPROM 1kB memory which uses 256B blocks
* where every block has different address.
* 0 - 256B address 0x54
* 256B - 512B address 0x55
* 512B - 768B address 0x56
* 768B - 1024B address 0x57
*/
eeprom: eeprom@54 { /* u23 */
compatible = "atmel,24c08";
reg = <0x54>;
};
};
};
};
- 重建设备树
petalinux-build -c device-tree
使用 Xilinx SDK 构建远程处理器演示应用程序:
对于 RPU 0 (cortex_r5_0)
按照 UG1186 中的说明进行操作,使用 Xilinx SDK 生成远程处理器 openamp 应用程序。
在Petalinux BSPs提供的预建应用程序中,也默认使用RPU 0。
对于 RPU 1 (cortex_r5_1)
远程处理器应用程序(echo_test、矩阵乘法、rpc 演示)代码默认设置为使用 RPU 0 运行,需要针对 RPU-1 稍作修改。在 Xilinx SDK 中选择 RPU-1 时,生成的代码需要修改如下:
- 检查 rsc_table.c 中的 RING_TX、RING_RX 条目是否在设备树中定义的保留内存部分内,但不与其中的任何其他部分重叠。(例如 RPU 0/1 的 DDR、vring 设备节点等)
- 检查链接描述文件地址是否匹配并适合 DTS zynqmp_r5_rproc 内存部分。
示例:在 Linux 上同时运行两个 echo_test 应用程序,每个应用程序都与一个单独的 RPU 通信
- 使用 Petalinux 构建/引导您的目标,然后登录到 Linux 控制台串行端口。
- 如果您尚未将远程处理器固件应用程序添加到您的 Linux 根文件系统(请参阅 ug1186 的第 3 章)
- 这些应用程序可以在目标目录 /lib/firmware 中 tftp’d
- 检查 remoteproc 驱动程序是否已加载(通常是如果您的设备树配置正确):
root@plnx_aarch64:/lib/firmware# lsmod
Tainted: G
virtio_rpmsg_bus 20480 0 - Live 0xffffff800098e000
rpmsg_core 16384 1 virtio_rpmsg_bus, Live 0xffffff800097c000
zynqmp_r5_remoteproc 16384 0 - Live 0xffffff800096a000
remoteproc 40960 1 zynqmp_r5_remoteproc, Live 0xffffff8000959000
virtio 16384 2 virtio_rpmsg_bus,remoteproc, Live 0xffffff8000951000
virtio_ring 20480 2 virtio_rpmsg_bus,remoteproc, Live 0xffffff8000948000
uio_pdrv_genirq 16384 0 - Live 0xffffff8000940000
- 启动 RPU-0:
root@plnx_aarch64:/lib/firmware# echo image_echo_test_r5_0 > /sys/class/remoteproc/remoteproc0/firmware
root@plnx_aarch64:/lib/firmware#
root@plnx_aarch64:/lib/firmware# echo start > /sys/class/remoteproc/remoteproc0/state
root@plnx_aarch64:/lib/firmware#
[70982.961635] remoteproc remoteproc0: powering up ff9a0100.zynqmp_r5_rproc
[70982.971366] remoteproc remoteproc0: Booting fw image image_echo_test_r5_0, size 638724
[70982.985672] virtio_rpmsg_bus virtio0: rpmsg host is online
[70982.993691] remoteproc remoteproc0: registered virtio0 (type 7)
[70983.002197] zynqmp_r5_remoteproc ff9a0100.zynqmp_r5_rproc: RPU boot from TCM.
[7Starting application...
Try to init remoteproc resource
Init remoteproc resource succeeded
Waiting for events...
0983.012367] remoteproc remoteproc0: remote processor ff9a0100.zynqmp_r5_rproc is now up
[70983.032821] virtio_rpmsg_bus virtio0: creating channel rpmsg-openamp-demo-channel addr 0x1
- 启动 RPU-1:
root@plnx_aarch64:/lib/firmware# echo image_echo_test_r5_1 > /sys/class/remoteproc/remoteproc1/firmware
root@plnx_aarch64:/lib/firmware#
root@plnx_aarch64:/lib/firmware# echo start > /sys/class/remoteproc/remoteproc1/state
[71185.157615] remoteproc remoteproc1: powering up ff9a0200.zynqmp_r5_rproc
[71185.167453] remoteproc remoteproc1: Booting fw image image_echo_test_r5_1, size 639140
[71185.182180] virtio_rpmsg_bus virtio1: rpmsg host is online
[71185.190226] remoteproc remoteproc1: registered virtio1 (type 7)
[71185.198724] zynqmp_r5_remoteproc ff9a0200.zynqmp_r5_rproc: RPU boot from TCM.
[7Starting application...
Try to init remoteproc resource
Init remoteproc resource succeeded
Waiting for events...
1185.208915] remoteproc remoteproc1: remote processor ff9a0200.zynqmp_r5_rproc is now up
[71185.229420] virtio_rpmsg_bus virtio1: creating channel rpmsg-openamp-demo-channel addr 0x1
- 使用串行端口或其他 telnet 或 ssh 连接运行带有 RPU-0 的 echo_test Linux 应用程序:
root@plnx_aarch64:/lib/firmware# echo_test
Echo test start
Open rpmsg dev!
- 使用另一个连接(telnet、ssh…)运行带有 RPU-1 的并发 echo_test Linux 应用程序:
root@plnx_aarch64:/lib/firmware# echo_test -d /dev/rpmsg1
Echo test start
Open rpmsg dev!
注意:启动 RPU 的顺序决定了哪个 /dev/rpmsgX 设备与该 RPU 一起使用。
在上述情况下,/dev/rpmsg0 用于 RPU-0。
然而,如果首先启动 RPU-1,它会与 /dev/rpmsg0 相关联,而 RPU-0 会一直使用 /dev/rpmsg1。
ZynqMP Linux Master 在 APU 上运行,RPMsg 在用户空间和 2 个 RPU slaves
- 将以下设备树内容添加到 <petalinux 项目>/project-spec/meta-user/recipes-bsp/device-tree/file/system-user.dtsi
/ {
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
/* Reserved memory for both firmware and shared memory */
rproc_0_reserved: rproc@3ed00000 {
no-map;
reg = <0x0 0x3ed00000 0x0 0x8000000>;
};
};
amba {
vring: vring@0 {
compatible = "vring_uio";
reg = <0x0 0x3ed40000 0x0 0x40000>;
};
shm0: shm@0 {
compatible = "shm_uio";
reg = <0x0 0x3ed80000 0x0 0x80000>;
};
vring1: vring@1 {
compatible = "vring_uio";
reg = <0x0 0x3ef00000 0x0 0x40000>;
};
shm1: shm@1 {
compatible = "shm_uio";
reg = <0x0 0x3ef40000 0x0 0x80000>;
};
ipi0: ipi@0 {
compatible = "ipi_uio";
reg = <0x0 0xff340000 0x0 0x1000>;
interrupt-parent = <&gic>;
interrupts = <0 29 4>;
};
};
};
- 使用“ petalinux-config -c rootfs ”启用 OpenAMP 和 libmetal 包:
Filesystem Packages --->
libs --->
libmetal --->
[*] libmetal
open-amp --->
[*] open-amp
使用 XSDK 构建 Linux OpenAMP 用户空间应用程序
- Create Empty Application for Linux and for A53
- 操作系统:Linux
- 处理器:psu_cortexa53
- Linux sysroot: 来自 Petalinux 项目的 sysroot:
- < plnx-proj-root >/images/linux/sdk/sysroots/aarch64-xilinx-linux
- 构建项目后,选择属性:
- C/C++ Build --> Settings
- Tool Settings Tab Libraries
- Libaries (-l) add “metal” and “open_amp”
- Miscellaneous
- 在链接器flag中,添加"–sysroot=//images/linux/sdk/sysroots/aarch64-xilinx-linux"
- Tool Settings Tab Libraries
- C/C++ Build --> Settings
- 将 ZynqMP 的 OpenAMP 应用程序的以下文件复制到目录中:
- 以及链接中三个 OpenAMP 应用程序之一的 Linux 文件:
- OpenAMP echo-test
- OpenAMP matrix multiplication Demo
- OpenAMP RPC Demo
- 在构建应用程序时注意一些配置参数:
- 如果构建 Linux 应用程序以与 RPU 1 通信:
- 替换 platform_info.c 中的以下内容:将 IPI_MASK 更改为 0x200
- RSC_RPROC_MEM 条目必须在相应的 vring 设备树节点内。
- 更新Linux应用程序的platform_info.c里面的以下内容,以反映设备树节点的可能变化:
- IPI_DEV_NAME
- VRING_DEV_NAME
- SHM_DEV_NAME
- 上面的意思是,如果设备树条目中的新 vring 条目位于 0x3ef00000,那么 VRING_DEV_NAME 的字符串现在应该是“3ef00000.vring”,如目标上的 sysfs 中所示.
- 更新 RING_TX 和 RING_RX 以反映设备树中的 vring 条目.
- 如果构建 Linux 应用程序以与 RPU 1 通信:
在 Petalinux 项目中安装 XSDK 构建的 Linux 应用程序
Linux 应用程序可以通过 yocto recipe 安装,如下所示:
SUMMARY = "Simple test application"
SECTION = "PETALINUX/apps"
LICENSE = "MIT"
LIC_FILES_CHKSUM =
"file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://<myapp>"
S = "${WORKDIR}"
INSANE_SKIP_${PN} = "arch"
do_install() {
install -d ${D}/lib/firmware
install -m 0644 ${S}/<myapp> ${D}/lib/firmware/<myapp>
}
FILES_${PN} = "/lib/firmware/<myapp>
使用 Xilinx SDK 构建远程处理器演示应用程序以在 RPU 0 (cortex_r5_0) 上运行
按照 UG1186 中的说明进行操作,使用 Xilinx SDK 生成远程处理器 openamp 应用程序。
使用 Xilinx SDK 构建远程处理器演示应用程序以在 RPU 1 (cortex_r5_1) 上运行
远程处理器应用程序(echo_test、矩阵乘法、rpc 演示)代码默认设置为使用 RPU 0 运行,需要针对 RPU-1 稍作修改.
- 在 Xilinx SDK 中选择 RPU-1 时,生成的代码需要修改如下: 编辑 rsc_table.c,使 RING_TX 和 RING_RX 在 vring 设备树节点的内存中。
- 检查链接器脚本的匹配地址是否在保留内存内,但不重叠。
示例:在 Linux 上同时运行两个 proxy_app-openamp 应用程序,每个应用程序与一个 RPU 通信
- 使用从 XSDK 构建的 RPU 固件生成 BOOT.BIN。下面是一个 BIF 示例:
the_ROM_image:
{
[fsbl_config] a53_x64
[bootloader] <plnx project>/images/linux/zynqmp_fsbl.elf
[destination_device=pl] <plnx project/images/linux/download.bit
[destination_cpu=pmu] <plnx project>/images/linux/pmufw.elf
[destination_cpu=r5-0] /path/to/openamp_firmware_on_rpu0.elf
[destination_cpu=r5-1] /path/to/openamp_firmware_on_rpu1.elf
[destination_cpu=a53-0, exception_level=el-3, trustzone] <plnx project>/images/linux/bl31.elf
[destination_cpu=a53-0, exception_level=el-2] <plnx project>/images/linux/u-boot.elf
}
- 启动时,RPU 0 和 RPU 1 的 RPU 固件应该有类似以下的输出:
Starting application...
Try to init remoteproc resource
Init remoteproc resource succeeded
Waiting for events...
- 使用串行端口或其他 telnet 或 ssh 连接运行带有 RPU-0 的 proxy_app-openamp Linux 应用程序:
root@plnx_aarch64# proxy_app-openamp
metal: info: metal_uio_dev_open: No IRQ for device 3ed40000.vring.
metal: info: Initializating I/Os redirection...
metal: info: metal_uio_dev_open: No IRQ for device 3ed40000.vring.
metal: info: metal_uio_dev_open: No IRQ for device 3ed80000.shm.
Master> Remote proc resource initialized.
Master> RPMSG channel has created.
Remote>Baremetal Remote Procedure Call (RPC) Demonstration
- 使用另一个连接(telnet、ssh…)运行具有 RPU-1 的并发 proxy_app-openamp Linux 应用程序:
root@xilinx-zcu102-2019_2:~# linux_proxy_userspace_to_r5_1.elf
metal: info: metal_uio_dev_open: No IRQ for device 3ef00000.vring.
metal: iInitializating I/Os redirection...
nfo: metal_uio_dev_open: No IRQ for device 3ef00000.vring.
metal: info: metal_uio_dev_open: No IRQ for device 3ef40000.shm.
Master> Remote proc resource initialized.
Master> RPMSG channel has created.
Remote>Baremetal Remote Procedure Call (RPC) Demonstration
ZynqMP Linux Master 在 APU 上运行,内核空间中带有 RPMsg 和一个 RPU slave。
当 RPU 在分离模式下运行并且只有一个 RPU 是 OpenAMP 从属设备时,第二个 RPU 仍然可以运行另一个非 OpenAMP 应用程序。
- RPU-0 slave:
- Petalinux BSP 提供了一个默认模板来生成支持在 RPU-0 上运行的 OpenAMP 的 DTB,请参阅:
- <petalinux 项目>/project-spec/meta-usr/recipes-bsp/device-tree/files/openamp-overlay.dtsi >
- 将其内容添加到文件 <petalinux 项目>/project-spec/meta-user/recipes-bsp/device-tree/file/system-user.dtsi
- Petalinux BSP 提供了一个默认模板来生成支持在 RPU-0 上运行的 OpenAMP 的 DTB,请参阅:
- RPU-1 slave
- 按照上面两个RPU的配置进行,编辑你的设备树,删除未使用的 "zynmp_r5_rproc "条目和可能不再需要的相关节点(tcm,pd,…)。
在 APU Linux 上运行的 ZynqMP Linux Master 加载 OpenAMP RPU 固件
概述
以下信息旨在为希望在 APU 上设置 Linux + 在 RPU 上的裸机/RTOS 的用户提供指导。此配置依赖 FSBL 启动 APU 上运行的软件,然后使用 remoteproc 的 APU Linux 将加载 RPU。
使用 Linux 通过 APU 引导 RPU 固件
这些说明假设用户已经为 RPU 生成了固件,并且用户正在使用 Petalinux 来创建他们的嵌入式 Linux 解决方案。
- 按照 UG 1186 中的指示,在 Petalinux 项目中创建一个应用程序,以将固件安装到 Linux 主机的文件系统中的 /lib/firmware。要为 yocto recipe 创建模板以安装固件,请执行以下操作:
- 在 Petalinux 项目中创建 yocto 应用程序
petalinux-create -t apps --template install -n <app_name> --enable
- 将固件(.elf 文件)复制到 project-spec/meta-user/recipes-apps/<app_name>/files/ 目录
- 修改 project-spec/meta-user/recipes-apps/<app_name>/<app_name>.bb 以在 RootFS 中安装远程处理器固件,如下所示:
SUMMARY = "Simple test application"
SECTION = "PETALINUX/apps"
LICENSE = "MIT"
LIC_FILES_CHKSUM ="file:${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file:<myfirmware>"
S = "${WORKDIR}"
INSANE_SKIP_${PN} = "arch"
do_install() {
install -d ${D}/lib/firmware
install -m 0644 ${S}/<myfirmware> ${D}/lib/firmware/<myfirmware>
}
FILES_${PN} = "/lib/firmware/<myfirmware>
- 在 PetaLinux 项目中使用“petalinux-build”命令构建 Linux 映像。
- 在 project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi 修改设备树。例如:
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
/* R5 0 firmware memory in DDR */
rproc_0_fw_reserved: rproc@3ed00000 {
no-map;
reg = <0x0 0x3ed00000 0x0 0x40000>;
};
/* DMA shared memory between APU and RPU */
rproc_0_dma_reserved: rproc@3ed40000 {
compatible = "shared-dma-pool";
no-map;
reg = <0x0 0x3ed40000 0x0 0x100000>;
};
};
zynqmp-r5-remoteproc@0 {
compatible = "xlnx,zynqmp-r5-remoteproc-1.0";
core_conf = "split";
#address-cells = <2>;
#size-cells = <2>;
ranges;
r5-0: r5@0 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
memory-region = <&rproc_0_fw_reserved>,
<&rproc_0_dma_reserved>;
pnode-id = <0x7>;
mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
mbox-names = "tx", "rx";
tcm-a: tcm@0 {
reg = <0x0 0xFFE00000 0x0 0x10000>,
pnode-id = <0xf>;
};
tcm-b: tcm@1 {
reg = <0x0 0xFFE20000 0x0 0x10000>,
pnode-id = <0x10>;
};
};
} ;
zynqmp_ipi {
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@ff90600 {
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 项目。
petalinux-build
启动 Petalinux 项目后,运行以下命令将 RPU 固件启动到 RPU。
echo <name of firmware> > /sys/class/remoteproc/remoteproc0/firmware
- 运行 Linux 应用程序
echo start > /sys/class/remoteproc/remoteproc0/state
- 停止固件
echo stop > /sys/class/remoteproc/remoteproc0/state
ZynqMP Linux 加载 RPU,Linux OpenAMP 应用程序与 RPU OpenAMP 应用程序交互
概述
设置远程固件
例如,用户可以使用与在 UG1186 的构建远程应用程序部分中创建的 OpenAMP RPU 应用程序类似的结构。
使用 Linux 通过 APU 引导 RPU 固件
这些说明假设用户已经为 RPU 生成了固件,并且用户正在使用 Petalinux 来创建他们的嵌入式 Linux 解决方案。
- 按照 UG 1186 中的说明,在 Petalinux 项目中创建一个 yocto recipe,以将固件安装到 Linux 主机的 /lib/firmware 文件系统中。
有关如何创建此类 yocto recipe 的指南,请参阅前面的示例:“在 APU Linux 上运行的 ZynqMP Linux Master 加载 OpenAMP RPU 固件”。 - 在 project-spec/meta-user/recipes-bsp/device-tree/files/system-user.dtsi 修改设备树。例如:
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
ranges;
/* R5 0 firmware memory in DDR */
rproc_0_fw_reserved: rproc@3ed00000 {
no-map;
reg = <0x0 0x3ed00000 0x0 0x40000>;
};
/* DMA shared memory between APU and RPU */
rproc_0_dma_reserved: rproc@3ed40000 {
compatible = "shared-dma-pool";
no-map;
reg = <0x0 0x3ed40000 0x0 0x100000>;
};
};
zynqmp-r5-remoteproc@0 {
compatible = "xlnx,zynqmp-r5-remoteproc-1.0";
core_conf = "split";
#address-cells = <2>;
#size-cells = <2>;
ranges;
r5-0: r5@0 {
#address-cells = <2>;
#size-cells = <2>;
ranges;
memory-region = <&rproc_0_fw_reserved>,
<&rproc_0_dma_reserved>;
pnode-id = <0x7>;
mboxes = <&ipi_mailbox_rpu0 0>, <&ipi_mailbox_rpu0 1>;
mbox-names = "tx", "rx";
tcm-a: tcm@0 {
reg = <0x0 0xFFE00000 0x0 0x10000>,
pnode-id = <0xf>;
};
tcm-b: tcm@1 {
reg = <0x0 0xFFE20000 0x0 0x10000>,
pnode-id = <0x10>;
};
};
} ;
zynqmp_ipi {
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@ff90600 {
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>;
};
/* UIO device node for vring device memory */
vring: vring@0 {
compatible = "vring_uio";
reg = <0x0 0x3ed40000 0x0 0x40000>;
};
/* UIO device node for shared memory device memory */
shm0: shm@0 {
compatible = "shm_uio";
reg = <0x0 0x3ed80000 0x0 0x80000>;
};
/* UIO device node for IPI device */
ipi0: ipi@0 {
compatible = "ipi_uio";
reg = <0x0 0xff340000 0x0 0x1000>;
interrupt-parent = <&gic>;
interrupts = <0 29 4>;
};
};
};
使用所需的软件包构建 Petalinux
- 使用 petalinux 工具启用所需的软件包。例如,转到 petalinux 项目的最顶层目录并启动 rootfs 配置实用程序:
petalinux-config -c rootfs
- 启用应用程序所需的 rootfs 包。如果您从 UG1186 运行示例应用程序,则可以通过以下方式启用这些包:
Filesystem Packages
--> libs
--> libmetal
--> [ * ] libmetal
--> openamp
--> [ * ] open-amp
--> misc
--> openamp-fw-echo-testd
--> [ * ] openamp-fw-echo-testd
--> openamp-fw-mat-muld
--> [ * ] openamp-fw-mat-muld
--> openamp-fw-rpc-demod
--> [ * ] openamp-fw-rpc-demod
--> rpmsg-echo-test
--> [ * ] rpmsg-echo-test
--> rpmsg-mat-mul
--> [ * ] rpmsg-mat-mul
--> rpmsg-proxy-app
--> [ * ] rpmsg-proxy-app
- 然后构建 petalinux 项目。
petalinux-build
加载固件并逐步启动固件:
echo <fw_name> /sys/class/remoteproc/remoteproc0/firmware
echo start > /sys/class/remoteproc/remoteproc0/state
停止固件:
echo stop > /sys/class/remoteproc/remoteproc0/state
APU Linux 上的 ZynqMP 通过共享内存与 RPU 通信,无需 OpenAMP
概述
以下信息旨在为希望设置 Linux + 裸机、RTOS 等的用户提供指导。我们假设 Linux 和 RPU 将通过共享内存进行通信。IPI 可用于进一步协调处理器之间的通信。IPI 的使用记录在标题为
Linux 的设备树设置
* 为了使运行在 APU 上的 Linux 可以访问共享内存设备,必须对设备树进行一些修改。
* 例如,如果为此处找到的 OpenAMP echo_test 演示配置设备树,则会在 amba 部分中放置一个共享内存节点。例如:
/{
amba {
/* UIO device node for shared memory device memory */
shm0: shm@0 {
compatible = "shm_uio";
reg = <0x0 0x3ed80000 0x0 0x80000>;
};
};
};
配置 Petalinux 项目
OpenAMP 应用程序使用 Libmetal 来访问共享内存。因此,必须启用 petalinux 项目中的 libmetal 包。可以通过使用 petalinux-config 实用程序进入 rootfs 来启用此软件包。
运行:
petalinux-config -c rootfs
然后在实用程序中启用以下软件包:
Filesystem Packages
--> libs
--> libmetal
--> [ * ] libmetal
--> openamp
--> [ * ] open-amp
--> misc
--> openamp-fw-echo-testd
--> [ * ] openamp-fw-echo-testd
--> openamp-fw-mat-muld
--> [ * ] openamp-fw-mat-muld
--> openamp-fw-rpc-demod
--> [ * ] openamp-fw-rpc-demod
--> rpmsg-echo-test
--> [ * ] rpmsg-echo-test
--> rpmsg-mat-mul
--> [ * ] rpmsg-mat-mul
--> rpmsg-proxy-app
--> [ * ] rpmsg-proxy-app
通过共享内存进行通信
以下信息是在假设共享内存节点在 Linux 用户空间中可见的情况下构建的。
使用 Libmetal API,我们可以使用以下函数读取和写入共享内存:
static inline uint64_t metal_io_read(struct metal_io_region *io, unsigned long offset, memory_order order, int width);
int metal_io_block_read(struct metal_io_regoin *io, unsigned long offset, void * restrict dst, int len);
And
static inline void metal_io_write(struct metal_io_region *io, unsigned long offset, uint64_t value, memory_order order, int width);
int metal_io_block_write(struct metal_io_region *io, unsigned long offset, const void *restrict src, int len);
可以在 此处找到显示在 Linux 用户空间中使用这些函数的示例。链接中的一些示例显示了读取和写入共享内存以及初始化和清理 Libmetal 资源的使用。
如何生成 BOOT.BIN
本节假定你的 Petalinux 项目已经运行 Petalinux-build 来构建嵌入式 Linux 解决方案的所有必要组件,以及在 RPU 上运行的固件。 使用 Petalinux 工具构建 BOOT.BIN,然后您可以将其放在 SD 卡上以启动 ZynqMP 板。 下面是一个示例 bootgen.bif 文件,您可以在 Petalinux 项目的顶级目录中创建或修改该文件,您可以使用它来帮助构建 BOOT.BIN:
the_ROM_image:
{
[fsbl_config] a53_x64
[bootloader, destination_cpu=a53-0] ./images/linux/zynqmp_fsbl.elf
[pmufw_image, destination_cpu=a53-0] ./images/linux/pmufw.elf
[destination_cpu=a53-0, exception_level=el-3, trustzone] ./images/linux/bl31.elf
[destination_cpu=a53-0, exception_level=el-2] ./images/linux/u-boot.elf
}
使用这个 .bif 文件和 petalinux 工具,我们将构建一个 BOOT.BIN 文件,您可以将其用于您的 ZynqMP 板子。
petalinux-package --boot --force --u-boot ./images/linux/u-boot.elf --cpu r5-0 --add /path/to/firmware
在这里,我们展示了一些东西:
- 我们使用 --cpu 选项和 r5-0 指定数据文件(您的固件)将发送到哪个 RPU。您还可以使用 r5-1 或 r5-lockstep 选项。
- –add 选项,其中以下参数指定固件的路径。
- –force 选项将现有的 BOOT.BIN 文件覆盖到当前目录中。
- –u-boot 选项指定 u-boot.elf 的位置
功能变化
Module Name | Change | Link |
---|---|---|
OpenAMP 回声测试和矩阵乘法演示 | 无需用户手动输入即可运行。相反,添加 -n 命令行选项以指定迭代次数 | 补丁链接 |
Xen Dom0 和 DomU 支持在 RPMsg 用户空间中运行的 OpenAMP | 2018.1对这两种配置的支持 | |
RPMsg 字符驱动支持(实验性) | 能够使用 rpmsg char 驱动程序运行 RPMsg OpenAMP 演示。启用此功能的补丁尚未在上游。 | 补丁链接 |
libmetal MicroBlaze 裸机支持 | 向 libmetal 添加 MicroBlaze 裸机支持 | 链接到源代码 |
为在 RPU0 和 RPU1 上运行的 OpenAMP echo demo 添加修复以挂起大量有效载荷 | 更新 Embeddedsw 中的 GIC 驱动程序,以便可以将相关中断映射或取消映射到 CPU。 | 补丁链接 |