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.
Looking at the application discussed earlier, the embedded application can deliver
data to the
MM2S kernel, to introduce it to the
AI Engine graph for the
Classifier kernels, and read data from the
S2MM kernel to continue processing in the embedded application. In
this case, address the
S2MM kernels as they are implemented in the PL region
of the fixed platform.
main.cpp of the example shows
#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 location of the base address for the
implemented kernels is located in the fixed platform xparameters.h file, that is located in the
<platform_name>/standalone_domain/bspinclude/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
xparameters.hfile is generated and addressing is dynamic. It is best to reference the address macros for kernels than to hard code them.
The location of the address offset is located in the <kernel_driver>_hw.h file of the _x/<kernel>/<kernel>/<kernel>/solution/impl/ip/drivers/<kernel>_v1_0/src
folder of the compiled kernel produced by the
compiler. For example, the
MM2S kernel driver, xmm2s_mm2s_hw.h displays the following data.
#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);