Addressing Kernels in Bare-Metal Applications - 2025.2 English - UG1076

AI Engine Tools and Flows User Guide (UG1076)

Document ID
UG1076
Release Date
2025-11-20
Version
2025.2 English

For bare-metal applications, when addressing the PL kernels from the embedded application, you must use the control registers, or read and write to the kernel at the appropriate base address and offset as it is implemented in hardware.

A convenient method to inject and extract AXI4-Stream data to and from AI Engine graph PLIO ports is to use MM2S and S2MM PL kernels.

In this case, address the MM2S and S2MM kernels as they are implemented in the PL region of the fixed platform.

The main.cpp of the example shows the #define statements for the kernel base address and the address offset for specific registers. For example:

#define MM2S_BASE XPAR_MM2S_S_AXI_CONTROL_BASEADDR
#define S2MM_BASE XPAR_S2MM_S_AXI_CONTROL_BASEADDR

#define MEM_OFFSET 0x10
#define SIZE_OFFSET 0x1C
#define CTRL_OFFSET 0x0

To determine the address and offsets for the kernels, examine some of the files in the fixed platform. The base address for the implemented kernels is in the fixed platform xparameters.h file. <kernel_driver>_hw.h contains the address offset.

<kernel_driver>_hw.h is located in the <vitis_workspace>/<vitis_platform_name>/export/<vitis_platform_name/sw/standalone/include folder. For the example design, use the following entries in xparameters.h to determine the base addresses of these kernels.

/* Definitions for peripheral MM2S */
#define XPAR_MM2S_S_AXI_CONTROL_BASEADDR 0xA4020000
#define XPAR_MM2S_S_AXI_CONTROL_HIGHADDR 0xA402FFFF

/* Definitions for peripheral S2MM */
#define XPAR_S2MM_S_AXI_CONTROL_BASEADDR 0xA4030000
#define XPAR_S2MM_S_AXI_CONTROL_HIGHADDR 0xA403FFFF

The following code represents a <kernel_driver>_hw.h example for MM2S.

When building Vitis platform component, kernel drivers are added to the <vitis_workspace>/<vitis_platform_name>/export/<vitis_platform_name/sw/standalone/hw_artifacts/drivers folder.

#define XMM2S_MM2S_CONTROL_ADDR_AP_CTRL    0x00
#define XMM2S_MM2S_CONTROL_ADDR_GIE        0x04
#define XMM2S_MM2S_CONTROL_ADDR_IER        0x08
#define XMM2S_MM2S_CONTROL_ADDR_ISR        0x0c
#define XMM2S_MM2S_CONTROL_ADDR_MEM_V_DATA 0x10
#define XMM2S_MM2S_CONTROL_BITS_MEM_V_DATA 64
#define XMM2S_MM2S_CONTROL_ADDR_SIZE_DATA  0x1c
#define XMM2S_MM2S_CONTROL_BITS_SIZE_DATA  32

Use these offsets when reading or writing to the kernels. For instance, from the example application main.cpp file use the following to write to the memory location.

Xil_Out32(MM2S_BASE + MEM_OFFSET, (uint32_t) memAddr);