In this example the PL addresses portion of the RPU fault injection test is combined with the initialization, configuration, and management of the XMPU_PL module examples that were previously implemented in the PMU. The zupl_xmpu software drivers can be found in the following program:
pl_xmpu_example.cincludes the declarations shown in the following figure.
- SetupInterruptSystem installs the general interrupt controller (GIC) and enables exception handling for interrupts and synchronous data aborts.
- SAbort_DataAbortHandler clears the ArmR5 aborts exception, returns the program pointer to the next instruction, and allows the application to continue operation.
- The readReg and writeReg memory tests use the exception detection to determine PASS/FAIL and prints the result.
- The XMpuPl_IntrHandler responds to interrupts triggered by the zupl_xmpu core’s irq signal. It stores the violation data and clears the interrupt status register.
- The exceptionDetected flag is set by SAbort_DataAbortHandler and indicates that exception has occurred.
- XMpuPl_IntrHandler stores the number of interrupt occurrences in
xmpu_intrand the status of the most previous interrupt in
The main (A) begins with instance declarations for the general interrupt controller and XMPU_PL, followed by the SetupInterruptSystem function call to set up the interrupt controller and exception handling.
Although this example PL design only implements a single XMPU_PL, the
demonstration code declares the XmpuPl instance as an array to support any number of
instances, defined by XMPU_PL_NUM_INST in
#define XMPU_PL_NUM_INST XPAR_ZUPL_XMPU_NUM_INSTANCES
The ZUPL_XMPU parameters are defined in
Initialization of the XMPU_PL instance(s), shown in the following figure, is carried out in a FOR loop. Each instance number represents the Device ID.
The interrupt ID for instance 0 is defined
#define XMPU_PL_INTR_ID XPAR_FABRIC_ZUPL_XMPU_0_IRQ_INTR
For each instance, the interrupt ID is registered to the XMpuPl_IntrHandler function which is passed the starting address of the instance array as its parameter. Since the design only contains a single instance, only instance 0 is configured.
The CTRL register is configured with default read allowed, default write
allowed, poison attribute and poison address enabled, and poisoned AXI response DECERR,
by XMPU_CTLR_VAL defined in
#define XMPU_CTRL_VAL ( XMPU_PL_CTRL_DEFRD \ | XMPU_PL_CTRL_DEFWR \ | XMPU_PL_CTRL_PSNATTREN \ | XMPU_PL_CTRL_PSNADDREN \ | XMPU_PL_CTRL_ARSP_DEC)
The defined register offsets and configuration options are found in the
zupl_xmpu SW driver file
zupl_xmpu_hw.h. The LOCK
BYPASS register configuration allows the PMU and RPU0 to have write access after the
LOCK is enabled.
#define XMPU_LOCK_MASTERS ( XMPU_PL_MID_PMU | XMPU_PL_MID_RPU0 )
Read and write violations are enabled interrupts by XMPU_INT_EN.
#define XMPU_INT_EN (XMPU_PL_IXR_WRVIO_MSK \ | XMPU_PL_IXR_RDVIO_MSK)
Region 0 is set to a 1 KB size starting at the base of the secure (S) BRAM area, and configured with the following parameters:
#define REGION_0_ADDR PL_BRAM_S_BASE #define REGION_0_MASTERS ( XMPU_PL_MID_RPU0 ) #define REGION_0_CFG ( XMPU_PL_REGION_WR_ALLOW \ | XMPU_PL_REGION_RD_ALLOW \ | XMPU_PL_REGION_ENABLE )
Only RPU0 has read and write privileges.
Region 1 is also set to a 1 KB size starting at the base of the non-secure (NS) BRAM area, and configured with the following parameters:
#define REGION_1_ADDR PL_BRAM_NS_BASE #define REGION_1_MASTERS ( XMPU_PL_MID_APU ) #define REGION_1_CFG ( XMPU_PL_REGION_WR_ALLOW \ | XMPU_PL_REGION_RD_ALLOW \ | XMPU_PL_REGION_ENABLE )
Only the APU has read and write privileges. PL_BRAM_NS_SHARED is set to an address between region 0 end and region 1 start. A region miss falls to the default settings specified in the CTRL registers that gives read and write access to all masters making the memory space shared.
The rest of main () runs the read/write tests and finally prints the number of interrupts recorded by the interrupt handler, XMpuPl_IntrHandler, shown in the following figure. In this example, one interrupt handler is shared by all instances. The interrupt status register of each instance is checked until an active violation is found. The interrupt status is stored, the number of interrupts is incremented, and then the interrupt status is cleared. If there is more than one instance issuing an interrupt, the handler gets recalled until all interrupts are cleared.
This is an example of one way a designer chooses to configure and handle the zupl_xmpu_v1_0 core. Additionally, you can add multiple instances into the PL design and add their configurations to this application. This is left for you as an exercise.