加入星計(jì)劃,您可以享受以下權(quán)益:

  • 創(chuàng)作內(nèi)容快速變現(xiàn)
  • 行業(yè)影響力擴(kuò)散
  • 作品版權(quán)保護(hù)
  • 300W+ 專業(yè)用戶
  • 1.5W+ 優(yōu)質(zhì)創(chuàng)作者
  • 5000+ 長(zhǎng)期合作伙伴
立即加入
  • 正文
  • 相關(guān)推薦
  • 電子產(chǎn)業(yè)圖譜
申請(qǐng)入駐 產(chǎn)業(yè)圖譜

如何優(yōu)雅地給板載SDRAM芯片上強(qiáng)度?

2021/03/22
334
閱讀需 19 分鐘
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

大家好,我是痞子衡,是正經(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è)試痞子衡便介紹完畢了,掌聲在哪里~~~

相關(guān)推薦

電子產(chǎn)業(yè)圖譜

碩士畢業(yè)于蘇州大學(xué)電子信息學(xué)院,目前就職于恩智浦(NXP)半導(dǎo)體MCU系統(tǒng)部門,擔(dān)任嵌入式系統(tǒng)應(yīng)用工程師。痞子衡會(huì)定期分享嵌入式相關(guān)文章