加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入
  • 正文
  • 推荐器件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

ECC给i.MXRT1170 FlexRAM带来了哪些变化?

2020/04/13
578
阅读需 14 分钟
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是恩智浦 i.MXRT1170 上 Cortex-M7 内核的 FlexRAM ECC 功能。

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

今天痞子衡就先给大家简单介绍一下 i.MXRT1170 上 Cortex-M7 内核下的 FlexRAM ECC 功能:

一、FlexRAM ECC 功能简介

1.1 FlexRAM v2 特点

i.MXRT1170 上的 FlexRAM 模块是 v2 版本,相比 i.MXRT10xx 上的 FlexRAM v1 版本,主要就是增加了 ECC 功能。关于 FlexRAM v1 基本功能,建议你先阅读痞子衡之前写过的文章 《恩智浦 i.MX RT1xxx 系列 MCU 外设那些事(2)- 百变星君 FlexRAM》,痞子衡今天主要聊 v2 新增的功能。

我们知道 i.MXRT1170 是 Cortex-M7 和 Cortex-M4 双核架构,我们看下它的 CM7 内核系统框图,FlexRAM 本质上是为 CM7 内核设计的,因为其管理的 TCM 空间仅能由 CM7 访问的,不过如果将 FlexRAM 也分配出一部分给 OCRAM,这部分 OCRAM(即文章开头 memory map 表里从 0x20360000 开始的空间)其实 CM4 也能正常访问。

在框图中你还会发现,FlexRAM 中物理 SRAM 总大小是 640KB,不是我们知道的可自由配置的 512KB,这是因为需要额外 128KB RAM 来存放 ECC 校验值,关于这个细节在下一节里展开聊。

 

 

1.2 关于 ECC 设计细节

关于 ECC,大家最早接触的应该是 ONFI Raw NAND 上的应用,NAND Flash 因为其物理特性的原因(允许坏块的存在),必须要包含 ECC 功能,痞子衡写过的一篇文章 《并行 NAND 接口标准(ONFI)及 SLC Raw NAND 简介》, 里面的 2.6 Raw NAND 坏块与 ECC 简单介绍了 ECC 在 Raw NAND 上的应用。

在 Raw NAND 上,通常是每写入 512bytes 数据计算出一个 ECC 校验值(4bytes),读取时也是读完全部 512bytes 数据后进行 ECC 校验,ECC 校验能力一般用 (n+1) bit 检错,n bit 纠错 来表达,即这 512bytes 数据里如果发生 n+1 bit 及以下的错误时能够检查出来,如果发生 n bit 及以下的错误时,能够自动纠正。比如典型的 Micron MT29F4G08 就是 5-bit 检错,4-bit 纠错。

但是 FlexRAM 本质上是 RAM,跟 Flash(尤其是 NAND)读写机制不一样,RAM 是随机地址按 Byte 读写,NAND 是以 Page 为单位顺序读写,所以 NAND 上 ECC 实现机制不适用于 RAM。那么 FlexRAM 到底采用的是什么样的 ECC 设计呢?

1.2.1 ECC 检验能力

好了,不卖关子了,公布答案。FlexRAM 中每 4ytes(针对 DTCM)或 8bytes(针对 ITCM/OCRAM)数据就会计算出一个 ECC 校验值(7/8bits),ECC 校验值都被放在了 ECC RAM 里。因为校验数据块分割得很小,所以此时不需要提供多 bit 纠错能力,FlexRAM 采用的是最经典的 Single-bit Error Correction and Dual-bit Error Detection(SEC-DED,汉明校验码)。关于 SEC-DED,你可以去 Linux 内核里看其在 NAND 上应用的源码实现 nand_ecc.c,写得非常经典。

存储类型 ECC 校验数据块大小 ECC 校验值长度 ECC 校验能力
Raw NAND 512 bytes 4 bytes 5-bit 检错,4-bit 纠错
FlexRAM 4/8 bytes 7/8 bits 2-bit 检错,1-bit 纠错
 
1.2.2 ECC RAM 分配

128KB ECC RAM 并不是只能用来存储 ECC 校验值的,其也可以当做普通 OCRAM 来使用,ECC RAM 具体功能是根据当前 FlexRAM 分配以及 ECC 是否开启而定的。eFuse 里默认的 512KB FlexRAM 配置是 256KB ITCM, 256KB DTCM, 没有 OCRAM。

