Source code interpretation and cross compilation of DDR stress testing tool memtester

Recently, for a product of the company, the DDR on the core board has been reduced from industrial grade to civilian use, and memory leaks are prone to occur during program operation. Therefore, the stress test of DDR is added to the product testing process.
The most popular open source tool memtester is used, but memtester has too many test cycles by default, and it takes more than 20 minutes to complete a stress test, which is not conducive to production testing, so the source code needs to be modified and recompiled.

1. Download the source code

Source code download address
insert image description here

2. Usage method and principleinsert image description here

3. Source code analysis

source file structure

\memtester-4.5.0
                \memtester.h
                \memtester.c        --主程序入口
                \sizes.h            --关于系统位数(32/64bit)的一些定义
                \types.h            --所用数据类型的定义
                \tests.h
                \tests.c            --测试算法子程序

Main program analysis

struct test {
    
    
    char *name;
    int (*fp)();
};
// 各个测试函数定义在tests.c中
struct test tests[] = {
    
    
    {
    
     "Random Value", test_random_value },
    {
    
     "Compare XOR", test_xor_comparison },
    {
    
     "Compare SUB", test_sub_comparison },
    {
    
     "Compare MUL", test_mul_comparison },
    {
    
     "Compare DIV",test_div_comparison },
    {
    
     "Compare OR", test_or_comparison },
    {
    
     "Compare AND", test_and_comparison },
    {
    
     "Sequential Increment", test_seqinc_comparison },
    {
    
     "Solid Bits", test_solidbits_comparison },
    {
    
     "Block Sequential", test_blockseq_comparison },
    {
    
     "Checkerboard", test_checkerboard_comparison },
    {
    
     "Bit Spread", test_bitspread_comparison },
    {
    
     "Bit Flip", test_bitflip_comparison },
    {
    
     "Walking Ones", test_walkbits1_comparison },
    {
    
     "Walking Zeroes", test_walkbits0_comparison },
#ifdef TEST_NARROW_WRITES    
    {
    
     "8-bit Writes", test_8bit_wide_random },
    {
    
     "16-bit Writes", test_16bit_wide_random },
#endif
    {
    
     NULL, NULL }
};

/* Function definitions */
void usage(char *me) {
    
    
    fprintf(stderr, "\n"
            "Usage: %s [-p physaddrbase [-d device]] <mem>[B|K|M|G] [loops]\n",
            me);
    exit(EXIT_FAIL_NONSTARTER);
}

int main(int argc, char **argv) {
    
    
    ul loops, loop, i;
    size_t bufsize, halflen, count;
    void volatile *buf, *aligned;
    ulv *bufa, *bufb;
    ul testmask = 0;

    // 省略若干变量定义代码

    printf("memtester version " __version__ " (%d-bit)\n", UL_LEN);
    printf("Copyright (C) 2001-2020 Charles Cazabon.\n");
    printf("Licensed under the GNU General Public License version 2 (only).\n");
    printf("\n");

    // 省略若干初始检查代码
    // 从输入参数里获取physaddrbase计算出内存测试起始地址aligned
    // 从输入参数里获取mem及B|K|M|G计算出内存测试总长度bufsize

    halflen = bufsize / 2;
    count = halflen / sizeof(ul);
    bufa = (ulv *) aligned;
    bufb = (ulv *) ((size_t) aligned + halflen);

    // 压力测试的重要变量, loops即重复次数
    for(loop=1; ((!loops) || loop <= loops); loop++) {
        printf("Loop %lu", loop);
        if (loops) {
            printf("/%lu", loops);
        }
        printf(":\n");
        printf("  %-20s: ", "Stuck Address");
        fflush(stdout);

        // 第一个测试 stuck_address
        if (!test_stuck_address(aligned, bufsize / sizeof(ul))) {
    
    
             printf("ok\n");
        } else {
    
    
            exit_code |= EXIT_FAIL_ADDRESSLINES;
        }

        // 遍历tests.c里的所有测试子程序
        for (i=0;;i++) {
    
    
            if (!tests[i].name) break;
            if (testmask && (!((1 << i) & testmask))) {
    
    
                continue;
            }
            printf("  %-20s: ", tests[i].name);
            // 可以看到将内存测试总空间一分为二,传给子程序做处理的
            if (!tests[i].fp(bufa, bufb, count)) {
    
    
                printf("ok\n");
            } else {
    
    
                exit_code |= EXIT_FAIL_OTHERTEST;
            }
            fflush(stdout);
            /* clear buffer */
            memset((void *) buf, 255, wantbytes);
        }
        printf("\n");
        fflush(stdout);
    }
}

4. Modify the source code

- count = halflen / sizeof(ul);
+ count = halflen / sizeof(ul) /4; //经过调试 将循环次数除以4得到合理的测试时间

5. Compile the source code

Modify the conf-cc file, change cc to arm-linux-gnueabihf-gcc and add -static (static compilation parameters)
as follows:

arm-linux-gnueabihf-gcc -static -O2 -DPOSIX -D_POSIX_C_SOURCE=200809L -D_FILE_OFFSET_BITS=64 -DTEST_NARROW_WRITES -c

Modify the conf-ld file, change cc to arm-linux-gnueabihf-gcc and add -static (static compilation parameters)
as follows:

arm-linux-gnueabihf-gcc -static -s

Execute make to compile the source code, and you can see that an executable file called memtester is generated.

Extension:
view makefile

CC			= $(shell head -n 1 conf-cc)
LD			= $(shell head -n 1 conf-ld)

You can see that after executing make, the compiler and linker information in the conf-cc conf-ld file is assigned to the variables CC and LD

Reference:
https://www.cnblogs.com/henjay724/archive/2021/03/25/14560706.html

Guess you like

Origin blog.csdn.net/weixin_44698673/article/details/128238798