DDR ECC功能介绍
1、背景介绍:双倍数据速率同步动态随机存取内存(DDR SDRAM)技术由于其高密度,架构简单以及低延迟低功耗等优势,目前已经几乎成为所有应用场景下的主内存,特别是在汽车电子领域,对DDR的高效性,安全性则有着更近一步的要求,其在TDA4系列SoC中大致内存系统框图如图1所示。
在汽车处理器应用中,DDR承载着绝大多数应用的运行,但是DDR内存系统就像任何电子系统一样,不可避免的会受到系统软件或硬件设计上的缺陷,甚至纹波噪声等外界因素的影响,导致数据发生错误/偏移,进而导致系统出错甚至奔溃,这在要求高功能安全的汽车应用中是不可接受的。
为了检测并解决在运行时遇到的这些内存错误,内存子系统必须具有内存RAS(可靠性、可用性和诊断性)功能,从而能在内存发生错误时进行检测并修正。其中ECC作为RAS中较常用的一种方案,可以对DDR数据进行计算并得到汉明码,在下一次读取时再次进行实时计算并与汉明码进行对比,从而实现单比特纠错以及双比特检错(SEC DED)。
2、主要概念及作用:ECC作为IPU02功能安全的一个重要组成部分,承担着系统稳定工作的首要责任,ECC是系统稳定工作的第一道硬件检测防线。ECC主要负责存储出错检测与纠正,对于单bit错误产生后会对其进行纠正,并上报错误,对于2bit及其以上,ECC已经不能对错误进行纠正,直接上报错误给系统处理。
3、内部实现机制:在完成DDR和ECC的初始化以及使能之后,若系统没有重新复写过DDR内容,系统运行期间进行读操作时,会读取实时的DDR数据以及上一次计算得到的ECC data1数值,并基于此实时的DDR 数据进行计算得到ECC data2。若两次计算得到的data1和data2相同,则视为数据没有发生变化,不产生ECC错误;若两次计算得到的数据不同,则认为数据发生变化,产生ECC错误事件输出到TDA4VM88的ESM模块中,从而对ECC错误进行下一步的处理。如下图所示,为传统DDR ECC工作时读写操作流程。
DDR ECC功能配置
1、配置流程:在SBL启动阶段,
(1)DDR初始化,配置DDR大小,预留出预计DDR ECC区域大小1/9 的内存大小,作为DDR ECC计算结果 的存储空间,并使能DDR ECC保护区域cache功能。
(2)进行DDR ECC初始化:
-
ESM模块初始化,使能1bit&2bit错误引脚中断。
-
配置DDR ECC三段保护区域并使能DDR ECC功能。
-
使用copy方式对DDR ECC三段保护区域进行pattern填充,填充值为任意。
-
清除DDR ECC中断状态,使能DDR ECC中断,ECC硬件开始工作,ESM可以通过ECC接口获取ECC错误监控状态 。
2、保护区域配置:
(1)测试DDR ECC保护的区域总共为118MB,分为三段
-
Region1:0xA0100400-0xA0FFFFFF
-
Region2:0xA1100400-0xA57FFFFF
-
Region3:0xCC000000-0xCDFFFFFF
Name
Start Addr
End Addr
Size
DDR_MCU1_0
0xA0100400
0xA0FFFFFF
15 MB
DDR_MCU2_0
0xA1100400
0xA2FFFFFF
31 MB
DDR_MCU2_1_IPC
0xA3000000
0xA30FFFFF
1024 KB
DDR_MCU2_1_RESOURCE_TABLE
0xA3100000
0xA31003FF
1024 B
DDR_MCU2_1
0xA3100400
0xA4FFFFFF
31 MB
DDR_MCU3_0_IPC
0xA5000000
0xA50FFFFF
1024 KB
DDR_MCU3_0_RESOURCE_TABLE
0xA5100000
0xA51003FF
1024 B
DDR_MCU3_0
0xA5100400
0xA57FFFFF
7.00 MB
SHMIPC_VRING_MEM
0xCC000000
0xCDFFFFFF
32MB
Total
118 MB
(2)因为pattern填充需要耗费比较长的时间,为了缩短系统的启动时间,可以建设DDR ECC保护地址区域 ,DDR ECC保护的区域总共为54MB,分为三段
-
Region1:0xA0100400-0xA0FFFFFF
-
Region2:0xA5100400-0xA57FFFFF
-
Region3:0xCC000000-0xCDFFFFFF
Name | Start Addr | End Addr | Size |
DDR_MCU1_0 | 0xA0100400 | 0xA0FFFFFF | 15 MB |
DDR_MCU3_0 | 0xA5100400 | 0xA57FFFFF | 7.00 MB |
SHMIPC_VRING_MEM | 0xCC000000 | 0xCDFFFFFF | 32MB |
Total |
|
| 54 MB |
(3)DDR的起始地址是0x80000000,配置时,需要将保护的地址减去起始地址0x80000000
emifCfg.pMemEccCfg.startAddr[0] = 0xA0100400 - 0x80000000; emifCfg.pMemEccCfg.endAddr[0] = 0xA0FFFFFF - 0x80000000; emifCfg.pMemEccCfg.startAddr[1] = 0xA5100400 - 0x80000000; emifCfg.pMemEccCfg.endAddr[1] = 0xA57FFFFF - 0x80000000; emifCfg.pMemEccCfg.startAddr[2] = 0xCC000000 - 0x80000000; emifCfg.pMemEccCfg.endAddr[2] = 0xCDFFFFFF - 0x80000000;
重要提示:如果保护区域只有1段或2段,则未使用的段需要将start的地址配置成大于end地址,否则可能会导致一直报ECC错误。如:region2未使用,则startAddr[2] = 0xCC000000,endAddr[2] = 0x00。 startAddr[2]要大于endAddr[2]。
3、ECC code预留存储配置:IPU02平台DDR总共4GB,在DDR的尾端配置预留500MB内存大小,作为DDR ECC计算结果的存储空间,
(1)配置文件路径: /psdkra/psdkqa/qnx/bsp/src/hardware/startup/boards/j721e/evm/board_ddr_ecc.h
(2)配置内容:
#define IDK_DDR0_BASE 0x80000000ul //前面2GB DDR的起始地址
#define IDK_DDR0_SIZE MEG(2048) //2GB 大小
#define IDK_DDR1_BASE 0x880000000ul //后2GB DDR的起始地址
#define IDK_DDR1_SIZE MEG(1548) // 预留500MB用于存储ECC code
DDR ECC功能验证
1、开发人员DDR ECC功能验证,往固定的2个地址注入故障,并将验证结果通过DDR传输到MCU1_0:
(1)DDR ECC 1bit故障注入
-
清除ECC错误
-
读取测试地址的值(测试地址的值由测试人员定)
-
把测试地址的值翻转1bit
-
Disable DDR ECC功能
-
将测试地址进行转换,把翻转1bit的值写回转换后的地址(enable ECC和disable ECC的DDR地址值会发生改变,所以需要进行地址转换)
-
Enable DDR ECC功能
-
读取测试地址的值,触发1bit ECC错误
-
ESM检测到1bit错误,并校验出错地址是否为测试地址
-
恢复测试地址的值为初始值
(2)DDR ECC 2bit故障注入
-
清除ECC错误
-
读取测试地址的值(测试地址的值由测试人员定,可以和1bit测试的地址一样)
-
把测试地址的值翻转2bit
-
Disable DDR ECC功能
-
将测试地址进行转换,把翻转2bit的值写回转换后的地址(enable ECC和disable ECC的DDR地址值会发生改变,所以需要进行地址转换)
-
Enable DDR ECC功能
-
读取测试地址的值,触发2bit ECC错误
-
ESM检测到2bit错误,并校验出错地址是否为测试地址
-
恢复测试地址的值为初始值
(3)将测试结果写入到指定DDR地址
(4)MCU1_0读取指定DDR地址获取DDR ECC自检结果
-
都成功,0xDEADBEEF,
-
1bit成功,2bit失败,0xAA55BEEF
-
1bit失败,2bit成功,0xDEAD55AA
-
都失败:0xAA5555AA
经验教训
1.DDR ECC初始化和自检是在SBL阶段完成的,所以需要编译tiboot3.bin,关于tiboot3.bin编译的命令和注意点请参考SBL配置及编译说明文档。
2.在DDR初始化阶段,需要给DDR ECC保护的区域打开cache,否则2bit故障注入,在读触发ECC错误时会卡死,1bit故障注入测试能成功,具体原因TI也未知。
注意:有可能在前面将2GB cache都打开了,但后面又将部分地址cache关闭的情况。例如,上图Region 4区域将2GB cache打开,在Region 15区域将0xCC000000-0xCDFFFFFF的cache关闭,此时,在0xCC000000-0xCDFFFFFF这段地址注入2bit故障时,在读触发ECC错误时会卡死。
3.DDR ECC保护最多为三段。如果只需要保护1段,则其它不用的2段需要配置成startAddr大于endAddr,否则在MCU1_0起来后报一直报ECC错误。如:region2未使用,则startAddr[2] = 0xCC000000,endAddr[2] = 0x00。 startAddr[2]要大于endAddr[2]。
4.在enable ECC后,DDR的地址会发生改变,如下函数为enable ECC的地址转换为disable ECC对应的地址。