在默认 FlexRAM 配置情况下,如果 TCM ECC 没有开启,那么 128KB ECC RAM 全部都是普通 OCRAM,其地址空间如下表所示:

在默认 FlexRAM 配置情况下,如果 TCM ECC 已经开启,那么 128KB ECC RAM 全部都用来存储 ECC 校验值,这个区域仅能由 FlexRAM 模块内部访问,用户无法访问这 128KB 区域(不在 memory map 空间里),毕竟 ECC 校验值不能被随便改。

如果我们在 eFuse 或者 IOMUXC_GPR 寄存器里将 FlexRAM 配置改掉,分配出一部分给 OCRAM(比如 256KB TCM, 256KB OCRAM),那这 128KB ECC RAM 功能分配就稍微复杂一些了。最简单的情况是 TCM 和 OCRAM ECC 都没有开启,那么这 128KB ECC RAM 还是普通 OCRAM,map 地址是紧跟在 FlexRAM OCRAM 后面的,如下表所示:

如果 TCM 和 OCRAM ECC 都开启了,那么这 128KB ECC RAM 就还是全部用来存储 ECC 校验值了,用户无法访问。

如果 OCRAM ECC 没有开启,不管 TCM ECC 是否开启,这 128KB ECC RAM 中本用于存储 OCRAM ECC 的区域都将被划分为普通 OCRAM,另一部分用于存储 TCM ECC 的区域(无论是否真的要存储 ECC 校验值)用户则无法访问。区域划分比例与 OCRAM 在总 FlexRAM 大小中占比保持一致,比如 512KB FlexRAM(一共 16 个 bank,每个 bank 32KB)划分出了 256KB OCRAM,那么 128KB ECC RAM(也是 16 个 bank,每个 bank 8KB)则划出了 64KB 作为普通 OCRAM,如下表所示:

1.2.3 ECC 错误触发处理

ECC 错误分两种,分别是 1-bit 错误和 2-bit 错误。从软件层面来看,1-bit 错误可以不用管,FlexRAM 模块会自动纠错。我们主要处理 2-bit 错误,由于 2-bit 错误仅能检错,无法纠错,所以发生了这个错误,就意味着读取的数据不可靠了,需要丢弃并重新写一次(丢弃之前可以再 retry read 一次看是否还是报错)。

关于 ECC 错误处理,可根据如下 FlexRAM 寄存器来操作,首先当然是在 INT_SIG_EN 寄存器中使能 multi-bit ECC Error,当有 2-bit 错误发生时,系统会触发 FLEXRAM_IRQn(中断号是 50),在中断处理程序里找到相应的 ECC_MULTI_ERROR_ADDR,对这个地址重新写一次初始化数据(按 ECC 校验块长度一次性写入),最后清除 INT_STATUS 寄存器里的相应状态位。

需要注意的是,上述处理流程仅对 FlexRAM 中存放的是普通业务数据且发生 ECC 错误时有效,如果 ECC 错误发生在关键代码段或变量段中,这个处理是不适用的,因为这种 ECC 错误可能会造成程序崩溃。

Offset Register
10h Interrupt Status Register (INT_STATUS)
14h Interrupt Status Enable Register (INT_STAT_EN)
18h Interrupt Enable Register (INT_SIG_EN)
30h OCRAM multi-bit ECC Error Address Register (OCRAM_ECC_MULTI_ERROR_ADDR)
50h ITCM multi-bit ECC Error Address Register (ITCM_ECC_MULTI_ERROR_ADDR)
6Ch D0TCM multi-bit ECC Error Address Register (D0TCM_ECC_MULTI_ERROR_ADDR)
84h D1TCM multi-bit ECC Error Address Register (D1TCM_ECC_MULTI_ERROR_ADDR)

 

二、开启 FlexRAM ECC 的步骤

FlexRAM ECC 需要按照标准步骤去开启,需要特别注意的是开启 ECC 操作的代码不能放在待开启 ECC 的 FlexRAM 空间里(比如 TCM ECC 要开启,那么开启 ECC 操作的代码不能使用任何 TCM 空间),因此不管是 XIP 还是 Non-XIP 应用程序,最好是用一个二级 loader(这个 loader 可以链接在固定 OCRAM1/2 空间里,或者 XIP)来完成 ECC 开启操作然后再加载应用程序执行。痞子衡给了如下示例 loader 代码工程,代码里主要有四个步骤:

参考代码:https://github.com/JayHeng/cortex-m-apps/blob/master/apps/coremark_imxrt1176/loader/loader.c

2.1 使能 TCM 的 RMW(可选)

如果需要开启 TCM ECC,那么首先需要在 CM7 内核寄存器里开启 TCM RMW(Read-Modify-Write)功能,这是 ARM 的规定,可在 Cortex-M7 Technical RM 手册里找到相关信息如下。手册里明确写了 RMW 位同时也控制了外部逻辑(即 MCU 厂商的设计)来支持 ECC 功能。

操作函数代码如下:

void enable_cm7_tcm_rmw(void)
{
    SCB->ITCMCR |= SCB_ITCMCR_RMW_Msk;
    SCB->DTCMCR |= SCB_DTCMCR_RMW_Msk;
}

2.2 使能 FlexRAM 的 ECC

现在需要开启 FlexRAM ECC,在 i.MXRT1170 参考手册里的 FlexRAM 章节可以找到 FLEXRAM_CTRL 寄存器定义,其中 bit5 和 bit4 就是用来分别控制 TCM 和 OCRAM 的 ECC 开关

操作函数代码如下:

void enable_flexram_tcm_ecc(void)
{
    *(uint32_t *)(FLEXRAM_BASE + 0x108) |= (1u << 5);
}

void enable_flexram_ocram_ecc(void)
{
    *(uint32_t *)(FLEXRAM_BASE + 0x108) |= (1u << 4);
}

2.3 初始化 FlexRAM 的 ECC 值

FlexRAM ECC 开启了之后,此时还不能随机访问 FlexRAM,因为初始 ECC 校验值还没有填充,如果这时候去读 FlexRAM 会产生错误。我们首先需要将会用到的 FlexRAM 空间全部初始化一遍(就是以 ECC 校验数据块大小对齐方式从头到尾写入一遍,写入内容不限,正常用全 0)。

操作函数代码如下:

#define ITCM_START   0x00000000
#define ITCM_SIZE    (256*1024U)  // 只是示例长度,根据实际情况修改
#define DTCM_START   0x20000000
#define DTCM_SIZE    (256*1024U)  // 只是示例长度,根据实际情况修改
#define OCRAM_START  0x20360000
#define OCRAM_SIZE   (256*1024U)  // 只是示例长度,根据实际情况修改

void init_flexram_itcm_ecc(void)
{
    for (uint32_t i = 0; i < ITCM_SIZE; i += sizeof(uint64_t))
    {
        *(uint64_t *)(ITCM_START + i) = 0;
    }
}

void init_flexram_dtcm_ecc(void)
{
    for (uint32_t i = 0; i < DTCM_SIZE; i += sizeof(uint32_t))
    {
        *(uint32_t *)(DTCM_START + i) = 0;
    }
}

void init_flexram_ocram_ecc(void)
{
    for (uint32_t i = 0; i < OCRAM_SIZE; i += sizeof(uint64_t))
    {
        *(uint64_t *)(OCRAM_START + i) = 0;
    }
}

 

2.4 加载应用程序执行

当 FlexRAM 初始 ECC 校验值已经被填充之后,此时便可以正常随机读写 FlexRAM 了。如果此时加载的是一个在 ITCM 里执行并且 data 段在 DTCM 里的应用程序,可以参考痞子衡前面给出的示例 loader 工程。

这是 loader 工程完整主函数代码,其中 memcpy 那一句代码里的 app_code 是应用程序 binary 数组(用 Python 脚本将应用程序工程生成的 .bin 文件转换成 C 语言数组放到 loader 工程源文件里)。

#define APP_START 0U

int main(void)
{
    enable_cm7_tcm_ecc();
    enable_flexram_tcm_ecc();
    init_flexram_itcm_ecc();
    init_flexram_dtcm_ecc();

    // Copy image to RAM.
    memcpy((void *)APP_START, app_code, APP_LEN);
    
    uint32_t appStack = *(uint32_t *)(APP_START);
    uint32_t appEntry = *(uint32_t *)(APP_START + 4);

    // Turn off interrupts.
    __disable_irq();

    // Set the VTOR to default.
    SCB->VTOR = APP_START;

    // Memory barriers for good measure.
    __ISB();
    __DSB();

    // Set main stack pointer and process stack pointer.
    __set_MSP(appStack);
    __set_PSP(appStack);

    // Jump to app entry point, does not return.
    void (*entry)(void) = (void (*)(void))appEntry;
    entry();
}

 

