大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家分享的是i.MXRT1170 XECC開(kāi)啟及Data Swap功能對(duì)于外部RAM的訪(fǎng)問(wèn)性能影響。
這篇文章里痞子衡給大家介紹了 XECC 原理及在其使能下操作 NOR Flash 步驟(尤其涉及對(duì) Flash 的 AHB 方式寫(xiě)),但文章里并沒(méi)有涉及性能方面的評(píng)估。我們知道 RT1170 上內(nèi)部 FlexRAM ECC 模塊使能后對(duì) TCM 訪(fǎng)問(wèn)性能幾乎無(wú)影響,那么 XECC 使能后對(duì)于掛在 FlexSPI/SEMC 接口上的外部 PSRAM/SDRAM 訪(fǎng)問(wèn)性能是否有影響呢?今天我們就來(lái)聊聊這個(gè)話(huà)題:
- Note:本文以 MIMXRT1170-EVKB (Rev.B) 板卡上掛在 SEMC 接口的 16bit SDRAM - W9825G6KH-5I 讀寫(xiě)測(cè)試為例,PSRAM 測(cè)試過(guò)程類(lèi)似。
一、XECC功能測(cè)試
測(cè)試 XECC 對(duì)于 SDRAM 訪(fǎng)問(wèn)保護(hù)功能我們可以直接使用如下兩個(gè)官方例程,其中 xecc_single_error 示例了單 bit 糾錯(cuò)(4bits數(shù)據(jù)單元而言),xecc_multi_error 示例了雙 bit 報(bào)錯(cuò)(4bits數(shù)據(jù)單元而言),這兩個(gè)例程都借助了 XECC 本身的 Error injection 特性人為制造數(shù)據(jù) bit 錯(cuò)誤來(lái)做測(cè)試(可以指定 32bits 數(shù)據(jù)塊中任意位置和個(gè)數(shù)的 bit 出錯(cuò))。
SDK_2_16_000_MIMXRT1170-EVKBboardsevkbmimxrt1170driver_examplesxeccsemcxecc_single_errorcm7
SDK_2_16_000_MIMXRT1170-EVKBboardsevkbmimxrt1170driver_examplesxeccsemcxecc_multi_errorcm7
痞子衡簡(jiǎn)單整合了上述兩個(gè)例程代碼到一個(gè)工程里,這樣可以同時(shí)測(cè)單/雙/多 bit 錯(cuò)誤情況,其中主要代碼摘錄如下。此外為了方便觀(guān)察不同的錯(cuò)誤注入導(dǎo)致的結(jié)果,我們將待寫(xiě)入值 sdram_writeBuffer[0] 設(shè)為 0x00000000,這樣發(fā)生無(wú)法糾錯(cuò)情況時(shí)讀回的數(shù)據(jù) sdram_readBuffer[0] 就應(yīng)該等于錯(cuò)誤注入值 errorData。
#include?"fsl_xecc.h"
volatile?uint32_t?sdram_writeBuffer[0x1000];
volatile?uint32_t?sdram_readBuffer[0x1000];
int?main(void)
{
????//?系統(tǒng)與?SDRAM?初始化代碼省略...
????//?初始化?XECC_SEMC?模塊,設(shè)置?SDRAM?[0x80000000,?0x8007FFFF]?為?ECC?使能區(qū)域,其中前?256KB?是用戶(hù)數(shù)據(jù)訪(fǎng)問(wèn)空間
????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);
????//?對(duì)?32bits?數(shù)據(jù)塊進(jìn)行錯(cuò)誤注入(這里設(shè)定得是錯(cuò)誤?bit?位置)
????uint32_t?errorData?=?0x00000001;
????XECC_ErrorInjection(XECC_SEMC,?errorData,?0);
????sdram_writeBuffer[0]?=?0x00000000U;
????//?AHB?方式寫(xiě)數(shù)據(jù)進(jìn)?SDRAM
????*(uint32_t?*)0x80000000U?=?sdram_writeBuffer[0];
????//?關(guān)閉?DCache?代碼省略...
????//?AHB?方式從?SDRAM?讀回?cái)?shù)據(jù)
????sdram_readBuffer[0]?=?*(uint32_t?*)0x80000000U;
????while?((!s_xecc_single_error)?&&?(!s_xecc_multi_error))
????{
????}
????//?代碼省略...
}
在放測(cè)試結(jié)果之前,我們先回顧一下 XECC 錯(cuò)誤檢測(cè)機(jī)制。在默認(rèn)不開(kāi)啟 Data Swap 特性情況下,對(duì)于 32bits 數(shù)據(jù)塊,XECC 可以糾正其中發(fā)生的 8bits 錯(cuò)誤,但前提是按序分割開(kāi)的每 4bits 數(shù)據(jù)單元僅能有 1bit 錯(cuò)誤(即分散 bit 錯(cuò)誤)。如果這 4bits 數(shù)據(jù)單元里有 2bit 錯(cuò)誤,那 XECC 會(huì)檢測(cè)出位置并報(bào)告;如果有 3/4bit 錯(cuò)誤,那已經(jīng)超出 XECC 處理能力,結(jié)果不可預(yù)期了。
但如果現(xiàn)場(chǎng)實(shí)際環(huán)境發(fā)生連續(xù) bit 錯(cuò)誤概率高于分散 bit 錯(cuò)誤,這時(shí)候可以考慮開(kāi)啟 XECC Data Swap 功能,這時(shí)候 XECC 處理能力變成可以糾正連續(xù) bit 錯(cuò)誤,但對(duì)于分散 bit 錯(cuò)誤就無(wú)法處理了(如下圖所示,實(shí)際上 Swap 是將圖左邊 32bits 原數(shù)據(jù)打亂再重新組合成圖右邊 32bits 新數(shù)據(jù))。
根據(jù)上面的理論,我們現(xiàn)在再來(lái)看測(cè)試結(jié)果,那就非常合理了,有些情況下開(kāi)啟 Data Swap 增強(qiáng)了糾檢錯(cuò)能力,有些情況下開(kāi)啟 Data Swap 卻減弱了原來(lái)的糾檢錯(cuò)能力。(注意,Error injection 設(shè)定的 errorData 是針對(duì) swap 之后的數(shù)據(jù) bit 序而言)
- Note:?jiǎn)?32bits 數(shù)據(jù)塊寫(xiě)讀測(cè)試時(shí),改動(dòng) L1 D-Cache 操作代碼位置(前移到 main 開(kāi)始),會(huì)影響測(cè)試結(jié)果,這里留一個(gè)伏筆,以后具體分析。
二、XECC性能測(cè)試
現(xiàn)在我們簡(jiǎn)單測(cè)試一下內(nèi)核對(duì) SDRAM 讀寫(xiě)性能是否受 XECC 影響,就在 semcxecc_multi_error 例程基礎(chǔ)之上,設(shè)計(jì)了如下代碼,便于測(cè)試不同的數(shù)據(jù)塊大?。ū热?64KB,128KB,256KB),而且可以一次性對(duì)比沒(méi)有 XECC 保護(hù),加 XECC 保護(hù),以及開(kāi)啟 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);
????//?寫(xiě)讀?SDRAM?非?XECC?保護(hù)區(qū)域
????uint32_t?normalTimeInUs?=?get_sdram_rw_block_time(0x80000000,?size);
????//?寫(xiě)讀?SDRAM?XECC?保護(hù)區(qū)域(不使能?Data?Swap)
????config.enableSwap?=?false;
????XECC_Init(XECC_SEMC,?&config);
????uint32_t?xeccNoSwapTimeInUs?=?get_sdram_rw_block_time(0x80040000,?size);
????//?寫(xiě)讀?SDRAM?XECC?保護(hù)區(qū)域(使能?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("---------------------------------------rn");
????PRINTF("Write/Read/Compare?data?size:?%drn",?size);
????PRINTF("Write/Read/Compare?time?in?SDRAM?region?XECC?disable?:?%d?usrn",?normalTimeInUs);
????PRINTF("Write/Read/Compare?time?in?SDRAM?region?XECC?enable?without?data?swap?:?%d?usrn",?xeccNoSwapTimeInUs);
????PRINTF("Write/Read/Compare?time?in?SDRAM?region?XECC?enable?with?data?swap?:?%d?usrn",?xeccSwapTimeInUs);
}
get_sdram_rw_block_time() 函數(shù)里實(shí)際上也統(tǒng)計(jì)了數(shù)據(jù)出錯(cuò)情況,可用于輔助判斷寫(xiě)讀是否正常,在恩智浦開(kāi)發(fā)板測(cè)試環(huán)境下應(yīng)該無(wú) ECC 錯(cuò)誤,所以這里結(jié)果就略去不表了。
我們現(xiàn)在來(lái)看 800MHz 內(nèi)核主頻下對(duì) 200MHz SDRAM 訪(fǎng)問(wèn)性能情況(代碼跑在 ITCM 上),為了結(jié)果可靠,本次測(cè)試內(nèi)核頻率沒(méi)有設(shè)到最高。根據(jù)代碼打印結(jié)果,我們能得到如下結(jié)論:
結(jié)論1:在無(wú) XECC 保護(hù)情況下,開(kāi)啟 D-Cache 能將 SDRAM 讀寫(xiě)整體訪(fǎng)問(wèn)速度提升到 4 倍。
結(jié)論2:XECC 使能情況下,是否開(kāi)啟 Data Swap 功能幾乎不帶來(lái)性能變化(在 XECC 外設(shè)里 Swap 操作一拍時(shí)鐘就能完成,時(shí)延可以忽略)。
結(jié)論3:XECC 使能情況下,會(huì)降低 SDRAM 讀寫(xiě)整體訪(fǎng)問(wèn)性能,降幅在 28% (開(kāi)啟 D-Cache) 或 11%(不開(kāi)啟 D-Cache)。
結(jié)論4:XECC 使能情況下,對(duì)于讀寫(xiě)訪(fǎng)問(wèn)同樣大小數(shù)據(jù)塊,是否開(kāi)啟 D-Cache,不影響 XECC 校驗(yàn)處理的時(shí)間(即 D-Cache 不加速 XECC)。
至此,i.MXRT1170 XECC開(kāi)啟及Data Swap功能對(duì)于外部RAM的訪(fǎng)問(wèn)性能影響痞子衡便介紹完畢了,掌聲在哪里~~~