The libmetal library provides common user APIs for accessing devices, handle interrupts, and request memory across different operating environments. libmetal can be used to build custom AMP (Asymmetric Multi-/Processing) solution.
Xilinx uses the OpenAMP (Open Asymmetric Multi-processing) project as the default AMP solution (UG1186) for SoC, MPSoC and Versal-ACAP Devices/FPGAs. OpenAMP on Xilinx devices allows to enable communication between multiple processors on MPSoC/SoC/Versal-ACAP. OpenAMP supports Linux (Petalinux), FreeRTOS and Baremetal Applications to run across the processors.
For following this tutorial and building this application Petalinux 2021.1 and Vitis IDE (SDK) 2021.1 is required.
Objective of this Work: Running LED blink baremetal program in RPU with OpenAMP frameworks in Petalinux with Ultra96V2 board!Part A: Build blinkLED firmware in VitisCreate a Vivado hardware design file for connecting GPIOs to Zynq-MPSoC
- Open Vitis IDE
- Creat new project by selecting Ultra96-V2 FPGA in board selection
- For creating the hardware design, click Open Block Design in IP integrator- Add AXI_GPIO IP in the block design- Configure AXI_GPIO IP for two output LEDs- Set GPIO in outputs mode and GPIO width to 2 for 2 LED outputs
- Next add Zynq MPSoC IP block in the block Design
- Then click Run Connection Automation to connect all the blocks and add necessary IPs for selected IPs in design
- Now add constaint file to connect the GPIO to respective outputs in the Ultra96 connector pins. Here we are using D7 and F8 pin for the GPIO output in block diagram
- Validate the design and after successful validation, Synthesize, Implement and Create bitstream output for the block design
- Export hardware platform as
.xsa
file with bitstream. This is required to create the platform based project in Vitis IDE - Now in Vitis IDE create the project by using the above
.xsa
file
Part B: Create C code for blinking LED in Vitis IDE (SDK)
Create an new application project by starting Vitis application wizard
- File -> Create New -> New Application Project
- Next assign the xsa file created in Vivado
- Assign project name "hello_led_openamp" and select target processor -
psu-cortexr5_0
- Select standalone application domain for our LED application
- Next select helloworld application template as a starting point for source code
- Now update the helloworld.c with custom code for blinking the LEDs. Here is the code snippet to be updated:
int main(void)
{
int Status;
volatile int Delay;
/* Initialize the GPIO driver */
Status = XGpio_Initialize(&Gpio, GPIO_EXAMPLE_DEVICE_ID);
if (Status != XST_SUCCESS) {
xil_printf("Gpio Initialization Failed\r\n");
return XST_FAILURE;
}
/* Set the direction for all signals as inputs except the LED output */
XGpio_SetDataDirection(&Gpio, LED_CHANNEL, ~LED);
/* Loop forever blinking the LED */
while (1) {
/* Set the LED to High */
XGpio_DiscreteWrite(&Gpio, LED_CHANNEL, LED);
/* Wait a small amount of time so the LED is visible */
for (Delay = 0; Delay < LED_DELAY; Delay++);
/* Clear the LED bit */
XGpio_DiscreteClear(&Gpio, LED_CHANNEL, LED);
/* Wait a small amount of time so the LED is visible */
for (Delay = 0; Delay < LED_DELAY; Delay++);
}
}
- Update the lscript.ld file Memory Register, for reserving DDR memory for the application
- Now build the project to generate the
.elf
hex file in the project Debug folder.
Part C: Create recipe to add blinkLED firmware in Petalinux
Create a petlinux application recipe
petalinux-create -t apps --template install -n freertos-hello-world-r50 --enable
- Create a petlinux application recipe
petalinux-create -t apps --template install -n freertos-hello-world-r50 --enable
- Next copy the above generated
elf
file in the sourc file of the recipes - Modify the recipe for the application to include the RPU firmware ELF built in Vitis into the the rootfs.
$ vim project-spec/meta-user/recipes-apps/freertos-hello-world-r50/freertos-hello-world-r50.bb
#
# This file is the freertos-hello-world-r50 recipe.
#
SUMMARY = "Simple freertos-hello-world-r50 application"
SECTION = "PETALINUX/apps"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI = "file://freertos_hello_world_r50.elf"
S = "${WORKDIR}"
INSANE_SKIP_${PN} = "arch"
do_install() {
install -d ${D}/lib/firmware
install -m 0644 ${S}/freertos_hello_world_r50.elf ${D}/lib/firmware/freertos_hello_world_r50.elf
}
FILES_${PN} = "/lib/firmware/freertos_hello_world_r50.elf"
- Copy the contents of the openamp.dtsi from /project-spec/meta-user/recipes-bsp/device-tree/files into the system-user.dtsi. Please see the dtsi below for reference. NOTE: the node entry for rproc_0_reserved has the same memory region as the one carved out in the lscript.ld in the Vitis application.
/include/ "system-conf.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>;
};
};
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 = <0x18110005>;
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 = <0x1831800b>;
};
tcm_0_b: tcm_0@1 {
reg = <0x0 0xFFE20000 0x0 0x10000>;
pnode-id = <0x1831800c>;
};
};
};
zynqmp_ipi1 {
compatible = "xlnx,zynqmp-ipi-mailbox";
interrupt-parent = <&gic>;
interrupts = <0 33 4>;
xlnx,ipi-id = <5>;
#address-cells = <1>;
#size-cells = <1>;
ranges;
/* APU<->RPU0 IPI mailbox controller */
ipi_mailbox_rpu0: mailbox@ff990600 {
reg = <0xff3f0ac0 0x20>,
<0xff3f0ae0 0x20>,
<0xff3f0740 0x20>,
<0xff3f0760 0x20>;
reg-names = "local_request_region",
"local_response_region",
"remote_request_region",
"remote_response_region";
#mbox-cells = <1>;
xlnx,ipi-id = <3>;
};
};
};
- Also add the OpenAMP package group into petalinux rootfs config
- Build the PetaLinux project and create the BOOT.bin
$ petalinux-build
$ petalinux-package --boot --plm --psmfw --u-boot --dtb
Load the boot and rootfs into sd card and start the Ultra96 board
Part D:Running the blinkLED firmware in RPU
Load and start the firmware using remoteproc sysfs. Run following command to run the hello_led firmware in RPU in petalinux terminal(SSH/serial).
echo hello_led.elf > /sys/class/remoteproc/remoteproc0/firmware
echo start > /sys/class/remoteproc/remoteproc0/state
Corresponding log in dmesg shows firmware loaded and initialization of hello_led firmawre in RPU.
And to stop the program:
echo stop > /sys/class/remoteproc/remoteproc0/state
Corresponding log in dmesg
Thanks for going through this tutorial!
For any Queries on OpenAMP with Petalinux and FreeRTOS/Baremetal, please write us at info@logictronix.com
LogicTronix is Xilinx Certified Partner and also "Design Service Partner for Kria SoM for AI/ML". Know more about LogicTronix from Xilinx Partner Profile: LogicTronix Partner Profile-Link
Comments