痞子衡嵌入式:简析i.MXRT1170 MECC64功能特点及其保护片内OCRAM1,2之道


大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是i.MXRT1170 MECC64功能特点及其保护片内OCRAM1,2之道

ECC是 "Error Correcting Code" 的简写,ECC 能够实现错误检查和纠正,含有 ECC 功能的内存一般称为 ECC 内存,使用了 ECC 内存的系统在稳定性和可靠性上得到很大提升。相比前几代不带 ECC 的 i.MXRT10xx 型号,新一代 i.MXRT1170 在ECC上做了全面武装,从 eFuse 到 FlexRAM,从 OCRAM 到外部存储空间全都加上了 ECC 功能。如下表所示,不同类型的存储由不同的 ECC 控制器来守护:

今天痞子衡给大家简单介绍一下 i.MXRT1170 上用于保护片内 OCRAM1,2 的 MECC64 功能:

一、MECC64功能简介

1.1 MECC64特点

从用户角度来说,其实 MECC64 的设计特别简单,当 MECC64 使能后,任何对受保护的 OCRAM1/2 发起的 AXI 访问都会被 MECC64 模块接管,MECC64 组件负责根据用户写入的数据产生 ECC 校验值并将其存放于专用 OCRAM1/2_ECC 里,读访问时根据用户读取的地址从相应 OCRAM1/2_ECC 地址处获取 ECC 检验值并做检验处理后再返回数据。

从模块框图里看一个 MECC64 里有四个 ECC 小单元(也对应四个 RAM Bank 控制器),这其实是跟单个 512KB OCRAM 由四个 128KB Bank 组成一一对应的,这样便于转化 AXI64 接口到 RAM 接口。

text 复制代码
1. OCRAM 四个 Bank 挂载在 AXI64 系统总线上,AXI[1:0] 决定了访问得是 Bank0-3,这样的设计可以支持对不同 Bank 的读、写操作同时进行。
2. ECC 计算单元是 64bits,这 64bits 数据必须在同一 Bank 里,这个设计对 ECC 初始化操作影响较大,因此避免用 memset 函数去做初始化(STR指令是 byte access)。

MECC64 模块一共有两个,分别是 MECC1、MECC2,分别对应保护 OCRAM1、OCRAM2。此外还有两个专用 OCRAM1_ECC、 OCRAM2_ECC 存放 ECC 校验值(当 MECC64 没使能时,OCRAM1/2_ECC 也可当作普通 OCRAM 使用)。

text 复制代码
MECC1 base address: 4001_4000h
MECC2 base address: 4001_8000h

1.2 关于MECC64设计细节

关于 MECC64 基本概念,参看《简析i.MXRT1170 Cortex-M7 FlexRAM ECC功能特点、开启步骤、性能影响》 的 1.2节,这里不予赘述。

1.2.1 MECC64检验能力

MECC64 中每 64bits 数据就会计算出一个 ECC 校验值(8bits),ECC 算法用得是经典的 Hsiao Hamming。

存储类型 ECC校验数据块大小 ECC校验值长度 ECC校验能力
Raw NAND 512 bytes 4 bytes 5-bit检错,4-bit纠错
MECC64 64bits 8bits 2-bit检错,1-bit纠错
1.2.2 ECC错误触发处理

ECC 错误分两种,分别是 1-bit 错误和 2-bit 错误(针对 64bits 数据而言)。从软件层面来看,1-bit 错误可以不用管,MECC64 模块会自动纠错。我们主要处理 2-bit 错误,由于 2-bit 错误仅能检错,无法纠错,所以发生了这个错误,就意味着读取的数据不可靠了。对于 1/2 bit错误,MECC64 均提供了中断响应(MECCx_INT_IRQn / MECCx_FATAL_INT_IRQn)。

这里还需要特别提醒一下,当读访问是 64bits 时,发生 ECC 错误仅产生一次 ECC 中断,但是如果是 32/16/8bits 读访问则会连续产生两次 ECC 中断,因为 ECC 校验总是以 64bits 为基本数据单元。

