大家好,我是痞子衡,是正經(jīng)搞技術(shù)的痞子。今天痞子衡給大家介紹的是在i.MXRT1060-EVK上利用memtester程序給SDRAM做壓力測(cè)試。
我們知道恩智浦i.MXRT1xxx系列是高性能MCU的代表,對(duì)于這個(gè)超高主頻(>=500MHz)的怪獸,不做點(diǎn)人機(jī)交互圖形顯示或者跑點(diǎn)算法方面的高階應(yīng)用實(shí)在有點(diǎn)浪費(fèi)它的能力,高階應(yīng)用往往需要大容量緩存(RAM),i.MXRT1xxx系列內(nèi)部RAM最大也就1-2MB,不是特別寬裕,因此我們?cè)诎寮?jí)設(shè)計(jì)時(shí)往往會(huì)為i.MXRT1xxx再搭配一塊外部RAM。外部RAM的種類選擇很多,可通過FlexSPI外設(shè)掛HyperRAM/PSRAM或者通過SEMC外設(shè)掛SDRAM/SRAM,其中SDRAM是最常見的選擇,官方EVK上默認(rèn)也是選了SDRAM。
有了外部SDRAM雖然解決了系統(tǒng)緩存容量危機(jī),但也同時(shí)可能引入潛在的系統(tǒng)穩(wěn)定性問題,畢竟SDRAM是外部器件,容易受干擾(比如PCB走線或者環(huán)境溫度等),如果SDRAM的讀寫訪問不可靠,那么系統(tǒng)就會(huì)有不可預(yù)知的奇怪問題發(fā)生,因此我們需要在板子出廠時(shí)對(duì)SDRAM做一次壓力測(cè)試(既測(cè)試了SDRAM芯片和PCB設(shè)計(jì),也測(cè)試了對(duì)應(yīng)的SEMC外設(shè)配置),今天痞子衡就選用memtester程序給SDRAM上一次強(qiáng)度。
關(guān)于memtester程序的基本知識(shí),痞子衡之前專門寫過一篇文章 《內(nèi)存讀寫正確性壓力測(cè)試程序(memtester)》 ,本篇就是基于了解memtester基本知識(shí)之后的一次實(shí)踐。來,讓我們開始吧。
一、準(zhǔn)備工作
1.1 硬件平臺(tái)NXP i.MX RT1060 EVK
要開始給SDRAM做壓力測(cè)試,首先你得有一塊開發(fā)板,恩智浦官網(wǎng)上有i.MXRT1060評(píng)估板,板載SDRAM芯片型號(hào)為鎂光的MT48LC16M16A2,我們今天就來測(cè)試它。
1.2 集成開發(fā)環(huán)境IAR EWARM
ARM Cortex-M微控制器的集成開發(fā)環(huán)境有很多,其中IAR EWARM憑借優(yōu)良的特性備受廣大工程師青睞,今天痞子衡就選用IAR作為軟件環(huán)境,具體版本為IAR EWARM v8.50.6。
1.3 官方軟件開發(fā)包NXP MCUXpresso SDK
在開始移植memtester程序到i.MXRT1062上之前,我們需要先有一個(gè)i.MXRT1062的基本hello world的例程,當(dāng)然我們可以對(duì)著數(shù)據(jù)手冊(cè)自己從頭寫一個(gè),但是這里痞子衡推薦使用官方軟件開發(fā)包。
注冊(cè)并登錄恩智浦官網(wǎng),來到 MCUXpresso SDK Builder 頁面,在"Select Development Board"里選擇EVK-MIMXRT1060后點(diǎn)擊Build MCUXpresso SDK后跳轉(zhuǎn)到下一個(gè)頁面,點(diǎn)擊Download SDK后便可得到SDK_2.9.1_EVK-MIMXRT1060.zip,下面是痞子衡下載的開發(fā)包具體版本信息:
二、開始實(shí)測(cè)
2.1 跑通hello world
給i.MXRT1060 EVK板子供電(J2口接5V輸出的電源),并且使用USB線連接電腦與板子的J41 USB口,此時(shí)在設(shè)備管理器應(yīng)該可以看到USB虛擬的串口(EVK板載LPC-LINK2調(diào)試器內(nèi)含USB轉(zhuǎn)串口功能,如果看不到串口,請(qǐng)自行安裝LPC-LINK2驅(qū)動(dòng))。
打開前一步下載的開發(fā)包里的SDK_2.9.1_EVK-MIMXRT1060boardsevkimxrt1060demo_appshello_worldiarhello_world.eww工程,確認(rèn)工程option里linker文件選擇的是MIMXRT1062xxxxx_ram.icf,然后J21 JTAG口連接上Jlink Plus直接將工程下載進(jìn)主芯片的RAM運(yùn)行。
如果工程運(yùn)行正常,你在串口調(diào)試助手(115200,8N1)里應(yīng)該能看到"hello world."打印輸出。
2.2 移植memtester程序
以hello_world工程為基礎(chǔ),將從官方網(wǎng)站下載到的memtester-4.5.0.tar包解壓,將memtester-4.5.0路徑下的如下源文件(.c或.h)全部拷貝到hello world工程目錄下:
memtester-4.5.0
memtester.h
memtester.c --主程序入口
sizes.h --關(guān)于系統(tǒng)位數(shù)(32/64bit)的一些定義
types.h --所用數(shù)據(jù)類型的定義
tests.h
tests.c --測(cè)試算法子程序
將上面所有memtester源文件全部添加進(jìn)hello_world工程并將工程更名為memtester,然后再將工程中原主函數(shù)入口文件hello_world.c更名為main.c,此時(shí)基本memtester工程就完成了。但注意此時(shí)工程無法編譯,因?yàn)閙emtester源文件還需要進(jìn)一步修改。
2.2.1 適配嵌入式平臺(tái)
我們下載的memtester源碼本用作在Unix-like系統(tǒng)上運(yùn)行的,所以源碼里面有一些僅適用于Unix-like系統(tǒng)上運(yùn)行的代碼,需要將這些代碼全部刪除以適合在嵌入式平臺(tái)運(yùn)行。
關(guān)于頭文件引用部分,需要?jiǎng)h除memtester.c和tests.c文件里的一些不適用的#include語句,改用SDK里的標(biāo)準(zhǔn)頭:
// 下述Unix系統(tǒng)頭需刪除
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// 下述SDK標(biāo)準(zhǔn)頭需添加
#include "fsl_common.h"
#include "fsl_debug_console.h"
整個(gè)memtester源碼其實(shí)最主要(唯一)的改動(dòng)就是memtester.c里的原main()函數(shù),本來main函數(shù)是接受控制臺(tái)傳來的用戶選項(xiàng)完成解析獲取必要的參數(shù)(內(nèi)存起始地址,測(cè)試長(zhǎng)度,壓力測(cè)試循環(huán)次數(shù)),然后運(yùn)行tests.c里各種算法子程序。我們需要做的就是將main函數(shù)里代碼各種刪減,把不適用于MCU上運(yùn)行的代碼全部拿掉,并且將main函數(shù)原型改為如下:
/*******************************************************************************
* Input parameters:
* ---- phystestbase : memory base address
* ---- wantraw : memory size
* ---- memsuffix : memory unit, B,K,M,G for B, KB, MB, GB
* ---- loop : memory test code loop times
* ---- pagesize : memory pase size (Bytes)
*/
int memtester_main(ul phystestbase, ul wantraw, char *memsuffix, ul loops, ul pagesize)
{}
最后memtester_main里跑tests.c里具體算法子程序時(shí),如果遇到失敗的情況,默認(rèn)是繼續(xù)執(zhí)行下一個(gè)算法子程序,我們可以加一個(gè)fail_stop控制變量,決定遇到失敗是直接結(jié)束整個(gè)測(cè)試還是繼續(xù)往下跑。
2.2.2 板級(jí)初始化
上一節(jié)里已經(jīng)將memtester.c里面的main()函數(shù)改成了memtester_main(),所以我們直接在原h(huán)ello_world.c改成的main.c里的main函數(shù)中增加memtester_main()的調(diào)用即可,注意按需設(shè)置測(cè)試參數(shù)(下述代碼里的設(shè)置就是一個(gè)示例,測(cè)試0x8000_0000地址開始的64KB內(nèi)存,循環(huán)一次即可)。此外Cache是否使能對(duì)測(cè)試影響很大,建議關(guān)掉DCache測(cè)試。
typedef struct _semc_test_config {
uint32_t baseAddr;
uint32_t testSize;
uint32_t loopNum;
uint32_t dramFreq;
uint32_t enableCache;
} semc_test_config_t;
int fail_stop = 1;
int main(void)
{
char memsuffix = 'B';
/* Init board hardware. */
BOARD_InitHardware();
/* --------------- stress test --------------- */
semc_test_config_t testConfig;
testConfig.baseAddr = 0x80000000;
testConfig.testSize = 64 * 1024;
testConfig.loopNum = 1;
testConfig.dramFreq = CLOCK_GetFreq(kCLOCK_SemcClk);
testConfig.enableCache = 0;
if (!testConfig.enableCache) {
/* Disable D cache */
SCB_DisableDCache();
}
PRINTF("rn########## Print out from target board ##########rn");
PRINTF("rnSDRAM r/w test settings:rn");
PRINTF(" Base Addr: 0x%x;rn", testConfig.baseAddr);
PRINTF(" Test Size: %d Bytes;rn", testConfig.testSize);
PRINTF(" Test Loop: %d;rn", testConfig.loopNum);
PRINTF(" SDRAM Freq: %d Hz;rn",testConfig.dramFreq);
PRINTF(" Enable Cache: %d;rnrn", testConfig.enableCache);
/* Run memory stress test: 64KByte, loop=1, page_size = 1kbyte */
memtester_main(testConfig.baseAddr, testConfig.testSize, &memsuffix, testConfig.loopNum, (1*1024));
while (1)
{
}
}
2.2.3 串口打印功能
串口打印功能的改動(dòng)比較簡(jiǎn)單,直接把原memtester.c和tests.c文件里的fprintf()全部替換成PRINTF()即可,PRINTF函數(shù)在原h(huán)ello world工程里已經(jīng)實(shí)現(xiàn)了。
2.3 memtester參數(shù)配置
痞子衡在memtester程序的基本知識(shí)介紹里說過,memtester幾乎沒有參數(shù)配置,就是需要在sizes.h文件里把如下兩個(gè)宏加進(jìn)去:
#define ULONG_MAX (4294967295UL)
#define TEST_NARROW_WRITES
2.4 輸出memtester結(jié)果
到這里memtester的移植工作就完全結(jié)束了,此時(shí)memtester工程(代碼和變量都鏈接在TCM里)也應(yīng)該能正常編譯了。你可能會(huì)疑問,SEMC外設(shè)的初始化代碼在哪里啊?別急,工程選項(xiàng)調(diào)試器設(shè)置里提供了兩種SDRAM初始化腳本,我們隨便選用一種即可:
另外需要注意的是,在工程預(yù)編譯選項(xiàng)里需要加上SKIP_SYSCLK_INIT宏,因?yàn)楣こ虝r(shí)鐘初始化函數(shù)BOARD_BootClockRUN()會(huì)根據(jù)這個(gè)宏來決定要不要重配SEMC,我們已經(jīng)有SDRAM初始化腳本了,不需要在工程里再配SEMC時(shí)鐘了。
現(xiàn)在還等什么?將memtester工程趕緊下載進(jìn)芯片并打開串口調(diào)試助手看memtester結(jié)果啊。痞子衡為了盡快得到結(jié)果,僅測(cè)試了64KB的空間,按說應(yīng)該測(cè)試全部32MB空間才對(duì),但這個(gè)測(cè)試時(shí)間是很漫長(zhǎng)的,如果循環(huán)次數(shù)loopNum大于1,那等待時(shí)間就更長(zhǎng)了。如果測(cè)試中遇到了失敗,除了要檢查板級(jí)硬件外,還可以調(diào)整SDRAM初始化腳本里的配置再次測(cè)試,直至通過壓力測(cè)試。
想偷懶的朋友直接移步痞子衡的github https://github.com/JayHeng/cortex-m-apps 去下載移植好的工程,工程在cortex-m-appsappsmemtester_imxrt1062bsp下面。
至此,在i.MXRT1060-EVK上利用memtester程序給SDRAM做壓力測(cè)試痞子衡便介紹完畢了,掌聲在哪里~~~