前言
在使用环境比较严苛的工业化产品,航空航天等产品中,RAM的内容可能由于环境的因素导致小概率的随机bit翻转,比如宇宙高能粒子的撞击等。所以在这些场景一般都要求芯片自带ECC功能,能进行RAM的错误检测和校正,以此来提高系统的可靠性。尤其是航空航天产品这可以说是一个必备的功能。
SAM-D5x这个MCU带RAMECC功能,支持一个bit纠错,2个bit检错,一般来说这是一个标配,如果要支持更多位的纠错和检错,需要更多的额外存储和运算负荷,而一般出现多位错误的概率很低,所以均衡考虑一般都是支持1个bit纠错,2个bit的检错。
我们就针对该功能进行分析和测试。
ECC的原理可以网上搜索,这里介绍一个基本的公式,就是要满足检测n个bit的原始数据,需要增加m个bit的校验数据(这里只考虑一个bit的错误)?已知n,m至少是多少?
n个原始数据,加上m个校验数据,实际有n+m位数据了(因为校验数据本身也会出错,也需要检测错误),那么就有n+m种只错1位的情况,还有一种正确的状态,那么有n+m+1种状态,要表示这么多状态,用m位表示,就必须满足
2^m ≥ m + n + 1
比如8位原始数据,需要m至少为4,2^4=16>=8+4+1=13。
上述是检测1个bit的错误的情况,只有行校验,如果要检测两个bit的错误,还要增加1bit,增加一个列校验,所以是8位数据需要5个校验位,这是我们常见的配置。
所以我们看到RAMECC模块,框图
32位数据以字节为单位,分成4组,需要额外增加4x5位的校验信息
ECC工作逻辑是,写入时同时计算,同时更新原始值和ECC值,读时读出原始值计算ECC与存储的ECC对比,如果是一个bit错误则返回纠正后的值给CPU。这里需要注意一点,一个bit的纠错是指的,读时将纠正正确值返回给CPU,而不是指的自动纠正RAM中的值,所以需要在ECC中断中软件根据错误地址,自动将正确值回写到RAM中完成纠正。
而只有读到有错误校验值的地址,才会触发中断,如果不去读这个地址,哪怕有ECC错误也不会触发。所以这就需要软件定时去全盘读RAM来触发ECC检测,这个定时时间不饿能太短,太短增加软件处理负担,不能太长,太长可能单个错误累计到多个错误而无法恢复,这就需要平衡。并且读RAM还要考虑和正常程序执行的互斥,一般需要在临界段中进行读处理,而扫描读整个RAM的时间就不能忽视了。在检测到单bit错误,进行软件纠正恢复时也要考虑近阶段处理,避免更高优先级中断中再继续访问该错误值。
RAMECC介绍
参见手册的章节
《17. RAMECC – RAM Error Correction Code (ECC)》
结构
8位数据对应5位校验信息,支持纠错1位,检错2位,ECCDIS控制是否使能,使能后有效存储减半
时钟
时钟来自于AHB-APB B
MCLK.APBBMASK.RAMECC控制使能,默认复位就是使能的。
MCLK_REGS->MCLK_APBBMASK |= 1<<16;
寄存器写保护
上一篇有讲,这里不再重复
PAC_REGS->PAC_WRCTRL = (1<<16) | (32*1+16);
中断
ARM\PACK\Microchip\SAMD51_DFP\3.6.120\samd51a\include\samd51p20a.h
中查看中断号
RAMECC_IRQn = 45, /* 45 RAM ECC (RAMECC) */
\RTE\Device\ATSAMD51P20A\startup_samd51p20a.s中
中断服务函数
DCD RAMECC_Handler ; 45 RAM ECC Handler
标志清除
INTFLAG.SINGLEE and INTFLAG.DUALE bits are both cleared on ERRADDR read.
寄存器
INTENCLR:控制清除单错和双错中断使能
INTENSET:控制设置单错和双错中断使能
INTFLAG:中断标志,读ECCADDR清标志
STATUS:ECC使能状态,只读,NVM User Row配置,启动时加载到该位
ERRADDR:错误地址
DBGCTRL:调试时的行为配置,控制仿真读时是否记录ECC错误。
使能
UROW的bit39控制是否禁用RAM ECCDIS,默认值是1,禁用的。
需要修改RAM ECCDIS为0.
RAMECC测试
测试RAM ECC需要触发ECC错误,一般有以下几种方式
- 芯片自带的错误注入功能,我们这个芯片没有
- 不初始化RAM,这样RAM 的内容会随机或者全0,ECC就会不对。
- 使用激光等物理方法,模拟高能粒子撞击,模拟产生bit翻转导致的ECC错误。
我们条件只能使用方法2测试。
我们按照2进行测试
先要在程序启动后,访问RAM之前,进行RAM的初始化,也就是进行以此写,保证ECC的初始值正确。
这里我们故意最后4字节不初始化,在主程序中去读RAM,看是否读到这个未初始化的地方产生ECC错误。
ECC初始化代码
void ramecc_init(void)
{
MCLK_REGS->MCLK_APBBMASK |= 1<<16;
PAC_REGS->PAC_WRCTRL = (1<<16) | (32*1+16);
RAMECC_REGS->RAMECC_INTENSET = (1u<<0) | (1u<<1);
NVIC_SetPriority(RAMECC_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL);
NVIC_EnableIRQ(RAMECC_IRQn);
}
void RAMECC_Handler ( void )
{
volatile uint32_t erraddr;
erraddr = RAMECC_REGS->RAMECC_ERRADDR;
erraddr = erraddr;
}
RAM初始化代码如下
#define RAM_BASE 0x20000000
#define RAM_SIZE (128*1024ul)
void ram_init(void);
void ram_init(void)
{
uint32_t i;
for(i=0;i<RAM_SIZE-4;i++)
{
*(volatile uint8_t*)(RAM_BASE+i)=0x55;
}
}
在启动汇编代码中调用
IMPORT SystemInit
IMPORT __main
IMPORT ram_init
LDR R0, =ram_init
BLX R0
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
然后main函数中读RAM
void ram_read(void);
void ram_read(void)
{
volatile uint32_t i;
for(i=0;i<RAM_SIZE;i++)
{
if(*(volatile uint8_t*)(RAM_BASE+i) != 0x55)
{
}
}
}
int main(void)
{
NVIC_SetPriorityGrouping(0);
//PAC_REGS->PAC_WRCTRL = (1<<16) | (32*1+4);
PORT_REGS->GROUP[2].PORT_DIRSET = 1<<18; //PC18 OUTPUT
ramecc_init();
while(1)
{
ram_read();
}
return 0;
}
下载程序仿真运行进入了中断如下
可以看到ERRADDR的值正好是0x0001FFC,并且dual错误置位了
注意这里的错误地址是相对RAM开始地址的偏移
继续执行读ERRADDR状态清除
以上的测试主要要是断电后重新测试,模拟初始化ram的值为上电复位值。
如果我们将ram_init初始化范围改为全部128KB都初始化就不会触发ECC错误,这就验证了RAMECC的正确性。
RAMECC错误中断的处理需要注意的事项很多
分为单bit错误这种是可以纠正的,将读出来的正确值回写进去就可以了,单位错误读出来的是纠正后的值,但是需要软件手动写入才会纠正RAM中的值。这里需要注意中断中不能有高优先级中断抢占再去操作该地方的值了。
而多位错误此时软件没法恢复了,只能根据实际的策略进行处理,或者进行软件复位等相应的策略,这个就根据实际情况定了,有时安全相关的系统并不能直接软件复位,可能需要进行一些恢复或者切机策略等等处理,这个就不在此讨论了。
一个简单的中断处理如下
当然这可嫩还有很多情况没有考虑到,比如更高优先级中断的屏蔽等,只是作为演示,纠正恢复策略等也要根据实际多方考虑而定。
void RAMECC_Handler ( void )
{
volatile uint32_t erraddr;
erraddr = RAMECC_REGS->RAMECC_ERRADDR;
if(RAMECC_REGS->RAMECC_INTFLAG & 0x02)
{
//dual err reset or other
}
else if(RAMECC_REGS->RAMECC_INTFLAG & 0x01)
{
//single err
*(volatile uint8_t*)erraddr = *(volatile uint8_t*)erraddr;
}
}
总结
本文介绍了RAMECC原理,进行了RAMECC的测试,本芯片支持RAMECC单bit错误纠正,2位错误检测,能大大提高芯片的可靠性,这也是安全相关应用场景的一个标配。在商业航天降本等打趋势下,也在大量使用工业级的芯片。具备RAMECC的芯片,无疑是选型的一个基本要素,所以本芯片是具备在商业航天领域使用的基本要素的。