您好、再说一次、
如果有任何想法、问题所在、代码会跳转到无法屏蔽的数据中止。
如果在 L2L3测试之后执行 SRAM ECC 测试、这种情况在运行时和引导时间内发生。 出于某种原因、如果 L2L3测试仅在启动期间运行、则运行时 SRAM 测试在启动后正常工作。
制作了简单的启动测试案例、成功地重现了问题(在该代码之前、我已在启动例程的建议部分成功执行了 SRAM 测试)。
{
//只有这些测试可以在特权模式下运行
const sl_SelfTestType aeIconTesting[]=
{
L3INTERCONNECT_RESERVE_ACCESS、
L2INTERCONNECT_RESERVE_ACCESS
};
for (u32i = 0U;u32i <元素(aeIconTests);u32i++)
{
RetVal = sl_SelfTestL2L3Interconnect (aeIconTests[ u32I ]、NULL、0U);// REST 数据用于非私有边缘测试
Increment_pass fail_counter (ST_Pass、RetVal、failure_proceed);
}
}
{
SL_SelfTest_Result failInfoTCMRAM; /* TCM RAM 故障 信息*/
RetVal = sl_SelfTest_SRAM (SRAM_ECC_ERROR_ENCED_2BIT、TRUE、failInfoTCMRAM);
Increment_pass fail_counter (failInfoTCMRAM、RetVal、failure_proceed);
sl_vimREG->INTREQ0 = 1U;//清除 CH:esmHIGH (始终为 FIQ),test 将启用它
}
运行时和启动期间的结果相同:
==data_abort==
DFSR:0x409
DFAR:0x8008170
状态:0x19
读:正确
AxiDec:对
===========================
其中0x8008170属于 SafeTI 测试缓冲器
slamEccTestBuff 0x08008160 0x20 数据 GB sl_selftest.o [1]
在数据中止处理程序中、我从示例工程中复制了 SRAM 测试的错误处理+添加了每次识别测试时增加的变量
if (sl_FLAG_GET ((Int32) SRAM_ECC_ERROR_ENCERAING_2BIT)))
{
u32Ecc2bit++;
uint32 u32EccWrEnMask =(uint32) TCRAM_RAMCTRL_ECCWREN; /*lint !e9033 !e9053 *// TODO:为什么 lint
uint32 u32Eec1WrEn = sl_tcram1REG->RAMCTRL & u32EccWrEnMask;
uint32 u32Eec2WrEn = sl_tcram2REG->RAMCTRL & u32EccWrEnMask;
if ((u32Eec1WrEn =u32EccWrEnMask)||(u32Eec2WrEn ==u32EccWrEnMask))
{ /*看起来写入 ECC 区域已启用、请检查错误地址是否在测试缓冲区范围内*/
maskDAbort = true;// TODO:是否应检查地址、而不仅仅是基于 sl_FLAG_GET...的屏蔽错误
}
}
u32Ecc2bit 的值为3、该中止在每次测试中被调用两次、这意味着第2次测试成功处理了第一个数据中止、但在测试过程中会发生某些情况。
根据调试器,在执行该_sl_Barrier 数据访问()行时调用数据中止
/*为自检设置自检标志,以指示 ESM 处理程序将此操作作为自检的一部分来完成*/
/*从具有2位 ECC 错误的位置读取数据这将导致生成数据中止*/
/*SAFETYMCUSW 446 S MR:10.1. 注释_11*/
ramread64 = sramEccTestBuff[2];
_SL_Barche_Data_Access (); //此处出现意外的数据中止
/*恢复 Ctrl 寄存器*/
sl_tcram1REG->RAMCTRL &=~TCRAM_RAMCTRL_ECCWREN;
/*SAFETYMCUSW 134 S MR:12.2 备注_5*/
ramRead = sl_tcram2REG->RAMCTRL;
/*为自检设置自检标志,以指示 ESM 处理程序将此操作作为自检的一部分来完成*/
/*SAFETYMCUSW 446 S MR:10.1. 注释_11*/
ramread64 = sramEccTestBuff[3];
_sl_Barrier 数据访问();
/*恢复 Ctrl 寄存器*/
sl_tcram2REG->RAMCTRL &=~TCRAM_RAMCTRL_ECCWREN;
由于 SRAM_ECC_ERROR_ENCED_2BIT 在运行时单独工作、因此它指示测试本身正常。 由于它在启动后的运行时间为1次、但在 L2L3测试后的启动时间不能直接运行、因此它指示从启动到运行时间的转换中的某个位置将发生变化、从而允许它通过一次。
如果我正确理解下一个预期数据中止应该来自这里 ramread64 = sramEccTestBuff[3]; 因此、出现了问题。 让我们进一步检查:
我创建了这种调试陷阱、并将中断点设置为 IF
u32Ecc2bit++;
if (u32Ecc2bit == 3)
{
temptemp++;
}
一切看起来都很好、但代码也会在相同的循环中传递该值(我有一个逻辑、在本例中设置 maskDAbort = false;)
/*由于 SRAM ECC 2Bit 自检而导致 DAbort? *
if (sl_FLAG_GET ((Int32) SRAM_ECC_2BIT_FAULT_Inject))
{
}
因此、很显然、问题是测试活动数组会受到一些损坏。
在启动运行后、这个 L3INTERCONNECT_RESERVE_ACCESS 运行
sl_priv_flag_set[0]看起来具有值4 (这意味着 SRAM_ECC_ERROR_PAGED_1BIT 处于活动状态、但 sl_FLAG_SET 使用值0和1)
执行 L2INTERCONNECT_RESERVED_ACCESS 后 、sl_priv_flag_set[3]为136 (且[0]现在为零)、这意味着 SRAM_ECC_2BIT_FAULT_Inject 处于活动状态。
这完全解释了该数据中止处理程序挂起的原因、只是想知道这些 L2和 L3会破坏什么...
为什么该测试阵列损坏、L2和 L3测试的作用是什么? 这些破坏性测试是否与 PBIST 相同、何时应执行这些测试? 我几乎在启动结束时执行它们、如果 更多的 RAM 被破坏、而不仅仅是那些测试活动插槽、这种情况就不再安全了...
这也解释了为什么 SRAM 测试在启动后开始工作->在跳转到 main()之前重新初始化变量并删除损坏的 SRAM_ECC_2BIT_FAULT_INIT……
所有想法都很受欢迎、我是否在数据中止处理程序中做了一些错误?
如果是 L3测试、SL_priv_flag_set[0]将在 IF 启动之前转到 STR 命令中的值4、此时已返回数据中止
0xa6a6:0x0020 MOV R0、R4
0xa6a8:0xf001 0xfb24 BL sl_FLAG_set ;bcf4
_sl_Barrier 数据访问();
0xa6ac:0xf001 0xe826 BLX _SL_Barrier 数据访问;bb6fc
G_L2L3_READ_RESERTED_WORD =*((UINT32*) PCR_RESERVE_LOCATION);
0xa6b0:0xf05f 0x407d MOVs.W R0、#-50331648 ;0xfd000000
0xa6b4:0x6800 LDR R0、[R0]
0xa6b6:0xf8df 0x1d38 LDR.W R1、[PC、#0xd38] ;[b3f0] g_L2L3_read_reserved_word //跳转到数据中止
0xa6ba:0x6008 STR R0、[R1] //在这里看起来是损坏的
if ((0x00000008u =(UINT32)(0x00000008u &_SL_GET_DataFault_Status ())))&&
(((uint32) pcr_reserved_location =_sl_get_DataFault_Address ())){
0xa6bc:0xf000 0xef60 BLX _SL_GET_DataFault_Status;b5580
0xa6c0:0x0700 LSLS R0、R0、#28
0xa6c2:0xd505 BPL.N 0xa6d0
0xa6c4:0xf000 0xef60 BLX _SL_GET_DataFault_Address;0xb588
L2测试会在完全相同的点破坏数据
_sl_Barrier 数据访问();
0xa6e6:0xf001 0xe80a BLX _SL_Barrier 数据访问;bb6fc
G_L2L3_READ_RESERTED_WORD =*((uint32*) SCR_RESERVE_LOCATION);
0xa6ea:0xf05f 0x4008 MOVs.W R0、#-2013265920 ;0x88000000
0xa6ee:0x6800 LDR R0、[R0]
0xa6f0:0xf8df 0x1cfc LDR.W R1、[PC、#0xcfc] ;[b3f0] g_L2L3_read_reserved_word //跳转到数据中止
0xa6f4:0x6008 STR R0、[R1]//在这里看起来是损坏的
_sl_Barche_Data_Access();/*已添加以避免链接器对齐问题*/
0xa6f6:0xf001 0xe802 BLX _SL_Barrier 数据访问;bb6fc
if ((0x00000008u =(UINT32)(0x00000008u &_SL_GET_DataFault_Status ())))&&
(((uint32) scr_reserved_location =_sl_get_DataFault_Address ())){
0xa6fa:0xf000 0xef42 BLX _SL_GET_DataFault_Status;b5580
0xa6fe:0x0700 LSLS R0、R0、#28
0xa700:0xd505 BPL.N 0xa70e
0xa702:0xf000 0xef42 BLX _SL_GET_DataFault_Address;b0x588
在 L2测试中、R0 = 0x88000000、R1 = 0x0800A840
sl_priv_flag_set 的地址为0x0800A840
sl_priv_flag_set 0x0800a840 0x40 数据 GB sl_priv.o [1]
因此、这很可能不会破坏任何其他东西...
sl_priv_flag_set[3]的地址为0x0800A843、因此此 STR 命令会对测试数组的开头进行32位写入、并损坏它...
您能不能猜到花了3分钟才知道发生了什么...