1. i.MX 8M Plus 在线 ECC 功能

 

i.MX 8M Plus DDR 控制器支持在线 ECC,可保护系统免受软错误(例如由 α 射线、中子等引起的 DRAM 位翻转)的影响。它为每 64 位数据存储 8 位 ECC(纠错码),从而能够纠正单比特错误并检测双比特错误。

由于没有专门用于存储 ECC 的内存,因此大约 1/8 的 DDR 容量被用作 ECC 区域。

由于 32 位数据总线在数据和 ECC 之间共享,启用内联 ECC 功能会降低 DDR 访问性能。

 

1.1.单比特纠错 (SEC)

SEC 是 DDR 控制器的一项功能,用于检测单比特错误并将其纠正为正确的值。 Keita_Nagashima_4-1765435456176.png

图1 SEC示意图

 

1.2.双比特错误检测 (DED)

DED 是 DDR 控制器的一项功能,用于检测双比特错误。 Keita_Nagashima_5-1765435507241.png

图2 DED概念图

笔记:

实际上,SEC 和 DED 是在 64 字节对齐的数据区(加上 8 字节的 ECC)中检测的,而不是在 8 字节中检测的。

 

2.内联 ECC 内存映射(概要)

 

根据 DDR 容量的不同,设置内联 ECC 内存映射的方法也会有所不同。

 

2.1.DDR密度是2的幂(二进制对齐密度)

例如,对于 1、2、4、8、16GB 的情况,

  1. DDR的低地址7/8用作数据区,高地址1/8用作ECC区。ECC区通常不可访问。

  2. 数据区域最多分为八个区域:区域 0 至 6 和其他区域。每个区域都可以启用或禁用 ECC 功能。

  3. 区域 0 至 6 的容量相同,分别设置为 DDR 容量的 1/8、1/16、1/32 或 1/64。其余区域均为其他区域。

以下是当区域 0 到 6 的容量设置为 1/8 时的内存映射。在这种情况下,没有其他区域。

Keita_Nagashima_2-1765437269920.png

图 3内存映射示例 (1/8)


下面显示的是当区域 0 到 6 的容量设置为 1/16 时的内存映射。

Keita_Nagashima_3-1765437330955.png
图 4内存映射示例 (1/16)

2.2.非 2 的幂次方的 DDR 密度(非二进制对齐密度)

例如,对于 3、6 或 12 GB 的情况(i.MX 8M Plus LPDDR4 EVK 为 6 GB,因此这适用于这种情况)。

  1. 将整个 DDR 分成三份,每份的容量是 2 的幂。

    • 3GB内存,1GB x 3

    • 6GB内存,2GB x 3

    • 12GB版本,4GB x 3

  2. 对于分为三部分的低地址区域,进行如下设置:2.1. 当 DDR 容量为 2 的幂时。

  3. 三段式地址划分中,上两个地址区域的设置与下地址区域的设置相同。

下面显示的是设置为 1/8 时的内存映射。

Keita_Nagashima_4-1765437541555.png

图 5 DDR 容量不是 2 的幂(1/8)时的内存映射示例


3.使用 DDR 寄存器编程辅助工具进行设置

 

使用DDR 寄存器编程辅助工具(DDR RPA) 配置内联 ECC。

笔记:

请准备一个 DDR RPA,该 RPA 可以运行禁用内联 ECC 的 DDR 压力测试(并且还可以验证其是否可以运行 u-boot)。

由于存在漏洞,i.MX8MP LPDDR4/DDR4 RPA v6 或更早版本无法正常工作内联 ECC。请使用 v7 或更高版本。除非有特殊情况,否则请使用最新版本的 DDR RPA。(截至 2024 年 9 月,最新版本为 v9。)

Linux BSP 的 U-Boot 中包含的 i.MX 8M Plus EVK 的lpddr4_timing.c 文件。以及ddr4_timing.c虽然乍一看似乎可以正常工作,因为它包含了定义CONFIG_IMX8M_DRAM_INLINE_ECC ,但内联 ECC 设置存在问题,无法正常工作。即使您使用的是 EVK 进行测试,也请使用 DDR RPA 和 DDR Tool 生成 lpddr4_timing.c/ddr4_timing.c 文件。


3.1.启用在线 ECC

在 DDR RPA 寄存器配置表中,将内联 ECC 项设置为启用。

 
Keita_Nagashima_1-1765438351335.png

3.2.内存映射

 

3.2.1.DDR密度是2的幂(二进制对齐密度)