二、开启MECC64的步骤

2.1 激活MECC64特性

芯片出厂,默认是没有激活 MECC64 特性的,如果需要开启 MECC64,需要烧写 efuse,fusemap 中 0x840[2] 对应的是 MECC_ENABLE bit,我们需要将这个 bit 烧写成 1,才能激活 MECC64 特性。

2.2 SDK驱动初始化MECC64

然后可以直接利用 SDK 里的 fsl_mecc 驱动对 MECC64 模块进行初始化,代码非常简单,如下示例代码就是初始化 MECC1,使能 OCRAM1 区域的读写 ECC 功能:

C 复制代码
#include "fsl_mecc.h"

void init_mecc(void)
{
    mecc_config_t config;
    MECC_GetDefaultConfig(&config);

    // 使能 MECC64,并且指明受保护的 OCRAM 空间
    config.enableMecc         = true;
    config.Ocram1StartAddress = 0x20240000;
    config.Ocram1EndAddress   = 0x202BFFFF;

    // 初始化 MECC64 模块,并且初始化 OCRAM 区域为全 0
    MECC_Init(MECC1, &config);
}

进 MECC_Init() 函数内部可以看到其对 OCRAM 区域的初始化用得是 64bits 赋值,这样可以保证正确生成首次 ECC 校验值,等 OCRAM 区域全部初始化过后,底下就可以对 OCRAM 进行任意数据长度的访问了。

2.3 AXI方式读写OCRAM区域

现在我们直接调试 \SDK_2_14_0_MIMXRT1170-EVKB\boards\evkbmimxrt1170\driver_examples\mecc\mecc_single_error\cm7\iar 工程,跑到 MECC 初始化结束后,打开 Memory 窗口,可以看到 OCRAM1 区域(0x20240000 - 0x202BFFFF) 已经是全 0,OCRAM1_ECC 区域(0x20340000 - 0x2034FFFF)也是全 0。但是往 0x20240020 处写入 8 字节测试数据后,并没有看到 OCRAM1_ECC 区域有数据上的变化,说明 ECC 校验码数据是受保护的,仅能被 MECC64 模块访问,对用户不可见。

三、激活MECC64特性后的影响

前面讲到 fusemap 中 0x840[2] 对应的是 MECC_ENABLE bit,这个 bit 被烧录为 1 后,我们还需要初始化 MECC64 模块里(打开MECC->PIPE_ECC_EN[ECC_EN])才能真正开启 OCRAM ECC 功能,但是别忘了芯片参考手册里 MECC64 章节有一个提醒:

是的,BootROM 上电运行,第一件事就是检查 fuse MECC_ENABLE bit 位,如果已经置 1,那就立刻开启 MECC1 和 MECC2 模块的 PIPE_ECC_EN[ECC_EN],即启用 OCRAM ECC,但是 BootROM 并没有初始化全部 OCRAM1 和 OCRAM2 区域,仅仅初始化了 OCRAM1 前 48KB,这部分是 BootROM 程序的 RW 区。

痞子衡找了两块 RT1170 板卡做了对比测试(芯片设为 Serial Downloader模式,挂上 JLink 读取内存),未激活 MECC64 特性的芯片 OCRAM 区域读取出来全是随机值,而激活了 MECC64 特性的芯片仅 ROM RW 区被初始化了以及 OCRAMx_ECC 不可访问外,其余区域全是随机值(这里的读取其实不太可靠,毕竟使能了 ECC 后首次访问必须是写,然后才能正常被读写)。

对于激活了 MECC64 特性之后的芯片,无论是设计下载算法还是 IDE 里的初始化脚本,或者 App 应用里的变量访问,如果涉及到 ROM RW 区之外的 OCRAM1,OCRAM2 区域,建议一律做先写后读处理,否则可能会出现奇怪的错误。

至此,i.MXRT1170 MECC64功能特点及其保护片内OCRAM1,2之道痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

文章会同时发布到我的 博客园主页CSDN主页知乎主页微信公众号 平台上。

微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。