痞子衡嵌入式:简析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这颗划时代的 ...
随机推荐
- Python第五章-内置数据结构05-集合
Python内置数据结构 五.集合(set) python 还提供了另外一种数据类型:set. set用于包含一组无序的不重复对象.所以set中的元素有点像dict的key.这是set与 list的最 ...
- 在django中如何从零开始搭建一个mock服务
mock概念 mock 就是模拟接口返回的一系列数据,用自定义的数据替换接口实际需要返回的数据,通过自定义的数据来实现对下级接口模块的测试.这里分为两类测试:一类是前端对接口的mock,一类是后端单元 ...
- 粒子群优化算法(PSO)之基于离散化的特征选择(FS)(四)
作者:Geppetto 前面我们介绍了特征选择(Feature Selection,FS)与离散化数据的重要性,介绍了PSO在FS中的重要性和一些常用的方法.FS与离散化的背景,介绍了EPSO与PPS ...
- python文件调用方法
文件输入输出 open函数可以对文本文件进行读写的操作 基本形式: open(filename,mode) filename是文件名,可以写为绝对路径也可以是相对路径 mode是打开模式. open函 ...
- ajax的封装——jq简化版
最近在复习ajax的知识,练习了下ajax的封装,此处做下笔记 废话不多说,直接代码 //发请求 //此处的url为请求地址,type为请求方式,success为请求成功的回调函数 myaxios({ ...
- LFU五种实现方式,从简单到复杂
前言 最近刷力扣题,对于我这种 0 基础来说,真的是脑壳疼啊.这个月我估计都是中等和困难题,没有简单题了. 幸好,力扣上有各种大牛给写题解.看着他们行云流水的代码,真的是羡慕不已.让我印象最深刻的就是 ...
- Day19-apache
HTTPD(俗称apache) 简介:目前来说,Linuxweb服务器主要用apache与nginx. 1.web服务器的输入/输出结构: 单线程I/O结构 多线程I/O结构 复用的I/O结构,单个线 ...
- 解读windows认证
0x00 前言 dll劫持的近期忙,没时间写,先给大家写个windows认证的水文. 0x01 windows认证协议 windows上的认证大致分为本地认证,ntlm协议,和Kerberos协议. ...
- SVN同步代码问题集锦
1.删除文件后file missing警告 相关链接: http://blog.sina.com.cn/s/blog_63e26d560100ve00.htm ...
- 读者来信 | 如何判断HBase Major Compact是否执行完毕?(已解决)
前言:之前有朋友加好友与我探讨一些问题,我觉得这些问题倒挺有价值的:于是就想在本公众号开设一个问答专栏,方便技术交流与分享,专栏名就定为:<读者来信>.欢迎关注本人微信公众号<HBa ...