SD EMMC Stress Test SOP


REVISION HISTORY

Revision No.
Description
Date
1.0
  • Initial release
  • 04/15/2025

    1. SD EMMC压力测试介绍

    1.1. 概述

    本文用于指导在SOC emmc boot下对sd/emmc存储进行读写以及擦除的压力测试,主要是通过fio工具及相关的测试接口来对sd/emmc进行读写及擦除测试,并希望以此能够暴露出sd/emmc潜在的问题,判断sd/emmc的健康情况。

    1.2. 测试前环境准备

    注:Linux emmc boot环境默认已经打开了emmc drivers。

    1.2.1. Kernel driver

    测试前需要确保内核支持emmc driver。

    1. make menuconfig
    2. # Device Drivers -->
    3. #    <*> MMC/SD/SDIO card support -->                   (mmc_core.ko)
    4. #        <*> MMC block device driver                    (mmc_block.ko)
    5. #    [*] SStar SoC platform drivers -->
    6. #        <*> SStar SD/MMC Card Interface Support        (kdrv_sdmmc.ko)
    7. #        [ ]     Support SD30
    8. #        [*]     Support EMMC50
    9. #        [*]     Support SDMMC Command
    10.#        [*]       Support SDMMC UT verify
    11.#        [*]     SELECT EMMC
    

    1.2.2. 开发板环境

    1. 命令检查

      测试需要使用到fio工具,fio的github下载地址:https://github.com/axboe/fio, 请客户根据自己平台编译。

    2. 驱动检查

      按照1.2.1描述的打开驱动并升级后,检查开发板SD和EMMC对应的块设备文件(/dev/mmcblk0或/dev/mmcblk1),进入/sys/class/mmc_host/mmc0/device/目录后检查eMMC_erase测试接口文件(不测试emmc擦除则不用这个文件)是否存在,不存在需要在编译代码前后检查内核相关选项是否开启。

    3. 测试分区

      若需要进行emmc擦除测试,建议单独创建分区进行测试。

      新建分区方式:

      测试者可以在uboot下可以使用emmc create命令创建测试分区,例:

      emmc create test1 0x82900000 //创建一个大小为2G,名称为test1的emmc分区
      

      使用mmc part查看新建的分区:

      可以看到分区test1的分区号为7,在kernel下对应的测试分区文件为/dev/mmcblk0p7

    1.3. FIO读写测试

    测试前挂载需要测试的分区。以SD为例,若SD卡的块设备文件为/dev/mmcblk1,可通过以下方式挂载:

    mkfs.fat /dev/mmcblk1     //以fat文件系统格式化SD卡
    
    mount /dev/mmcblk1 /mnt/   //挂载SD卡到/mnt/目录
    

    使用FIO工具对sd/emmc进行读写测试,包含顺序写、顺序读、随机写和随机读四种方式。测试前在所测试的分区中创建测试文件(如emmc_test),注意使用FIO进行测试时,分区所预留的空间需要大于设置的读写数据量,建议测试的数据量大小大于1G。

    参数bs和size可根据用户需求自行设置,其它参数按下面指定即可。

    1.3.1. FIO参数说明

    filename=/mnt/emmc_test    #测试文件名称(填绝对路径)。
    direct=1        #是否使用directIO,测试过程绕过系统自带的buffer。
    rw=randread     #测试随机读的I/O
    rw=randwrite    #测试随机写的I/O
    rw=read         #测试顺序读的I/O
    rw=write        #测试顺序写的I/O
    bs=512          #单次IO的块文件大小为512字节
    size=1G         #每个线程读写的数据量为1GB。
    name=mytest     #当前指令任务的名字
    thread          #使用pthread_create创建线程,另一种是fork创建进程。进程的开销比线程要大,一般都采用thread测试。
    ioengine=psync   #指定IO引擎使用psync方式。
    -numjobs=4       #本次测试的线程数是4
    -group_reporting     #显示任务的测试结果
    

    1.3.2. FIO顺序写测试

    使用以下指令进行测试:

    (1)测试单次写的块IO大小为512字节,数据大小为1G

    fio -filename=/mnt/emmc_test -direct=1 -thread -rw=write -ioengine=psync -bs=512 -size=1G -numjobs=4 -group_reporting -name=mytest
    

    (2)测试单次写的块IO大小为1M,数据大小为1G

    fio -filename=/mnt/emmc_test -direct=1 -thread -rw=write -ioengine=psync -bs=1M -size=1G -numjobs=4 -group_reporting -name=mytest
    

    1.3.3. FIO顺序读测试

    使用以下指令进行测试:

    (1)测试单次读的块IO大小为512字节,数据大小为1G

    fio -filename=/mnt/emmc_test -direct=1 -thread -rw=read -ioengine=psync -bs=512 -size=1G -numjobs=4 -group_reporting -name=mytest
    

    (2)测试单次读的块IO大小为1M,数据大小为1G

    fio -filename=/mnt/emmc_test -direct=1 -thread -rw=read -ioengine=psync -bs=1M -size=1G -numjobs=4 -group_reporting -name=mytest
    

    1.3.4. FIO随机写测试

    使用以下指令进行测试:

    (1)测试单次写的块IO大小为512字节,数据大小为1G

    fio -filename=/mnt/emmc_test -direct=1 -thread -rw=randwrite -ioengine=psync -bs=512 -size=1G -numjobs=4 -group_reporting -name=mytest
    

    (2)测试单次写的块IO大小为1M,数据大小为1G

    fio -filename=/mnt/emmc_test -direct=1 -thread -rw=randwrite -ioengine=psync -bs=1M -size=1G -numjobs=4 -group_reporting -name=mytest
    

    1.3.5. FIO随机读测试

    使用以下指令进行测试:

    (1)测试单次读的块IO大小为512字节,数据大小为1G

    fio -filename=/mnt/emmc_test -direct=1 -thread -rw=randread -ioengine=psync -bs=512 -size=1G -numjobs=4 -group_reporting -name=mytest
    

    (2)测试单次读的块IO大小为1M,数据大小为1G

    fio -filename=/mnt/emmc_test -direct=1 -thread -rw=randread -ioengine=psync -bs=1M -size=1G -numjobs=4 -group_reporting -name=mytest
    

    1.3.6. FIO测试结果分析

    可忽略报错:

    fio:cache invalidation of /mnt/emmc_test fail:Invalid argument
    

    测试结果举例:

    测试者主要关注红色方框内的几个参数数据是否异常:

    cpu: 用户(usr)时间和系统(sys)时间的占比

    bw: 总带宽(a),最小带宽(b)和最大带宽©,这里均为202M/S。(括号内是10的幂的形式)

    io: 该组中所有线程执行的累计I/O大小(d),这里四个线程累计写4096M(括号内是10的幂的形式)

    run: 这组线程中最小和最长的运行时间(e),这里运行时间为20.26秒

    1.3.7. CPU加压测试

    除了上述常规FIO测试外,可模拟CPU忙碌状态下进行FIO测试。

    cpu_loading使用方式:

    echo “loading 0 80 4” > /sys/devices/virtual/sstar/msys/cpu_loading
    

    参数说明:

    • 第一个%d表示总的运行毫秒数,当输入为0时,表示没有时间限制

    • 第二个%d表示需要的%CPU占用数值,设置的值是下限,80表示最低80%,不一定保持在80%(0< num <= 100: 以毫秒为单位,占用一毫秒内的百分比时间,余下时间休眠)

    • 第三个%d表示是否开启运行及运行模式(测试时候使用4,为0时表示关闭程序运行)

    注:多核情况下,使用top命令查看展示的%CPU是多核的平均值,需要乘以核数才是单核CPU的实际占用率。

    Cpu占用率可根据用户业务实际情况自行设置,模拟CPU忙碌时,FIO读写emmc是否正常。可开启cpu_loading之后再进行FIO读写测试。

    1.3.8. BIST拉频宽测试

    除了章节1.3.7描述的CPU加压测试外,可以开启BIST来进行DDR的加压测试。

    BIST使用方式:

    echo loop rw all > /sys/devices/system/miu/miu0/bist;
    

    通过上述命令bist将最大限度占用访问DDR的频宽,可以在此模式下进行FIO测试

    关闭BIST:

    echo stop all > /sys/devices/system/miu/miu0/bist;
    

    可以增大BIST UTIL占用,默认cmd_mode=0,UTIL占用84%;cmd_mode=15时,UTIL占用98%,请先关闭bist,再进行设定

    echo cmd_mode  15  > /sys/devices/system/miu/miu0/bist;
    

    注:遇到cma_alloc 失败时,可以在bootargs里增大cma size

    1.4. EMMC擦除测试

    擦除测试会擦除分区数据,建议单独创建分区进行测试,分区创建方法见章节2.2,如果不想创建新分区可以不进行擦除测试。

    eMMC_erase使用方式:

    cd /sys/class/mmc_host/mmc0/device/
    echo "0x5AEC00 0x414800" > eMMC_erase
    

    参数说明:

    • 第一个%x表示分区的起始地址,单位是块(十六进制)

      注:可以通过cat /sys/block/mmcblk0/mmcblk0p7/start命令获取分区起始地址

    ​ 用计算器将5958656转换为16进制为0x5AEC00

    • 第二个%x表示要擦除的大小,单位是块(十六进制)

      注:这里0x414800表示擦除整个分区,分区大小可以通过cat /sys/block/mmcblk0/mmcblk0p7/size命令获取。

    ​ 用计算器将4278272转换为16进制为0x414800

    若需要反复进行擦除测试可以每次擦除前重新格式化分区,保证擦除动作会被emmc设备执行。格式化方式:mkfs.ext4 /dev/mmcblk0p7,过程中输入y即可。

    1.5. vbs脚本监控测试结果

    若测试者需要自动监控压测结果是否正常可以使用xshell运行下面所提供的vbs监控脚本:

    Sub Main
        Dim waitStrs, result
        Dim i, testCount
    
        i = 0
        testCount = 172800 '48h'
        waitStrs = Array("DumpReg")
    
        Do While i < testCount
    
            result = xsh.Screen.WaitForStrings(waitStrs, 1000)
            If result = 1 Then
                xsh.Screen.Send chr(3)
                xsh.Screen.Send(VbCr)
                xsh.Screen.Send("ps w | grep emmc_stress_test | grep -v ""grep"" | awk '{printf $1}' | xargs kill >/dev/null 2>&1")
                xsh.Screen.Send(VbCr)
                xsh.Screen.Send(VbCr)
                xsh.Screen.Send("emmc stress test fail!")
                exit sub
            else
                i = i + 1
            End If
        Loop
    
        xsh.Screen.Send chr(3)
        xsh.Screen.Send(VbCr)
        xsh.Screen.Send("ps w | grep emmc_stress_test | grep -v ""grep"" | awk '{printf $1}' | xargs kill >/dev/null 2>&1")
        xsh.Screen.Send(VbCr)
        xsh.Screen.Send(VbCr)
        xsh.Screen.Send("emmc stress test success.")
    End Sub
    

    使用者可以根据需要修改脚本中的测试时间,若压测脚本在后台运行,运行前将压测脚本重命名为emmc_stress_test.sh,vbs监控脚本最后会停止压测脚本运行。

    压测开始前运行此脚本,打开xshell的工具选项,选择要运行的脚本文件:

    脚本运行后会监控压测过程中驱动是否报出eMMC_FCIE_DumpRegisters相关错误,检查到此错误后会停止压测,打印“emmc stress test fail!”,若是监控时间内没有检查到错误,最后也会停止压测并打印“emmc stress test success.”


    2. eMMC 掉电保护压力测试介绍

    2.1. 概述

    本章节用于指导eMMC Power Save Mode(PSM)功能压测,模拟实际应用场景,在压测环境下,配合随机上下电,检验系统稳定性,全过程自动化进行。

    2.2. 测试环境准备

    2.2.1 硬件环境

    • evb开发板(需要将SAR1 pin放通以支持SAR detect功能)

    • 继电器控制模块

    • 2个12V电源适配器(一个给开发板供电;另一个给继电器控制模块供电)

    • 1个串口模块

    2.2.2 测试原理

    • fio工具进行顺序读写

    • python serial模块编程控制继电器随机上下电

    • eMMC驱动掉电保护功能

    2.3. 测试步骤

    2.3.1 pure linux

    • 开发板使用emmc boot方式进入到uboot,创建test分区,大概4GB左右,如图:

    • 重新进入kernel后,将新创建的分区格式化为ext4文件系统格式,挂载点为/mnt

    • 挂载好test分区后,配置网络参数信息,进入/mnt路径,将fio文件和emmc_voltage_drop_test.zip附件中的testcheck.sh脚本放到/mnt路径中。记得dos2unix testcheck.sh并且同时给fio和testcheck.sh赋予执行权限+x

    • 更改/etc/init.d/rcS如下,使得每次下电上电后可以自动执行压测脚本

    2.3.3 随机上下电

    附件中的serialControl.py为控制继电器随机上下电的python脚本,直接在PC端执行即可:python serialControl.py。通电时间为[10s, 600s]区间内的整数。唯一需要注意的是,脚本中的端口号,需要根据接入PC时,继电器控制器实际分配为准。

    2.4. 测试结果

    • 测试持续时长可以根据实际情况自行决定

    • 如果压测过程出现异常,会输出error log

    2.5. 附件

    emmc_voltage_drop_test.zip