如果 DDR 容量是 2 的幂,请使用 ECC_Config_BinaryAligned 表。

  • 指定区域 0 至 6 的容量。(1/8、1/16、1/32 或 1/64)

  • 启用或禁用 0 至 6 区及其他区域的 ECC(受保护或未受保护)。

这是区域 0 到 6 的容量设置为 1/8 时的示例。

Keita_Nagashima_2-1765438431895.png

图 6 DDR RPA 设置 (1/8)


这是一个将 0 到 6 区的容量设置为 1/16 的示例。

Keita_Nagashima_3-1765438479461.png

图 7 DDR RPA 设置 (1/16)


3.2.2.非 2 的幂次方的 DDR 密度(非二进制对齐密度)

如果 DDR 容量不是 2 的幂,请使用 ECC_Config_nonBinaryAligned 表(i.MX 8M Plus LPDDR4 EVK 就是这种情况,容量为 6GB)。

  • 指定区域 0 至 6 的容量。(1/8、1/16、1/32 或 1/64)

  • ECC 启用或禁用内存区域 0 中的区域 0 到 6 以及其他区域(受保护或未受保护)的 ECC。

ECC 内存区域 1/2 将自动设置为与 ECC 内存区域 0 相同的设置。

这是区域 0 到 6 的容量设置为 1/8 时的示例。

Keita_Nagashima_6-1765438674787.png
Keita_Nagashima_5-1765438582315.png
Keita_Nagashima_7-1765438743893.png

图 8 DDR RPA 设置 (1/8)


这是一个将 0 到 6 区的容量设置为 1/32 的示例。

Keita_Nagashima_8-1765438820847.pngKeita_Nagashima_9-1765438875946.pngKeita_Nagashima_10-1765438920329.png

图 9 DDR RPA 设置 (1/32)


4.使用 DDR 工具进行测试并生成 lpddr4_timing.c/ddr4_timing.c 文件

 

您可以使用 DDR 工具来检查 DDR RPA 中所做的设置的运行情况。

如果 DDR 压力测试通过,则生成 lpddr4_timing.c/ddr4_timing.c 以合并到 U-Boot 中。

 

5. U-Boot 中的内联 ECC 实现

 

5.1.替换 lpddr4_timing.c/ddr4_timing.c

lpddr4_timing.c 或者将ddr4_timing.c替换为 DDR RPA 和 DDR Tool 生成的文件。

 

5.2.添加配置

将CONFIG_IMX8M_DRAM_INLINE_ECC=y添加到您的 U-Boot 配置文件中。

将清单 1添加到 uboot-imx/configs/imx8mp_evk_defconfig
CONFIG_IMX8M_DRAM_INLINE_ECC=y

笔记:

U-Boot 配置文件imx8mp_evk_inline_ecc_defconfig是在 Linux BSP 5.4 中添加的,但由于维护不当,已被弃用。使用 EVK 进行测试时,更安全的做法是将配置添加到imx8mp_evk_defconfig中并使用它。

5.3.更改Linux保留区域¶

软件禁止访问 ECC 区域。因此,设备树会动态修改,以便 Linux 内核(以及其他系统软件)将 ECC 区域视为保留区域。默认值硬编码为与 EVK 的 DDR 容量相匹配(LPDDR4 为 6GB,DDR4 为 4GB),因此如果 DDR 容量与 EVK 的容量不同,则必须修改代码。

使用uboot-imx/board/freescale/imx8mp_evk/imx8mp_evk.c中的函数ft_board_setup来更改 ECC 区域,使其与实际 DDR 容量相匹配。例如,对于 DDR4,ECC 区域的起始地址和大小是硬编码的,假定 DDR 容量为 4GB。

列表 2: DDR4 容量硬编码为 4GB
phys_addr_t ecc_start = 0x120000000;
size_t ecc_size = 0x20000000;

如果实际 DDR 容量为 2GB,则从物理地址 0x40000000 到 0xc0000000 的 1/8 (256MB) 高地址保留为 ECC 区域。

示例 3 :将 DDR 内存容量更改为 2GB
phys_addr_t ecc_start = 0xb0000000;
size_t ecc_size = 0x10000000;

imx8mp_evk.c 如果您不使用它,则需要添加与ft_board_setup函数等效的处理。

 

5.4.搬迁支持

