大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是i.MXRT1170 XECC开启及Data Swap功能对于外部RAM的访问性能影响

  文接上篇 《i.MXRT1170 XECC功能特点及其保护串行NOR Flash和SDRAM之道》,这篇文章里痞子衡给大家介绍了 XECC 原理及在其使能下操作 NOR Flash 步骤(尤其涉及对 Flash 的 AHB 方式写),但文章里并没有涉及性能方面的评估。我们知道 RT1170 上内部 FlexRAM ECC 模块使能后对 TCM 访问性能几乎无影响,那么 XECC 使能后对于挂在 FlexSPI/SEMC 接口上的外部 PSRAM/SDRAM 访问性能是否有影响呢?今天我们就来聊聊这个话题:

  • Note:本文以 MIMXRT1170-EVKB (Rev.B) 板卡上挂在 SEMC 接口的 16bit SDRAM - W9825G6KH-5I 读写测试为例,PSRAM 测试过程类似。

一、XECC功能测试

  测试 XECC 对于 SDRAM 访问保护功能我们可以直接使用如下两个官方例程,其中 xecc_single_error 示例了单 bit 纠错(4bits数据单元而言),xecc_multi_error 示例了双 bit 报错(4bits数据单元而言),这两个例程都借助了 XECC 本身的 Error injection 特性人为制造数据 bit 错误来做测试(可以指定 32bits 数据块中任意位置和个数的 bit 出错)。

\SDK_2_16_000_MIMXRT1170-EVKB\boards\evkbmimxrt1170\driver_examples\xecc\semc\xecc_single_error\cm7
\SDK_2_16_000_MIMXRT1170-EVKB\boards\evkbmimxrt1170\driver_examples\xecc\semc\xecc_multi_error\cm7

  痞子衡简单整合了上述两个例程代码到一个工程里,这样可以同时测单/双/多 bit 错误情况,其中主要代码摘录如下。此外为了方便观察不同的错误注入导致的结果,我们将待写入值 sdram_writeBuffer[0] 设为 0x00000000,这样发生无法纠错情况时读回的数据 sdram_readBuffer[0] 就应该等于错误注入值 errorData。

#include "fsl_xecc.h"
volatile uint32_t sdram_writeBuffer[0x1000];
volatile uint32_t sdram_readBuffer[0x1000];
int main(void)
{
// 系统与 SDRAM 初始化代码省略...
// 初始化 XECC_SEMC 模块,设置 SDRAM [0x80000000, 0x8007FFFF] 为 ECC 使能区域,其中前 256KB 是用户数据访问空间
XECC_Deinit(XECC_SEMC);
xecc_config_t config;
XECC_GetDefaultConfig(&config);
config.enableXECC = true;
config.enableWriteECC = true;
config.enableReadECC = true;
//config.enableSwap = true;
config.Region0BaseAddress = 0x80000000U;
config.Region0EndAddress = 0x80080000U; // 256KB * 2
XECC_Init(XECC_SEMC, &config);
(void)EnableIRQ(XECC_SEMC_INT_IRQn);
(void)EnableIRQ(XECC_SEMC_FATAL_INT_IRQn);
SCB->SHCSR |= SCB_SHCSR_BUSFAULTENA_Msk;
XECC_EnableInterrupts(XECC_SEMC, kXECC_AllInterruptsEnable); // 对 32bits 数据块进行错误注入(这里设定得是错误 bit 位置)
uint32_t errorData = 0x00000001;
XECC_ErrorInjection(XECC_SEMC, errorData, 0);
sdram_writeBuffer[0] = 0x00000000U; // AHB 方式写数据进 SDRAM
*(uint32_t *)0x80000000U = sdram_writeBuffer[0];
// 关闭 DCache 代码省略...
// AHB 方式从 SDRAM 读回数据
sdram_readBuffer[0] = *(uint32_t *)0x80000000U;
while ((!s_xecc_single_error) && (!s_xecc_multi_error))
{
}
// 代码省略...
}

  在放测试结果之前,我们先回顾一下 XECC 错误检测机制。在默认不开启 Data Swap 特性情况下,对于 32bits 数据块,XECC 可以纠正其中发生的 8bits 错误,但前提是按序分割开的每 4bits 数据单元仅能有 1bit 错误(即分散 bit 错误)。如果这 4bits 数据单元里有 2bit 错误,那 XECC 会检测出位置并报告;如果有 3/4bit 错误,那已经超出 XECC 处理能力,结果不可预期了。

  但如果现场实际环境发生连续 bit 错误概率高于分散 bit 错误,这时候可以考虑开启 XECC Data Swap 功能,这时候 XECC 处理能力变成可以纠正连续 bit 错误,但对于分散 bit 错误就无法处理了(如下图所示,实际上 Swap 是将图左边 32bits 原数据打乱再重新组合成图右边 32bits 新数据)。

  根据上面的理论,我们现在再来看测试结果,那就非常合理了,有些情况下开启 Data Swap 增强了纠检错能力,有些情况下开启 Data Swap 却减弱了原来的纠检错能力。(注意,Error injection 设定的 errorData 是针对 swap 之后的数据 bit 序而言)

  • Note:单 32bits 数据块写读测试时,改动 L1 D-Cache 操作代码位置(前移到 main 开始),会影响测试结果,这里留一个伏笔,以后具体分析。
