痞子衡嵌入式:简析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 接口),这样的设计有如下两个注意点:

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

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

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 功能:

#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 赋值(1.1小节里的 Note2),这样可以保证正确生成首次 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主页知乎主页微信公众号 平台上。

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

posted @ 2023-12-28 20:46  痞子衡  阅读(181)  评论(0编辑  收藏  举报