如果 DDR 容量为 2GB 或更小,且未安装 OPTEE,U-Boot 会尝试重定位到 DDR 的最高地址,但由于该地址与 ECC 区域重叠,因此会在重定位过程中卡住。为避免这种情况,请添加 imx8mp_evk.h 文件。将 ECC 区域容量从 DDR 容量定义PHYS_SDRAM_SIZE中减少 (1/8)。

清单 4 uboot-imx/include/configs/imx8mp_evk.h
-#define PHYS_SDRAM_SIZE         0x80000000
+#define PHYS_SDRAM_SIZE         0x70000000

 

5.5.排除对 ECC 区域的访问处理

如果 U-Boot 中还有其他代码访问了 ECC 区域,则需要排除对 ECC 区域的访问。例如,如果内存测试访问了整个 DDR 区域,则需要修改该测试,使其不再访问 ECC 区域。

参考: https ://github.com/nxp-imx/uboot-imx/blob/lf-6.1.55-2.2.0/configs/imx8mp_evk_defconfig#L10-L11

 

6. Linux 系统运行检查

 

6.1.查看启动日志

确保在 Linux 启动时已安装 EDAC 驱动程序。(EDAC = 错误检测和纠正)i.MX 8M Plus 的 EDAC 驱动程序位于linux-imx/drivers/edac/synopsys_edac.c 。

清单 5检查启动日志
root@imx8mp-lpddr4-evk:~# dmesg | grep EDAC
[    0.116733] EDAC MC: Ver: 3.0.0
[    1.874689] EDAC MC0: Giving out device to module 1 controller synps_ddr_controller: DEV synps_edac (INTERRUPT)

 

6.2.检查内存映射

使用命令cat /proc/iomem确认 ECC 区域已按照5.3 节“更改 Linux 保留区域”中的配置设置为保留。以下是 i.MX 8M Plus LPDDR4 EVK(DDR 容量 6GB)的示例。

列表 6检查内存映射
root@imx8mp-lpddr4-evk:~# cat /proc/iomem | grep reserved
...
b0000000-bfffffff : reserved
...
130000000-13fffffff : reserved
...
1b0000000-1bfffffff : reserved

 

6.3.检查何时发生 ECC 错误

根据应用说明AN13566 - i.MX 8 系列上的 ECC ,i.MX 8M Plus 中的 DDR 控制器没有故意生成 ECC 错误的功能。

3.2.9通过软件注入ECC错误

ECC 错误注入是系统级软件验证的一个有用的可选功能。与边带 ECC 不同,它没有专门的硬件支持。但是,可以通过软件注入错误,方法是通过“ECC_REGION_PARITY_LOCK”寄存器解锁 ECC 区域并覆盖 ECC 奇偶校验位。当从受保护的内存区域读取相应的地址时,根据引入的错误类型,会产生可纠正的或不可纠正的 ECC 错误。

注意:DDR 控制器不支持 ECC 数据中毒。参考手册将进行更新,移除此功能。

因此,我们解锁ECC区域,并从内核层面修改ECC区域以模拟ECC错误并进行测试。基本思路如下:

  1. 将 8 字节值 0xffffffff_ffffffff 写入 DataAddr。DDRC 向 DDR 写入数据的同时,还会写入 1 字节的 ECC 纠错码。

  2. 解锁 ECC 区域,允许核心访问 ECC 区域。

  3. 获取与 DataAddr 对应的 ECC 字节的地址,并读取 ECC 的一个字节。

  4. 将反转后的值 0xffffffff_fffffffe 写入 DataAddr。同时更新 ECC 1 字节。

  5. ECC 1 字节,ECC 读取于 3。将字节值写回。

  6. 锁定 ECC 区域,禁止从核心访问 ECC 区域。

  7. 读取 DataAddr 的值。此时,由于 ECC 不一致,单比特纠错被激活,并读取纠错后的 8 字节值 0xffffffff_ffffffff。同时,内核也会收到一个可纠正错误中断通知。

笔记:

由于这涉及到访问 DDR,因此必须在非缓存区域执行测试。

Keita_Nagashima_11-1765439108812.png

图 10单比特纠错 (SEC) 测试方法¶

 

双比特错误检测 (DED) 调试也可以用同样的方法进行。

 

7.参考资料



8.注意


  • 本文档是使用恩智浦产品的参考指南。

  • 有关正式规格,请参阅产品手册和应用说明。

  • 实际操作可能因各种条件(例如所使用的软件版本)的不同而与所述内容有所不同。

  • 并非所有功能都已验证,因此请务必验证和测试产品,以确保其符合您的预期用途。