config.enableSwap errorData sdram_writeBuffer[0] sdram_readBuffer[0] 测试结果
false/true 0x00000001 0x00000000 0x00000000 bit0错误被纠正
false/true 0x11111111 0x00000000 0x00000000 bit0,4,8,12,16,20,24,28错误被纠正
false 0x08040201 0x00000000 0x00000000 bit0,9,18,27错误被纠正
ture 0x08040201 0x00000000 0x00000000 (原性能增强)bit0,2,17,19错误被纠正
false 0x02040801 0x00000000 0x00000000 bit0,11,18,25错误被纠正
ture 0x02040801 0x00000000 0x00000000 (原性能增强)bit0,1,2,3错误被纠正
false 0x00000003 0x00000000 0x00000003 bit0,1错误被检测
true 0x00000003 0x00000000 0x00000201 (原性能减弱)bit0,9错误被检测
false 0x00000007 0x00000000 0x00000007 触发单bit纠错中断,出错bit0,1,2位置识别不准
true 0x00000007 0x00000000 0x00040201 触发单bit纠错中断,(原性能减弱)出错bit0,9,18位置识别不准
false 0x0000000F 0x00000000 0x0000000F 触发双bit检错中断,出错bit0,1,2,3位置识别不准
true 0x0000000F 0x00000000 0x08040201 触发双bit检错中断,(原性能减弱)出错bit0,9,18,27位置识别不准

二、XECC性能测试

  现在我们简单测试一下内核对 SDRAM 读写性能是否受 XECC 影响,就在 \semc\xecc_multi_error 例程基础之上,设计了如下代码,便于测试不同的数据块大小(比如 64KB,128KB,256KB),而且可以一次性对比没有 XECC 保护,加 XECC 保护,以及开启 XECC Data Swap 三种情况(中途需要 Deinit 再 Init XECC 模块)。

