大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道

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

痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道-LMLPHP

  今天痞子衡给大家简单介绍一下 i.MXRT1170 上用于保护挂载在 FlexSPI 和 SEMC 接口上的外部存储器的 XECC 功能:

一、XECC功能简介

1.1 XECC特点

  从用户角度来说,其实 XECC 的设计特别简单,当 XECC 使能后,任何对 ECC 保护区域的 AHB 访问(注意仅 AHB 方式才能激活 XECC,IPG 方式是不受 XECC 影响的)都会被 XECC 模块接管,WECC 组件负责根据用户写入的数据值产生 ECC 校验值一并存入目标地址,RECC 组件负责根据用户读取的地址获取相应 ECC 检验值并做检验处理后再返回数据值。WECC 和 RECC 组件可独立开关控制。

痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道-LMLPHP

  XECC 模块一共有三个,分别是 XECC_FLEXSPI1、XECC_FLEXSPI2、XECC_SEMC,每个模块均支持 4 个 ECC 区域的设置(区域最小单位 4KB,即 ECC_BASE/EDD_ADDRx 寄存器的低 12bits 总是 0)。

痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道-LMLPHP

1.2 关于ECC设计细节

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

1.2.1 ECC检验能力

  XECC 中每 4bits 数据就会计算出一个 ECC 校验值(4bits),不同于 FlexRAM ECC 会有专门的独立存储空间用于存放 ECC 校验值,XECC 校验值是紧跟着放在源数据后面的,这意味着 XECC 校验值会占据目标存储器(Flash 或 SDRAM)里受 ECC 保护区域的一半空间。

  为便于 master 通过 AHB 总线访问,实际 XECC 检验值是拓展到 32bits 来存储的,即 32bits 原始数据后面会紧跟着 32bits XECC 检验值,如此往复如下图所示。

痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道-LMLPHP

  比如 XECC 保护挂在 FlexSPI1 上的 Flash,设置的 Flash ECC 保护区域为 0x30000000 - 0x30000FFF,共 4KB 空间。那么从实际物理空间角度(IPG 方式去读)来说 0x30000000 处保存的是原始 4bytes 用户数据(D0),0x30000004 处保存的是 4bytes XECC 校验值(E0),0x30000008 处保存的又是原始 4bytes 用户数据(D1),0x3000000c 处保存的又是 4bytes XECC 校验值(E1)...

  注意上述地址均表述的是实际物理地址,但 master 通过 AHB 总线直接读写 Flash 时,仅需访问 0x30000000 - 0x300007FF 空间里的 2KB 实际用户数据即可,完全不需在意另外 2KB 的 XECC 检验值的处理,SoC 系统里直接做了自动处理与地址转换,即 0x30000000 处对应校验后的 4bytes 用户数据(D0),0x30000004 处对应校验后的 4bytes 用户数据(D1)...

1.2.2 ECC错误触发处理

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

  对于 32bits 数据而言,XECC 是可以纠正其中发生的 8bits 错误的,但前提是按序分割开的每 4bits 数据位仅能有 1bit 错误,如果这 4bits 数据位里有多 bit 错误,我们依然想校正的话,需要借助 Data Swap 功能,这里不再单独展开,可查看 RM 了解细节。

痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道-LMLPHP

二、开启XECC的步骤

2.1 激活XECC特性

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

痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道-LMLPHP

2.2 初始化存储器接口外设

  在初始化 XECC 模块之前一般先初始化存储器接口外设,这里我们先初始化 FlexSPI1,因为测试板卡 MIMXRT1170-EVK 上默认是 FlexSPI1 连接的串行 NOR Flash。

void init_flexspi_flash(void)
{
    flexspi_nor_flash_init(FLEXSPI1);

    // 尽量等待 FlexSPI 总线空闲再退出
    if ((FLEXSPI1->MCR0 & FLEXSPI_MCR0_MDIS_MASK) != FLEXSPI_MCR0_MDIS_MASK)
    {
        while (!FLEXSPI_GetBusIdleStatus(FLEXSPI1));
    }

    FLEXSPI_SoftwareReset(FLEXSPI1);
}

2.3 SDK驱动初始化XECC

  然后可以直接利用 SDK 里的 fsl_xecc 驱动对 XECC 模块进行初始化,代码非常简单,如下示例代码就是初始化 XECC_FLEXSPI1,使能 0x30000000 - 0x30000FFF 区域的读写 ECC 功能:

#include "fsl_xecc.h"

void init_flexspi_xecc(void)
{
    xecc_config_t config;
    XECC_GetDefaultConfig(&config);

    // 同时使能读写 XECC
    config.enableXECC     = true;
    config.enableWriteECC = true;
    config.enableReadECC  = true;

    // 设置 ECC 区域(0x30000000 - 0x30000FFF)
    config.Region0BaseAddress = FlexSPI1_AMBA_BASE;
    config.Region0EndAddress  = FlexSPI1_AMBA_BASE + 0x1000;

    // 初始化 XECC 模块
    XECC_Init(XECC_FLEXSPI1, config);
}

2.4 AHB方式读写ECC目标区域

  最后就是利用 《其实i.MXRT下改造FlexSPI driver同样支持AHB方式去写入NOR Flash》 一文 3.3 节里的 flexspi_nor_flash_program() 函数来对 Flash 做 AHB 方式的写入,以激活 XECC 工作。为了验证 XECC 是否工作正常,可以分别用 IPG 和 AHB 方式读回写入的区域看最终结果。

SDK_ALIGN(static uint8_t s_nor_program_buffer[256], 4);
static uint8_t s_nor_ipg_read_buffer[256];
static uint8_t s_nor_ahb_read_buffer[256];

void test_flash_ecc_rw(void)
{
    // 擦除 Flash 0x30000000 开始的 4KB 区域(1个Sector)
    flexspi_nor_flash_erase_sector(FLEXSPI1, 0x0);

    for (uint32_t i = 0; i < 0xFFU; i++)
    {
        s_nor_program_buffer[i] = i;
    }
    // AHB 方式写 256 字节数据进 Flash 0x30000000 开始的地址
    flexspi_nor_flash_program(FLEXSPI1, 0x30000000, s_nor_program_buffer, 256);

    DCACHE_CleanInvalidateByRange(0x30000000, 0x1000);

    // IPG 方式从 Flash 0x30000000 开始的地址读出 256 字节数据
    flexspi_nor_flash_read(FLEXSPI1, 0x0, (void *)s_nor_ipg_read_buffer, 256);

    // AHB 方式从 Flash 0x30000000 开始的地址读出 256 字节数据
    memcpy((void *)s_nor_ahb_read_buffer, (void *)0x30000000, 256);
}

痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道-LMLPHP

  至此,简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

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

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

痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道-LMLPHP

08-30 10:29