痞子衡嵌入式:简析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的影响,测试工程如下:
需要特别提醒的是,我们知道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主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:简析i.MXRT1170 Cortex-M4 L-MEM ECC功能特点、开启步骤、性能影响的更多相关文章
- 痞子衡嵌入式:揭秘i.MXRT1170 eFuse空间访问可靠性的保护策略(冗余与ECC)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MXRT1170的eFuse空间访问可靠性保护策略. 关于i.MXRT系列的eFuse/OTP,痞子衡之前在介绍Boot时写过 ...
- 痞子衡嵌入式:在i.MXRT1170上启动含DQS的Octal Flash可不严格设Dummy Cycle (以MT35XU512为例)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是Octal或Hyper Flash上DQS信号与Dummy Cycle联系. 关于在 i.MXRT 上启动 NOR Flash 时如何设 ...
- 痞子衡嵌入式:揭秘i.MXRT1170上用J-Link连接复位后PC总是停在0x223104的原因
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1170上安全调试策略实现对JLink调试的影响. 痞子衡之前写过一篇旧文 <i.MXRT600的ISP模式下用J-L ...
- 痞子衡嵌入式:揭秘i.MXRT1170上串行NOR Flash双程序可交替启动设计
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1170上串行NOR Flash双程序可交替启动设计. 在上一篇文章 <i.MXRT1060/1010上串行NOR F ...
- 痞子衡嵌入式:聊聊i.MXRT1170双核下不同GPIO组的访问以及中断设计
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1170双核下不同GPIO组的访问以及中断设计. 在双核 i.MXRT1170 下设计应用程序,有一个比较重要的考虑点就是外 ...
- 痞子衡嵌入式:简析i.MXRT1170 Cortex-M7 FlexRAM ECC功能特点、开启步骤、性能影响
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是恩智浦i.MXRT1170上Cortex-M7内核的FlexRAM ECC功能. ECC是"Error Correcting ...
- 痞子衡嵌入式:简析i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道. ECC 是 "Error Correc ...
- 痞子衡嵌入式:测一测i.MXRT1170 Raw NAND启动时间(从POR到进App的Reset_Handler)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MX RT1170 Raw NAND启动时间. 关于i.MXRT1170这颗划时代的MCU,痞子衡去年10月在其刚发布的时候, ...
- 痞子衡嵌入式:大话双核i.MXRT1170之Cortex-M7与Cortex-M4互相激活之道
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是恩智浦i.MXRT1170上Cortex-M7与Cortex-M4内核互相激活的方法. 痞子衡最近在深耕i.MXRT1170这颗划时代的 ...
随机推荐
- OpenCV-Python SIFT尺度不变特征变换 | 三十九
目标 在这一章当中, 我们将学习SIFT算法的概念 我们将学习找到SIFT关键点和描述算符. 理论 在前两章中,我们看到了一些像Harris这样的拐角检测器.它们是旋转不变的,这意味着即使图像旋转了, ...
- OpenCV-Python 霍夫线变换 | 三十二
目标 在这一章当中, 我们将了解霍夫变换的概念. 我们将看到如何使用它来检测图像中的线条. 我们将看到以下函数:cv.HoughLines(),cv.HoughLinesP() 理论 如果可以用数学形 ...
- 使用Keras构建深度图像搜索引擎
动机 想象一下,如果有数十万到数百万张图像的数据集,却没有描述每张图像内容的元数据.我们如何建立一个系统,能够找到这些图像的子集来更好地回答用户的搜索查询? 我们基本上需要的是一个搜索引擎,它能够根据 ...
- rabbitmq++:rabbitmq 三种常用的交换机
更多 rabbitmq 介绍 首先先介绍一个简单的一个消息推送到接收的流程,提供一个简单的图: 黄色的圈圈就是我们的消息推送服务,将消息推送到 中间方框里面也就是 rabbitMq的服务器: 然后经过 ...
- coding++:Spring中的@Transactional(rollbackFor = Exception.class)属性详解
异常: 如下图所示,我们都知道 Exception 分为 运行时异常 RuntimeException 和 非运行时异常. error 是一定会回滚的. 如果不对运行时异常进行处理,那么出现运行时异常 ...
- LeetCode46 回溯算法求全排列,这次是真全排列
本文始发于个人公众号:TechFlow,原创不易,求个关注 今天是LeetCode的26篇文章,我们来实战一下全排列问题. 在之前的文章当中,我们讲过八皇后.回溯法,也提到了全排列,但是毕竟没有真正写 ...
- [noip模拟]数字对<RMQ&二分>
数字对 [题目描述] 小H是个善于思考的学生,现在她又在思考一个有关序列的问题. 她的面前浮现出一个长度为n的序列{ai},她想找出一段区间[L, R](1 <= L <= R <= ...
- Java 程序该怎么优化?(工具篇)
程序员:为什么程序总是那么慢?时间都花到哪里去了? 面试官:若你写的 Java 程序,出现了性能问题,该怎么去排查呢? 工欲善其事必先利其器,为你呈上一箩筐性能优化工具,必有一款满足你,废话不多说,直 ...
- JAVABEAN的SCOPE属性(转载)
对于JSP 程序而言,使用JavaBeans 组件不仅可以封装许多信息,而且还可以将一些 数据处理的逻辑隐藏到JavaBeans 的内部,除此之外,我们还可以设定JavaBeans 的Scope ...
- java文件中字母出现的次数和百分比
主要是文件的读写.先在代码中导入文件.一行一行的进行数据的读入,通过“ ”空格对读入的信息进行分割,存入到数组里之后对于每一个单词的每一个字母进行区分存入相应的字母数组里.最后统计总的字母个数.应用 ...