uint32_t readErrorCnt = 0;
uint32_t get_sdram_rw_block_time(uint32_t start, uint32_t size)
{
uint64_t tickStart = life_timer_clock();
readErrorCnt = 0;
for (uint32_t idx = 0; idx < size; idx += 4)
{
*((uint32_t*)(start + idx)) = idx;
}
for (uint32_t idx = 0; idx < size; idx += 4)
{
uint32_t temp = *((uint32_t*)(start + idx));
if (temp != idx)
{
readErrorCnt++;
}
}
uint64_t tickEnd = life_timer_clock();
return ((tickEnd - tickStart) / (CLOCK_GetRootClockFreq(kCLOCK_Root_Bus) / 1000000));
} void test_xecc_sdram_perf(uint32_t size)
{
xecc_config_t config;
XECC_GetDefaultConfig(&config);
config.enableXECC = true;
config.enableWriteECC = true;
config.enableReadECC = true;
config.Region0BaseAddress = 0x80040000;
config.Region0EndAddress = 0x800C0000;
XECC_Deinit(EXAMPLE_XECC);
// 写读 SDRAM 非 XECC 保护区域
uint32_t normalTimeInUs = get_sdram_rw_block_time(0x80000000, size);
// 写读 SDRAM XECC 保护区域(不使能 Data Swap)
config.enableSwap = false;
XECC_Init(XECC_SEMC, &config);
uint32_t xeccNoSwapTimeInUs = get_sdram_rw_block_time(0x80040000, size);
// 写读 SDRAM XECC 保护区域(使能 Data Swap)
XECC_Deinit(XECC_SEMC);
config.enableSwap = true;
XECC_Init(XECC_SEMC, &config);
uint32_t xeccSwapTimeInUs = get_sdram_rw_block_time(0x80040000, size); PRINTF("---------------------------------------\r\n");
PRINTF("Write/Read/Compare data size: %d\r\n", size);
PRINTF("Write/Read/Compare time in SDRAM region XECC disable : %d us\r\n", normalTimeInUs);
PRINTF("Write/Read/Compare time in SDRAM region XECC enable without data swap : %d us\r\n", xeccNoSwapTimeInUs);
PRINTF("Write/Read/Compare time in SDRAM region XECC enable with data swap : %d us\r\n", xeccSwapTimeInUs);
}

  get_sdram_rw_block_time() 函数里实际上也统计了数据出错情况,可用于辅助判断写读是否正常,在恩智浦开发板测试环境下应该无 ECC 错误,所以这里结果就略去不表了。

  我们现在来看 800MHz 内核主频下对 200MHz SDRAM 访问性能情况(代码跑在 ITCM 上),为了结果可靠,本次测试内核频率没有设到最高。根据代码打印结果,我们能得到如下结论:

  • 结论1:在无 XECC 保护情况下,开启 D-Cache 能将 SDRAM 读写整体访问速度提升到 4 倍。
  • 结论2:XECC 使能情况下,是否开启 Data Swap 功能几乎不带来性能变化(在 XECC 外设里 Swap 操作一拍时钟就能完成,时延可以忽略)。
  • 结论3:XECC 使能情况下,会降低 SDRAM 读写整体访问性能,降幅在 28% (开启 D-Cache) 或 11%(不开启 D-Cache)。
  • 结论4:XECC 使能情况下,对于读写访问同样大小数据块,是否开启 D-Cache,不影响 XECC 校验处理的时间(即 D-Cache 不加速 XECC)。

  至此,i.MXRT1170 XECC开启及Data Swap功能对于外部RAM的访问性能影响痞子衡便介绍完毕了,掌声在哪里~~~

欢迎订阅

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

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

痞子衡嵌入式:简析i.MXRT1170 XECC开启及Data Swap功能对于外部RAM的访问性能影响的更多相关文章

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

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

  2. 痞子衡嵌入式:揭秘i.MXRT1170 eFuse空间访问可靠性的保护策略(冗余与ECC)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是恩智浦i.MXRT1170的eFuse空间访问可靠性保护策略. 关于i.MXRT系列的eFuse/OTP,痞子衡之前在介绍Boot时写过 ...

  3. 痞子衡嵌入式:在i.MXRT1170上启动含DQS的Octal Flash可不严格设Dummy Cycle (以MT35XU512为例)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是Octal或Hyper Flash上DQS信号与Dummy Cycle联系. 关于在 i.MXRT 上启动 NOR Flash 时如何设 ...

  4. 痞子衡嵌入式:揭秘i.MXRT1170上用J-Link连接复位后PC总是停在0x223104的原因

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1170上安全调试策略实现对JLink调试的影响. 痞子衡之前写过一篇旧文 <i.MXRT600的ISP模式下用J-L ...

  5. 痞子衡嵌入式:揭秘i.MXRT1170上串行NOR Flash双程序可交替启动设计

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1170上串行NOR Flash双程序可交替启动设计. 在上一篇文章 <i.MXRT1060/1010上串行NOR F ...

  6. 痞子衡嵌入式:聊聊i.MXRT1170双核下不同GPIO组的访问以及中断设计

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1170双核下不同GPIO组的访问以及中断设计. 在双核 i.MXRT1170 下设计应用程序,有一个比较重要的考虑点就是外 ...

  7. 痞子衡嵌入式:浅谈i.MXRT1xxx系列MCU时钟相关功能引脚的作用

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1xxx系列MCU时钟相关功能引脚作用. 如果我们从一颗 MCU 芯片的引脚分类来看芯片功能,大概可以分为三大类:电源.时钟 ...

  8. 痞子衡嵌入式:利用i.MXRT1xxx系列ROM集成的DCD功能可轻松配置指定外设

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是利用i.MXRT1xxx系列ROM集成的DCD功能可轻松配置指定外设. 关于 i.MXRT1xxx 系列芯片 BootROM 中集成的 ...

  9. 痞子衡嵌入式:飞思卡尔i.MX RTyyyy系列MCU特性那些事(2)- RT1052DVL6性能实测(CoreMark)

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是飞思卡尔i.MX RTyyyy系列MCU的性能. 在前面的文章 i.MXRTyyyy微控制器概览 里,痞子衡给大家简介过恩智浦半导体在2 ...

  10. 痞子衡嵌入式:在串口波特率识别实例里逐步展示i.MXRT上提升代码执行性能的十八般武艺

    大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是在串口波特率识别实例里逐步展示i.MXRT上提升代码执行性能的十八般武艺. 恩智浦 MCU SE 团队近期一直在加班加点赶 SBL 项目 ...

