Zynq Ultrascale+如何在OCM中插入测试ECC error

作者:Davis Zhang,AMD工程师,来源:AMD Xilinx开发者社区

在一些系统安全性要求较高的设计里,通常会加入系统自检功能。通常会在系统启动时进行一次系统自检,然后系统工作过程中实时监测。Zynq Ultrascale+器件里的on-chip memory(OCM)支持ECC,并支持单比特错误修正,多比特错误检测,并且提供人工插入ECC测试error的功能。相关的OCM register如下:

1. OCM_ERR_CTRL(0x00FF960000),当检测到多比特错误(uncorrectable error)时,bit[3]用来控制OCM是否在axi4总线上返回slave error.
2. OCM_ISR(0x00FF960004),bit[6]和bit[7]分别是发生单比特error和多比特error的中断标志位。
3. OCM_IEN(0x00FF96000C),bit[6]和bit[7]分别用来enable单比特error和多比特error的中断。
4. OCM_IDS(0x00FF960010),bit[6]和bit[7]分别用来disable单比特error和多比特error的中断。
5. OCM_IMR(0x00FF960008),bit[6]和bit[7]分别是单比特error和多比特error的mask状态。
6. OCM_ECC_CTRL(0x00FF960014),bit[0]—disable/enable ECC,bit[1]—设置是否修复单比特error,bit[2]—设置对单次写操作插入ECC error还是对每次写操作都插入ECC error。
7. OCM_FI_D0~3(0x00FF96004C~0x00FF960058),用来设置当写入数据的时候,128-bit data word的哪些位反转插入错误数据位。
8. OCM_FI_SY(0x00FF96005C),用来设置当写入数据时,哪些ECC Syndrome位反转插入ECC error。
9. OCM_FI_CNTR(0x00FF960074),用来设置内部counter起始值,写入后开始计数,当减少到零的时候,可以通过写入数据到OCM来插入ECC error。

做ECC error插入之前,为了确认写入的数据进去OCM,通常会disable data cache。

当插入单比特ECC error的时候,需要先在OCM_FI_D0~3寄存器中的某一位置一,然后设置OCM_FI_CNTR内部counter起始值并开始计数,等待一些时间让counter计数变为0,注意这个阶段不能通过读OCM_FI_CNTR寄存器判断counter是否已经计数完毕,随后写入某个OCM地址一个数值,然后读取这个地址就可以产生单比特错误。程序大概流程为:

/*single bit error injection*/
Xil_Out32(0xFF96004C, 0x100);
Xil_Out32(0xFF960074, 4);
usleep(1000);
Xil_Out32(0xFFFC0000, 0xFFFFFFFF);
usleep(1000);
ocm_read = Xil_In32(0xFFFC0000);
while(ocm_isr != 0x40) {
ocm_isr = Xil_In32(0xFF960004);
}
xil_printf("single bit error injection\n\r");

当插入双比特错误的时候,需要先将寄存器OCM_ERR_CTRL的bit[3]设为0,这是因为双比特error是uncorrectable error,会在axi总线上返回slave error,这会导致standalone application进入data abort exception,导致程序停止,OCM_ERR_CTRL的bit[3]设置为0客户让OCM出现uncorrectable error的时候不在总线上返回slave error,有利于我们后续检查error状态。之后在OCM_FI_D0~3寄存器中的某两位置一,然后设置OCM_FI_CNTR内部counter起始值并等待计数完毕,随后写入某个OCM地址一个数值,然后读取这个地址就可以产生双比特错误。程序大概流程为,

/*disable bus slverr for dual bit error*/
Xil_Out32(0xFF960000, 7);

/*dual bit error injection*/
Xil_Out32(0xFF96004C, 0x300);
Xil_Out32(0xFF960074, 4);
usleep(1000);
Xil_Out32(0xFFFC0000, 0xFFFFFFFF);
usleep(1000);
ocm_read = Xil_In32(0xFFFC0000);
while(ocm_isr != 0x80) {
ocm_isr = Xil_In32(0xFF960004);
}
xil_printf("dual bit error injection\n\r");

最新文章

最新文章