大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家分享的是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主頁、知乎主頁、微信公眾號 平臺上。
微信搜尋"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。