随机推荐

  1. CSS – W3Schools 学习笔记 (3)

    CSS Rounded Corners Link to W3Schools 它是用来画圆角的, 假设有 1 给正方形, 100px. border-top-left-radius: 30px; bef ...

  2. USB LFPS是什么?

    USB LFPS:低功耗状态下的高速数据传输 什么是USB LFPS? USB LFPS(Low-Power Signaling)指的是USB接口在低功耗状态下的一种高速数据传输技术.传统上,USB接 ...

  3. Java日期时间API系列16-----Jdk8中java.time包中的新的日期时间API类,java日期计算3,日期中年月日时分秒的属性值修改等

    通过Java日期时间API系列8-----Jdk8中java.time包中的新的日期时间API类的LocalDate源码分析 ,可以看出java8设计非常好,实现接口Temporal, Tempora ...

  4. 银河麒麟、中标麒麟学习实操资料汇总(含V4、V7、V10)

    数据库和操作系统关系十分密切,因为数据库是运行于操作系统上的一个管理数据的应用.在数据库国产化替代的浪潮之下,一批批国产操作系统也崭露头角.墨天轮社区便选取了中国操作系统排行榜上排名靠前的麒麟软件,依 ...

  5. DOM 操作的常用 API 有哪些 ?

    DOM 操作的常用 API 就是DOM 通过API (接口)获取页面(html)元素: 1. 节点查询 API 1.1 document.querySelector()  选择第一个匹配的元素 1.2 ...

  6. NVM使用说明

    下载:https://github.com/coreybutler/nvm-windows/releases 切换镜像源:  settting.txt文件后面添加 node_mirror: https ...

  7. KubeSphere 社区双周报|2024.09.27-10.10

    KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书.新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列 ...

  8. 云原生爱好者周刊:Grafana 开源 Prometheus 长期存储项目 Mimir

    开源项目推荐 Grafana Mimir Grafana Mimir 是 Grafana Labs 新开源的项目,用来为 Prometheus 提供持久化存储,开源许可协议是 AGPL-3.0.此前 ...

  9. 详解 JuiceFS 在多云架构下的数据同步与一致性

    随着大模型流行,GPU 算力资源正变得日益稀缺,传统的"算力跟着存储跑"的策略需要转变为"存储跟着算力跑".为了确保数据一致性和管理的便捷性,企业通常在特定地区 ...

  10. 一文彻底弄懂MySQL的优化

    在企业级 Web 开发中,MySQL 优化是至关重要的,它直接影响系统的响应速度.可扩展性和整体性能.下面从不同角度,列出详细的 MySQL 优化技巧,涵盖查询优化.索引设计.表结构设计.配置调整等方 ...