本文基于NXP的S32K1xx系列的芯片,来分析SRAM的ECC机制以及通过故障注入方式来验证以下两种类型故障。
1,单比特翻转错误
2,多比特不可纠正错误
话不多说,走你~
在了解SRAM之前,有必要先说明一下RAM。RAM主要的作用就是存储代码和数据供CPU在需要的时候调用。但是这些数据并不是像用袋子盛米那么简单,更像是图书馆中用书架摆放书籍一样,不但要放进去还要能够在需要的时候准确的调用出来,虽然都是书但是每本书是不同的。对于RAM等存储器来说也是一样的,虽然存储的都是代表0和1的代码,但是不同的组合就是不同的数据。
让我们重新回到书和书架上来,如果有一个书架上有10行和10列格子(每行和每列都有0-9的编号),有100本书要存放在里面,那么我们使用一个行的编号+一个列的编号就能确定某一本书的位置。在RAM存储器中也是利用了相似的原理。
现在让我们回到RAM存储器上,对于RAM存储器而言数据总线是用来传入数据或者传出数据的。因为存储器中的存储空间是如果前面提到的存放图书的书架一样通过一定的规则定义的,所以我们可以通过这个规则来把数据存放到存储器上相应的位置,而进行这种定位的工作就要依靠地址总线来实现了。
对于CPU来说,RAM就像是一条长长的有很多空格的细线,每个空格都有一个唯一的地址与之相对应。如果CPU想要从RAM中调用数据,它首先需要给地址总线发送“编号”,请求搜索图书(数据),然后等待若干个时钟周期之后,数据总线就会把数据传输给CPU。
小圆点代表RAM中的存储空间,每一个都有一个唯一的地址线同它相连。当地址解码器接收到地址总线的指令:“我要这本书”(地址数据)之后,它会根据这个数据定位CPU想要调用的数据所在位置,然后数据总线就会把其中的数据传送到CPU。
静态随机存取存储器(Static Random-Access Memory,SRAM)是随机存取存储器的一种。所谓的“静态”,是指这种存储器只要保持通电,里面储存的数据就可以恒常保持。相对之下,动态随机存取存储器(DRAM)里面所储存的数据就需要周期性地更新。然而,当电力供应停止时,SRAM储存的数据还是会消失(被称为volatile memory),这与在断电后还能储存资料的ROM或闪存是不同的。
S32K1xx系列的SRAM可参考下图
~
1) 动态随机存取存储器(DRAM)里面所储存的数据就需要周期性地更新。
2) SRAM不需要刷新电路即能保存它内部存储的数据。而DRAM(Dynamic Random Access Memory)每隔一段时间,
要刷新充电一次,否则内部的数据即会消失, 因此SRAM具有较高的性能,功耗较小。
3) 此外,SRAM主要用于二级高速缓存(Level2 Cache)。它利用晶体管来存储数据。与DRAM相比,SRAM的速度快,
但在相同面积中SRAM的容量要比其他类型的内存小。
4) 但是SRAM也有它的缺点,集成度较低,相同容量的DRAM内存可以设计为较小的体积,SRAM却需要很大的体积。
同样面积的硅片 可以做出更大容量的DRAM,因此SRAM显得更贵。
5) SRAM的速度快但昂贵,一般用小容量SRAM作为更高速CPU和较低速DRAM 之间的缓存。
总结以上:
SRAM成本比较高,DRAM成本较低(1个场效应管加一个电容)。
SRAM存取速度比较快,DRAM存取速度较慢(电容充放电时间)。
SRAM一般用在高速缓存中,DRAM一般用在内存条里。
S32K146 SRAM=内部RAM+FlexRAM (FlexRAM配置为Traditional RAM的部分),
内部RAM=SRAM_L + SRAM_U, Traditional RAM要比内部RAM要慢。
~
SRAM_L和SRAM_U的区别:SRAM_L - PC bus, SRAM_U - PS bus控制总线不一样。
如下图33.2.1,因此我们可以确定,SRAM_L是CPU用来访问代码的,SRAM_U是CPU用来访问数据的
~
LMEM(Local memory controller)负责地址和数据总线的解码,然后传输到ARM内核。LMEM可以看作是ARM内核和系统总线之间“传令官”。
cache是LMEM模块的子模块,它本质是一块高速内存,它存储了部分地址信息和相关数据,一般情况下cache是自我管理自动更新的,目的是减少内存的平均访问时间。
~
纠错码(ECC)通常与存储器一起用于不容易容忍因软错误导致数据损坏的应用中。软件错误可能由辐射(中子或阿尔法粒子)、电磁干扰、电噪声或电池之间的短路引起。S32K1xx系列中使用的ECC方法提供单错误纠正(SEC)和双错误检测(DED)功能。
相关模块名词:
EIM:Error Injection Module,错误注入模块
ERM: Error Reporting Module,错误报告模块
操作步骤:
1,通过EIM模块实现双bit翻转的故障注入
2,通过ERM模块检验是否成功注入故障,ECC机制是否完善
错误注入模块(EIM)用于诊断目的,以便在访问SRAM时引发读取数据的单位和多位反转。当EIM用于向内存注入故障时,对
SRAM的任何访问都会产生相应的注入错误(单位或双位错误)。EIM支持两个错误注入通道,分别对应于特定的RAM阵列。
下表显示了不同S32K1xx衍生产品的通道分配
实际上,我们通过EIM来注入故障实际上,就是将CheckBit总线上的bit进行翻转,或者ReadData总线上的bit进行翻转。
如下图,EIM通过寄存器的编写,来改变总线上的数据。
~
EIM有两个注入通道,每个错误注入通道:
• 指定一个掩码,用于定义来自目标RAM的读取数据总线( ReadData Bus )和校验位总线( CheckBit )在读取访问上反转。
• 在EIM编程模型中,包含一个128位(16字节)的结构,由4个32位的字组成。
• 第一个字,Word0 (EICHDn_WORD0),定义校验的位掩码,(翻转校验位总线数据bit的掩码)。
• 剩下的,Word1-3 (EICHDn_WORD1-3), 定义数据掩码,(翻转读取数据总线bit的掩码)。
注:简单点,实际中,我们只用到Word0 和 Word1即可。
请严格按照操作步骤来!!!
注:
步骤1)和步骤2)取一即可。
因为步骤1)注入故障之后,实际改变了ReadData总线上的数据,会产生复位结果。具体看文章末尾的总结。
步骤2)可以用ERM来检验错误标志位是否置1。
EICHD0_WORD1[B0_3DATA_MASK],EICHD1_WORD1[B0_3DATA_MASK]。
B0_3DATA_MASK中的位对应于ReadData总线的0-3字节。
每个位指定来自目标RAM的ReadData总线的对应位是应该反转还是在读访问时保持未修改。
例如:反转总线上Byte0的bit0~bit3四个位数据,那么该寄存器就写入0x000F。
~
EICHD0_WORD0[CHKBIT_MASK], EICHD1_WORD0[CHKBIT_MASK],
CHKBIT_MASK的每个位指定在读取访问时,CheckBit总线的对应位应该倒取还是保持未修改。成功写入此字段将清除相应的错误注入通道有效位EICHEN[EICHnEN]。
注:由此可见,实际我们注入位反转错误不是直接反转SRAM中的数据,而是反转总线上的数据。
~
EICHEN[EICH0EN], EICHEN[EICH1EN]。
注:通道是指:0代表SRAM_L,1代表SRAM_U.
EIMCR[GEIEN]
注:看第3)步中的寄存器位描述,(The Global Error Injection Enable(EIMCR[GEIEN]) field must also be asserted to enable error injection.)
SR0[SBC0]
当注入1bit反转故障到SRAM_L,期待SR0[SBC0] == 1;
当注入2bit反转故障到SRAM_L,期待SR0[NCE0] == 1;
当注入1bit反转故障到SRAM_U,期待SR0[SBC1] == 1;
当注入2bit反转故障到SRAM_U,期待SR0[NCE1] == 1;
~
①,EIM通过强制执行两阶段启用机制,可以防止错误注入功能的意外启用和重新配置。要正确地为通道启用错误注入机制:
• Write 1 to the EICHEN[EICHnEN] field, where n denotes the channel number.
• Write 1 to EIMCR[GEIEN].
②,当一个通道的用例需要写入任何EICHDn_WORD寄存器时,请在执行两阶段启用机制之前写入EICHDn_WORD寄存器。
成功写入任何EICHDn_WORD寄存器都会清除相应的EICHEN[EICHnEN]字段。
③,EIM支持2个错误注入通道。每个通道:
• 被分配给单个内存阵列接口。
• 拦截分配的内存读取数据总线和校验位总线,并通过反转每条总线线上为选定位传输的值来注入错误.
④,在内存读取上,适用的EICHDn_WORD寄存器定义要反转的读数据和/或校验位总线的哪个位。
⑤,尝试在一个操作中反转超过2位可能会导致未定义的行为。
具体实现 ↓ ↓ ↓
void FuncSafe_ECC_CheckProcess(void)
{
uint32 ERM_EAR0_Sts = 0u;
uint32 ERM_EAR1_Sts = 0u;
uint32 ERM_SR0_Sts = 0u;
/* EIM寄存器变量指向寄存器地址 */
1:FuncSafeVar.EIM_Reg = IP_EIM;
/* 2 bits( bit0 - bit1 ) of the checkbit bus is inverted. */
2:FuncSafeVar.EIM_Reg->EICHDn[0].WORD0 = EIM_EICHDn_WORD0_CHKBIT_MASK(0x3u);
3:FuncSafeVar.EIM_Reg->EICHDn[1].WORD0 = EIM_EICHDn_WORD0_CHKBIT_MASK(0x3u);
/* 2 bits( bit0 - bit1 ) of the Read data bus is inverted. */
4:// FuncSafeVar.EIM_Reg->EICHDn[0].WORD1 = EIM_EICHDn_WORD1_B0_3DATA_MASK(3u);
5:// FuncSafeVar.EIM_Reg->EICHDn[1].WORD1 = EIM_EICHDn_WORD1_B0_3DATA_MASK(3u);
/* Global Error Injection Enable */
6:FuncSafeVar.EIM_Reg->EIMCR = EIM_EIMCR_GEIEN(1u);
/* Error injection is enabled on Error Injection Channel 0 */
7:FuncSafeVar.EIM_Reg->EICHEN |= EIM_EICHEN_EICH0EN(1u);
/* Error injection is enabled on Error Injection Channel 1 */
8:FuncSafeVar.EIM_Reg->EICHEN |= EIM_EICHEN_EICH1EN(1u);
/* ERM寄存器变量指向寄存器地址 */
9:FuncSafeVar.ERM_Reg = IP_ERM;
10:ERM_SR0_Sts = ( FuncSafeVar.ERM_Reg->SR0 );
11:ERM_EAR0_Sts = ( FuncSafeVar.ERM_Reg->EARn[0].EAR );
12:ERM_EAR1_Sts = ( FuncSafeVar.ERM_Reg->EARn[1].EAR );
LRX_DEBUG(" ERM_SR0_Sts == %x\n",ERM_SR0_Sts);
LRX_DEBUG(" ERM_EAR0_Sts == %x\n",ERM_EAR0_Sts);
LRX_DEBUG(" ERM_EAR1_Sts == %x\n",ERM_EAR1_Sts);
}
1:将声明的EIM模块寄存器结构体变量指向寄存器地址(完成寄存器结构体的地址映射);
2:将 SRAM_L的CheckBit Bus上的数据bit0~bit1的2位数据进行翻转(0x3,是两位的掩码);
3:将 SRAM_U的CheckBit Bus上的数据bit0~bit1的2位数据进行翻转(0x3,是两位的掩码);
4:将 SRAM_L的Read Data Bus上的数据bit0~bit1的2位数据进行翻转(小心!经过测试验证,会发生LOCK UP的复位);
5:将 SRAM_U的Read Data Bus上的数据bit0~bit1的2位数据进行翻转(小心!经过测试验证,会发生产生看门狗复位);
6:打开全局错误注入使能;
7:打开SRAM_L通道错误注入使能;
8:打开SRAM_U通道错误注入使能;
9:将声明的ERM模块寄存器结构体变量指向寄存器地址(完成寄存器结构体的地址映射);
10:读取ERM模块的SR0寄存器,检验是否可以读取到多位不可纠正错误的状态标志位置1;
11:读取ERM模块的EAR[0]寄存器,检查SRAM_L发生比特翻转的地址(SRAM_L的地址区间:0x0000 0000 ~ 0x1FFF FFFF)
12:读取ERM模块的EAR[1]寄存器,检查SRAM_U发生比特翻转的地址(SRAM_U的地址区间:0x2000 0000 ~ 自己去查阅手册)
串口打印消息如下:
SR0寄存器的数据是0x4400 0000
(对应寄存器来看,的确代表SRAM_L和SRAM_U均发生了多位不可纠正错误SR0[NCE0] == 1;SR0[NCE1] == 1;)
经过上述测试验证,针对SRAM的ECC机制,不需要开启ERM模块的中断提醒,
因为我们在真正的ReadData Bus 上做比特翻转的故障注入时候,会发生Core LockUp 复位(SRAM_L)和看门狗复位(SRAM_U)
因此,故障注入只能来通过反转CheckBit Bus的数据来检查状态ECC机制是否完善。当实际MCU工作中,在ReadData Bus产生了比特反转,会触发相应的复位操作。
注:上面说的复位,是博主实际对ReadData Bus 上做比特翻转操作之后的结论。即:步骤1)定义反转的读取总线上的Bit(Word1)。