Here are steps and code snippets illustrating how to inject an error in the configuration RAM for test purposes.
- Stop Scan
/*To stop scan*/ XSemIpiResp IpiResp = {0}; XStatus Status = XST_FAILURE; Status = XSem_CmdCfrStopScan(&IpiInst, &IpiResp); if ((XST_SUCCESS == Status) && \ (CMD_ACK_CFR_STOP_SCAN == IpiResp.RespMsg1) && \ (XST_SUCCESS == IpiResp.RespMsg2)) { xil_printf("[%s] Success: Stop\n\r", __func__); } else { xil_printf("[%s] Error: Stop Status 0x%x Ack 0x%x, Ret 0x%x", \ __func__, Status, IpiResp.RespMsg1, IpiResp.RespMsg2); goto END; }
- Inject ErrorNote: The error injection shall be done with valid CFRAME address and valid row.
- For valid range of addresses, refer to the LAST_FRAME_TOP (CFRAME_REG) and LAST_FRAME_BOT (CFRAME_REG) registers.
- For valid row, refer to the CFU_ROW_RANGE (CFU_APB) register.
To inject uncorrectable error, ensure to inject in alternate bit positions in the same qword. To inject CRC error, ensure to inject in alternate bit positions of the same qword in 3 or more than 3 positions. Refer to the xsem_cram_example.c file in the examples directory. For register information, see Versal ACAP Register Reference (AM012).
The safe location to perform error injection is QWORD 12 which has ECC bits. The error injection will not change the design behavior.
When an uncorrectable/CRC error or correctable error (correction is disabled in the configuration) is detected by XilSEM, the CRAM scan on PLM will be stopped and the user will be notified over IPI. In such case, ensure to reprogram/ restart to recover the error.
/* Inject 1-bit correctable error */ XSemIpiResp IpiResp = {0}; XStatus Status = XST_FAILURE; XSemCfrErrInjData ErrData = {0x7, 0x0, 0x0, 0x0}; Status = XSem_CmdCfrNjctErr(&IpiInst, &ErrData, &IpiResp); if ((XST_SUCCESS == Status) && \ (CMD_ACK_CFR_NJCT_ERR == IpiResp.RespMsg1) && \ (XST_SUCCESS == IpiResp.RespMsg2)) { xil_printf("[%s] Success: Inject\n\r", __func__); } else { xil_printf("[%s] Error: Inject Status 0x%x Ack 0x%x, Ret 0x%x",\ __func__, Status, IpiResp.RespMsg1, IpiResp.RespMsg2); goto END; }
- Start scan to detect/correct injected
error
/*To start scan*/ Status = XSem_CmdCfrStartScan(&IpiInst, &IpiResp); if ((XST_SUCCESS == Status) && \ (CMD_ACK_CFR_START_SCAN == IpiResp.RespMsg1) && \ (XST_SUCCESS == IpiResp.RespMsg2)) { xil_printf("[%s] Success: Start\n\r", __func__); } else { xil_printf("[%s] Error: Start Status 0x%x Ack 0x%x, Ret 0x%x", \ __func__, Status, IpiResp.RespMsg1, IpiResp.RespMsg2); goto END; }
Wait for the XilSEM library to detect and optionally correct the error (if configured to do so) and report the error. The following code illustrates how to validate if the error injection was successful.
/*To validate injection*/
while (XST_SUCCESS != XSem_ChkCfrStatus(0x1, 0x800U, 11U)) {
usleep(100);
}
xil_printf("Cram Status [0x%08x]\n\r", CfrStatusInfo.Status);
xil_printf("Cor Ecc Cnt [0x%08x]\n\r", CfrStatusInfo.ErrCorCnt);
xil_printf("Error address details are as\n\r");
for (Index = 0U ; Index < MAX_CRAMERR_REGISTER_CNT; Index++) {
xil_printf("\nErrAddrL%d [0x%08x]\n\r", \
Index, CfrStatusInfo.ErrAddrL[Index]);
xil_printf("ErrAddrH%d [0x%08x]\n\n\r", \
Index, CfrStatusInfo.ErrAddrH[Index]);
}
/*Function to check CFR status*/
static XStatus XSem_ChkCfrStatus(u32 ExpectedStatus, u32 Mask, u32 Shift)
{
XSemCfrStatus CfrStatusInfo = {0};
XStatus Status = XST_FAILURE;
u32 Temp = 0U;
Status = XSem_CmdCfrGetStatus(&CfrStatusInfo);
if (XST_SUCCESS == Status) {
Temp = DataMaskShift(CfrStatusInfo.Status, Mask, Shift);
if (Tesmp != ExpectedStatus) {
Status = XST_FAILURE;
}
}
return Status;
}