zoukankan      html  css  js  c++  java
  • 痞子衡嵌入式:简析i.MXRT1170 Cortex-M4 L-MEM ECC功能特点、开启步骤、性能影响


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

      本篇是 《简析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 NAND 512 bytes 4 bytes 5-bit检错,4-bit纠错
    L-MEM 4bytes 7bits 2-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错误可能会造成程序崩溃。

    Offset Register
    400h TCRAML ECC control Register (LMDR0)
    404h TCRAMU ECC control register (LMDR1)
    480h Local Memory Parity & ECC Control Register (LMPECR)
    488h Local 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 0x1FFE0000U
    
    int 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函数来测试性能影响。

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

    欢迎订阅

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

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

  • 相关阅读:
    ViewData,ViewBag,TempData
    http和https
    Array与ArrayList
    程序员与书和视频
    技术学习的方法研究
    文章发布声明
    面向对象JAVA多态性
    嵌入式开发总结
    CSDN博客代码显示乱码的原因
    将Windows的桌面目录设置到D盘
  • 原文地址:https://www.cnblogs.com/henjay724/p/12763779.html
Copyright © 2011-2022 走看看