查看: 1398|回复: 0

[分享] 简析i.MXRT1170 Cortex-M4 L-MEM ECC功能特点、开启步骤、性能影响

[复制链接]
  • TA的每日心情
    慵懒
    昨天 18:03
  • 签到天数: 1216 天

    [LV.10]以坛为家III

    22

    主题

    4777

    帖子

    0

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    8107

    活跃会员

    最后登录
    2024-5-1
    发表于 2021-5-7 17:30:58 | 显示全部楼层 |阅读模式
    本篇是 《简析i.MXRT1170 Cortex-M7 FlexRAM ECC功能特点、开启步骤、性能影响》 的姊妹篇,我们知道i.MXRT1170是双核MCU,主核Cortex-M7的TCM ECC由FlexRAM模块负责,那么从核Cortex-M4的TCM有没有ECC呢?如果有的话,是由哪个模块负责的呢?本篇给你解答。
      老规矩先来看一下Cortex-M4下的系统内存映射表,不同类型的存储由不同的ECC控制器来守护,从表中看,CM4的TCM也是有ECC功能的,ECC功能集成在了L-MEM控制器里,所以今天我们来聊一聊L-MEM的ECC功能。

    一、L-MEM ECC功能简介1.1 L-MEM特点  我们先来看下i.MXRT1170的CM4内核系统框图,L-MEM是专门为CM4内核设计的,其管理的TCM空间仅能由CM4访问。在框图中,L-MEM中物理SRAM总大小是256KB,细心的你可能发现了上面那张系统内存映射表中还有个256KB OCRAM(M4),这个OCRAM与L-MEM是什么联系?其实它俩指向的是同一块物理SRAM,只不过CM4内核是从TCM地址空间直接访问SRAM,而从OCRAM(M4)地址空间去访问SRAM相当于多绕了一级(速度变慢,所以不建议CM4访问OCRAM(M4)空间,这个地址空间主要是给CM7访问的)。
      我们知道支持ECC功能,需要有额外空间来存储ECC校验值,那么L-MEM的ECC校验值是存在哪里的呢?关于这个细节在下一节里展开聊。

    1.2 关于ECC设计细节  关于ECC基本概念,参看《简析i.MXRT1170 Cortex-M7 FlexRAM ECC功能特点、开启步骤、性能影响》 的 1.2节,这里不予赘述。
    1.2.1 ECC检验能力  L-MEM中每4bytes数据就会计算出一个ECC校验值(7bits),ECC校验值都被放在了ECC RAM区域里。这里必须要特别介绍一下ECC RAM区域,不同于FlexRAM ECC会有专门的独立RAM空间用于存放ECC校验值,L-MEM的ECC校验值是紧跟着放在每个32bit数据后面的,用户访问到的L-MEM是32bit数据线,但其实芯片内部设计L-MEM是39bit数据线,其中高7bit就是专门用来存放ECC校验值的。
    存储类型ECC校验数据块大小ECC校验值长度ECC校验能力
    Raw NAND512 bytes4 bytes5-bit检错,4-bit纠错
    L-MEM4bytes7bits2-bit检错,1-bit纠错

    1.2.2 ECC错误触发处理  关于ECC错误处理,可根据如下MCM寄存器(不要怀疑,L-MEM ECC的控制就是在MCM里实现的)来操作,首先当然是在LMPECR寄存器中使能multi-bit ECC Error,当有2-bit及以上错误发生时,系统会触发NonMaskableInt_IRQn(中断号是-14),在中断处理程序里找到相应的发生ECC错误的地址,对这个地址重新写一次初始化数据(按ECC校验块长度一次性写入),最后清除LMPEIR寄存器里的相应状态位。
      需要注意的是,上述处理流程仅对L-MEM中存放的是普通业务数据且发生ECC错误时有效,如果ECC错误发生在关键代码段或变量段中,这个处理是不适用的,因为这种ECC错误可能会造成程序崩溃。

    OffsetRegister
    400hTCRAML ECC control Register (LMDR0)
    404hTCRAMU ECC control register (LMDR1)
    480hLocal Memory Parity & ECC Control Register (LMPECR)
    488hLocal Memory Parity & ECC Interrupt Register (LMPEIR)

    二、开启L-MEM ECC的步骤  L-MEM ECC需要按照标准步骤去开启,需要特别注意的是开启ECC操作的代码不能放在待开启ECC的L-MEM空间里,因此不管是XIP还是Non-XIP应用程序,最好是用一个二级loader(这个loader可以链接在固定OCRAM1/2空间里,或者XIP)来完成ECC开启操作然后再加载应用程序执行。痞子衡给了如下示例loader代码工程,代码里主要有四个步骤:
    参考代码:https://github.com/JayHeng/cortex-m-apps/blob/master/apps/coremark_imxrt1176/cm4_loader/loader.c
    2.1 激活L-MEM ECC特性  芯片出厂,默认是没有激活L-MEM ECC特性的,如果需要开启L-MEM ECC,需要烧写efuse,fusemap中0x840[2]对应的是MECC_ENABLE bit,这个bit不仅控制MECC模块,也同时控制了L-MEM ECC特性,我们需要将这个bit烧写成1,才能激活L-MEM ECC特性。
    2.2 使能L-MEM的ECC  现在需要使能L-MEM ECC,在i.MXRT1170参考手册里的MCM章节可以找到LMDR0/1寄存器定义,其中bit3就是用来分别控制TCRAML(对应ITCM)和TCRAMU(对应DTCM)的ECC开关。特别注意,这里的MCM模块寄存器仅能在CM4下被访问。
      操作函数代码如下:
    void enable_lmem_tcm_ecc(void){    // Check eFuse 0x840[2] - MECC_ENABLE bit    while (!(OCOTP->HW_OCOTP_FUSE004 & 0x4));    // MCM->LMPECR[9,1] - Enable TCRAM ECC 1-bit/Multi-bit IRQ    *(uint32_t *)0xE0080480 |= 0x303;    // MCM->LMDR0[3] - Enable TCRAML ECC    *(uint32_t *)0xE0080400 |= 0x0B;        /* Enable CM4 TCRAM_L ECC */    // MCM->LMDR1[3] - Enable TCRAMU ECC    *(uint32_t *)0xE0080404 |= 0x0B;        /* Enable CM4 TCRAM_U ECC */}2.3 初始化L-MEM的ECC值  L-MEM ECC开启了之后,此时还不能随机访问L-MEM,因为初始ECC校验值还没有填充,如果这时候去读L-MEM会产生错误。我们首先需要将会用到的L-MEM空间全部初始化一遍(就是以ECC校验数据块大小对齐方式从头到尾写入一遍,写入内容不限,正常用全0)。
      操作函数代码如下:

    #define ITCM_START   0x1FFE0000#define ITCM_SIZE    (128*1024U)#define DTCM_START   0x20000000#define DTCM_SIZE    (128*1024U)void init_lmem_itcm_ecc(void){    for (uint32_t i = 0; i < ITCM_SIZE; i += sizeof(uint32_t))    {        *(uint32_t *)(ITCM_START + i) = 0;    }}void init_lmem_dtcm_ecc(void){    for (uint32_t i = 0; i < DTCM_SIZE; i += sizeof(uint32_t))    {        *(uint32_t *)(DTCM_START + i) = 0;    }}2.4 加载应用程序执行  当L-MEM初始ECC校验值已经被填充之后,此时便可以正常随机读写L-MEM了。如果此时加载的是一个在ITCM里执行并且data段在DTCM里的应用程序,可以参考痞子衡前面给出的示例loader工程。
      这是loader工程完整主函数代码,其中memcpy那一句代码里的cm4_app_code是应用程序binary数组(用Python脚本将应用程序工程生成的.bin文件转换成C语言数组放到loader工程源文件里)。

    #define APP_START 0x1FFE0000Uint main(void){    enable_lmem_tcm_ecc();    init_lmem_itcm_ecc();    init_lmem_dtcm_ecc();    // Copy image to RAM.    memcpy((void *)APP_START, cm4_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对内存访问性能的影响  L-MEM开了ECC后,访问性能会有一定降低,毕竟数据访问中插入了额外的ECC校验工作,不过据说影响非常小。我们来做个测试,痞子衡就用经典的benchmark程序(Coremark)来测试ECC对L-MEM的影响,测试工程如下:
    Coremark工程:https://github.com/JayHeng/cortex-m-apps/tree/master/apps/coremark_imxrt1176/bsp/build7804_cm4_loader
      需要特别提醒的是,我们知道i.MXRT1170 CM4内核最高可以配置到480MHz,但是开了L-MEM ECC后,为了保证访问可靠性,此时CM4内核最好是工作在360MHz,下面的coremark结果也是在360MHz主频下得到的:
    Benchmark类型L-MEM ECC开关Benchmark结果
    coremark关闭Total ticks : 813867
    Total time (secs): 25.433344
    Iterations/Sec : 1179.553907
    Iterations : 30000
    CoreMark 1.0 : 1179.553907
    coremark开启Total ticks : 813868
    Total time (secs): 25.433375
    Iterations/Sec : 1179.552458
    Iterations : 30000
    CoreMark 1.0 : 1179.552458

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

    该会员没有填写今日想说内容.
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-5-2 06:05 , Processed in 0.100777 second(s), 18 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.

    快速回复 返回顶部 返回列表