三、ECC 对内存访问性能的影响

FlexRAM 开了 ECC 后,访问性能会有一定降低,毕竟数据访问中插入了额外的 ECC 校验工作,不过这个影响非常小,因为一次 ECC 校验仅增加 1-2 个机器 cycle。下面是 FlexRAM 分配出的不同存储类型的基本情况,其中 OCRAM 可以被 L1 Cache 加速,所以从应用程序角度开 ECC 对其访问性能影响就更小了,我们主要讨论 ECC 对 TCM 性能的影响。

FlexRAM 分配类型 ECC 校验数据块大小 总线类型 访问速度 L1 Cache 加速
ITCM 8 bytes ITCM_ITF 64-bits 与 CM7 同频
DTCM 4 bytes DTCM_ITF 2x32-bit 与 CM7 同频
OCRAM 8 bytes AXI64 与 CM7 频率的 1/4

为了简化测试,痞子衡就用经典的 benchmark 程序(Coremark 和 Dhrystone)来测试 ECC 对 TCM 的影响,测试工程如下:

Coremark 工程:https://github.com/JayHeng/cortex-m-apps/tree/master/apps/coremark_imxrt1176/loader Dhrystone 工程:https://github.com/JayHeng/cortex-m-apps/tree/master/apps/dhrystone_imxrt1176/loader

需要特别提醒的是,我们知道 i.MXRT1170 CM7 内核最高可以配置到 1GHz,但是开了 TCM ECC 后,为了保证访问可靠性,此时 CM7 内核最好是工作在 800MHz,下面的 benchmark 结果也是在 800MHz 主频下得到的:

Benchmark 类型 TCM ECC 开关 Benchmark 结果
coremark 关闭 Total ticks : 2023600
Total time (secs): 20.236000
Iterations/Sec : 3953.350465
Iterations : 80000
CoreMark 1.0 : 3953.350465
coremark 开启 Total ticks : 2023657
Total time (secs): 20.236570
Iterations/Sec : 3953.239111
Iterations : 80000
CoreMark 1.0 : 3953.239111
dhrystone 关闭 Dhrystones per Second: 3622138.51
DMIPS: 2061.5472
DMIPS/MHz: 2.0698
dhrystone 开启 Dhrystones per Second: 3621977.04
DMIPS: 2061.4553
DMIPS/MHz: 2.0697

从 benchmark 结果来看,ECC 是否开启对性能影响特别小,可以忽略,当然 benchmark 测试并不是特别精确地反映了性能影响,底下有空痞子衡会再专门用 memcpy 函数来测试性能影响。

至此,恩智浦 i.MXRT1170 上 Cortex-M7 内核的 FlexRAM ECC 功能痞子衡便介绍完毕了,掌声在哪里~~~

推荐器件

更多器件
器件型号 数量 器件厂商 器件描述 数据手册 ECAD模型 风险等级 参考价格 更多信息
ASV-50.000MHZ-EJ-T 1 Abracon Corporation XTAL OSC XO 50.0000MHZ HCMOS SMD

ECAD模型

下载ECAD模型
$0.82 查看
MCP2551-I/SN 1 Microchip Technology Inc DATACOM, INTERFACE CIRCUIT, PDSO8, 0.150 INCH, LEAD FREE, PLASTIC, SOIC-8

ECAD模型

下载ECAD模型
$1.37 查看
74HC14D 1 Philips Semiconductors Inverter, CMOS, PDSO14,
$0.91 查看
恩智浦

恩智浦

恩智浦半导体创立于2006年,其前身为荷兰飞利浦公司于1953年成立的半导体事业部,总部位于荷兰埃因霍温。恩智浦2010年在美国纳斯达克上市。恩智浦2010年在美国纳斯达克上市。恩智浦半导体致力于打造全球化解决方案,实现智慧生活,安全连结。

恩智浦半导体创立于2006年,其前身为荷兰飞利浦公司于1953年成立的半导体事业部,总部位于荷兰埃因霍温。恩智浦2010年在美国纳斯达克上市。恩智浦2010年在美国纳斯达克上市。恩智浦半导体致力于打造全球化解决方案,实现智慧生活,安全连结。收起

查看更多

相关推荐

电子产业图谱

硕士毕业于苏州大学电子信息学院,目前就职于恩智浦(NXP)半导体MCU系统部门,担任嵌入式系统应用工程师。痞子衡会定期分享嵌入式相关文章