ARM 處理器平臺 eMMC Flash 存儲磨損測試示例
1). 簡介
目前工業(yè)嵌入式 ARM 平臺最常用的存儲器件就是 eMMC Nand Flash 存儲,而由于工業(yè)設(shè)備一般生命周期都比較長,eMMC 存儲器件的磨損壽命對于整個設(shè)備來說至關(guān)重要,因此本文就基于 NXP i.MX8M Mini ARM 處理器平臺演示 eMMC 器件磨損測試的示例流程。
關(guān)于 eMMC 存儲器件的基本介紹可以參考如下文章,eMMC 存儲器件通常包含有 eMMC Nand Flash 控制器和一定數(shù)量的 Nand Flash 存儲顆粒來組成,ARM 處理器主機(jī)對于 eMMC 的操作都要通過 Nand Flash 控制器進(jìn)行映射,同時 Nand Falsh 控制器還負(fù)責(zé) Wear leveling/ECC/Bad Block Management 等功能以保證 eMMC 器件穩(wěn)定可靠工作。
https://developer.toradex.cn/software/linux-resources/linux-features/emmc-linux/
eMMC 存儲器件的磨損壽命主要由其包含的 Nand Flash 顆粒存儲單元的 P/E(programming and erasing) 次數(shù)來決定,不同 Nand Flash 顆粒種類通常的 P/E 次數(shù)不同,一個大概的參考如下,不同品牌不同工藝的顆粒會有差異。
./ SLC Nand Flash - 10K - 100K P/E Cycles
./ MLC Nand Flash - 3K - 10K, normally 3K P/E Cycles
./ 2D TLC Nand Flash - normally 1K P/E Cycles
./ 3D TLC Nand Flash - normally 3K P/E Cycles
但是由于 Nand 控制器操作 Nand Flash 存儲單元 programming 寫入最小單位是 Page,而 erasing 擦除最小單位是 Block,因此當(dāng)寫入/擦除數(shù)據(jù)不是對應(yīng)最小單元整數(shù)倍時候就會產(chǎn)生額外的開銷,同時還附加其他 Wear leveling/Garbage collection/Bad Block Management 等功能產(chǎn)生的開銷,就會導(dǎo)致實(shí)際寫入的全壽命數(shù)據(jù)量要小于理論上按照單元 P/E Cycles 計算的數(shù)據(jù)量(eMMC capacity * P/E cycles),這個差異就是 WAF (Write Amplification Factor)寫放大因子((eMMC capacity * P/E cycles)/actual full-lifetime data written)。更多相關(guān)說明請參考如下文章。
https://www.toradex.cn/blog/shi-yong-emmc-shan-cun-de-she-bei-de-mo-sun-gu-ji
因此由于上述 Nand Flash 控制器地址映射和 WAF 的存在,磨損測試是無法直接將 Host 寫入數(shù)據(jù)和實(shí)際 Nand Flash 顆粒的 P/E 對應(yīng)的,而 WAF 在不同寫入情況下又是一個動態(tài)數(shù)值,所以我們依賴 Linux Kernel mmc-utils 工具或者 eMMC 提供商的專用軟件來讀取 Extended CSD rev 1.7 (MMC 5.0) 包含的 Health Status 信息,并通過其每 10% 的線性變化和實(shí)際寫入數(shù)據(jù)是否對應(yīng)線性變化,以及最終寫入數(shù)據(jù)量,可以推算出實(shí)際的 WAF。
https://developer.toradex.cn/software/linux-resources/linux-features/emmc-linux/#extended-csd-rev-17-mmc-50
關(guān)于 CSD Register 中 Health Status 和 Spare Block Register 的定義說明如下
./ Device life time estimation type A/B: life time estimation based on blocks P/E cycles, provided in steps of 10%, e.g.:
0x02 means 10%-20% device life time used.
./ Pre EOL information: overall status for reserved blocks. Possible values are:
0x00 - Not defined.
0x01 - Normal: consumed less than 80% of the reserved blocks.
0x02 - Warning: consumed 80% of the reserved blocks.
0x03 - Urgent: consumed 90% of the reserved blocks.
本文所示例的平臺來自于 Toradex Verdin i.MX8MM 嵌入式平臺。
2. 準(zhǔn)備
a). Verdin i.MX8MM ARM核心版配合Dahlia 載板并連接調(diào)試串口用于后續(xù)測試
b).參考這里下載 Toradex Yocto Linux BSP6 Reference Image
c).參考這里的說明將上述下載的 BSP Image 安裝到 Verdin i.MX8MM 核心板。
d).準(zhǔn)備一個 SD 卡,參考這里的說明使用上述下載的 BSP Image 制作啟動 SD 卡。
3). 測試流程
a). 將 SD 插入 Dahlia 載板后啟動,系統(tǒng)自動會優(yōu)先從外部 SD 卡 (mmc1) 啟動,可以通過如下調(diào)試串口 log 信息來進(jìn)一步判定。
-------------------------------
......
Hit any key to stop autoboot: 0
switch to partitions #0, OK
mmc1 is current device
Scanning mmc 1:1...
Found U-Boot script /boot.scr
......
-------------------------------
b). 因?yàn)橄到y(tǒng)會自動 mount eMMC 對應(yīng)設(shè)備分區(qū),為了后續(xù)測試,需要先關(guān)閉自動掛載。
-------------------------------
root@verdin-imx8mm-07276322:~# mount |grep /dev/mmcblk0
/dev/mmcblk0p2 on /media/RFS-mmcblk0p2 type ext4 (rw,relatime)
/dev/mmcblk0p1 on /media/BOOT-mmcblk0p1 type vfat (rw,relatime,gid=6,fmask=0007,dmask=0007,allo)
-------------------------------
在設(shè)備 Linux 下執(zhí)行下面腳本關(guān)閉自動掛載,執(zhí)行成功后上述掛載信息就沒有了。
-------------------------------
#!/bin/sh -e
systemd-umount /dev/mmcblk0p1
systemd-umount /dev/mmcblk0p2
systemctl stop systemd-udevd
systemctl stop systemd-remount-fs
count=`ls -1 /etc/udev/rules.d/*automount.rules 2>/dev/null |wc -l`
if [ $count != 0 ]
then
rm /etc/udev/rules.d/*automount.rules
fi
-------------------------------
c). 接下來要通過 Linux 磁盤操作工具來進(jìn)行大量寫入數(shù)據(jù)來測試 eMMC 的磨損, 本文測試使用 fio 工具,當(dāng)然還有像 dd/hdparm 等工具也可以根據(jù)情況酌情選擇。
./ 首先創(chuàng)建 fio 配置文件,類似如下,具體說明可以參考 fio 官方文檔。
-------------------------------
[global]
bs=32k
direct=0
ioengine=libaio
iodepth=4
verify=crc32c
filename=/dev/mmcblk0 ; emmc device filename
verify_dump=1
verify_fatal=1
randrepeat=0
[write-once]
description=Write once area, used for testing date retention
stonewall
rw=write
verify_pattern=0xaa555aa5 ; fixed data pattern
size=256M
offset=0
[verify-write-once]
description=Verify write once area, used for testing data retention
stonewall
rw=read
verify_only
size=256M
offset=0
[write]
description=Write r/w stress data area with random data
stonewall
rw=write
do_verify=0
offset=256M
[verify]
description=Verify r/w stress data area
stonewall
rw=read
verify_only
offset=256M
-------------------------------
//其中需要說明的是 bs (block size) 的設(shè)置需要根據(jù)不同的 eMMC 手冊中定義的 Optimal Write Size 以盡可能減小 WAF,比如當(dāng)前測試 eMMC 手冊中定義如下
實(shí)際讀取的寄存器數(shù)值如下,對應(yīng)為 32KB,因此 fio 配置文件中 bs 參數(shù)設(shè)置為 32k 或者其整數(shù)倍數(shù),可以保證 Nand Flash 顆粒存儲單元寫入都是按照 Page Size。
-------------------------------
$ mmc extcsd read /dev/mmcblk0 | grep write
Optimal write size [OPTIMAL_WRITE_SIZE: 0x08]
-------------------------------
./ 然后可以通過類似如下測試腳本來進(jìn)行一次寫入和驗(yàn)證,測試 fio 的配置正確和可用以及當(dāng)前的 eMMC Health Status 狀態(tài)
-------------------------------
#!/bin/bash -e
EMMC_DEVICE=/dev/mmcblk0
FIO_TEST_NAME=emmc-pe-test.fio
echo ">> eMMC P/E test preparation on ${EMMC_DEVICE}"
echo ">> eMMC EXTCSD Health Status"
mmc extcsd read "${EMMC_DEVICE}" | fgrep -A1 DEVICE_LIFE_TIME_EST
mmc extcsd read "${EMMC_DEVICE}" | fgrep -A1 PRE_EOL_INFO
echo ">> Write once data"
fio --section=write-once "${FIO_TEST_NAME}"
echo ">> Verify write once data"
fio --section=verify-write-once "${FIO_TEST_NAME}"
-------------------------------
./ 最后可以通過如下循環(huán)寫入腳本持續(xù)寫入測試來測試 eMMC 磨損情況。
-------------------------------
#!/bin/bash -e
EMMC_DEVICE=/dev/mmcblk0
COUNT=0
FIO_TEST_NAME=emmc-pe-test.fio
echo ">> Starting eMMC P/E test on ${EMMC_DEVICE}"
while true
do
echo ">> Run $COUNT"
echo ">> eMMC EXTCSD Health Status"
mmc extcsd read "${EMMC_DEVICE}" | fgrep -A1 DEVICE_LIFE_TIME_EST
mmc extcsd read "${EMMC_DEVICE}" | fgrep -A1 PRE_EOL_INFO
echo ">> Check write once data"
fio --section=verify-write-once "${FIO_TEST_NAME}"
echo ">> Wear eMMC"
fio --section=write --section=verify "${FIO_TEST_NAME}"
COUNT=$(($COUNT + 1))
done
-------------------------------
./ 磨損測試一次全盤寫入和驗(yàn)證的 log 信息如下,由于實(shí)際測試完成時間會非常長,通常根據(jù) eMMC 容量不同可能需要幾天甚至十幾天時間,本文就不演示最終完成的數(shù)據(jù)。最后可以根據(jù)壽命達(dá)到90%以上時候全部 log 信息統(tǒng)計出類似如下表格 eMMC 每磨損 10% 實(shí)際 P/E 的次數(shù)和數(shù)據(jù)量,得出 eMMC 的全壽命磨損數(shù)據(jù)/磨損是否線性以及實(shí)際 WAF 數(shù)值。另外,關(guān)于 LIFE_TIME_EST_A 還是 LIFE_TIME_EST_B 沒有標(biāo)準(zhǔn)定義,由各個廠商自行定義,所以實(shí)際以廠商定義為準(zhǔn)。
-------------------------------
>> Starting eMMC P/E test on /dev/mmcblk0
>> Run 0
>> eMMC EXTCSD Health Status
Device life time estimation type B [DEVICE_LIFE_TIME_EST_TYP_B: 0x01]
i.e. 0% - 10% device life time used
Device life time estimation type A [DEVICE_LIFE_TIME_EST_TYP_A: 0x01]
i.e. 0% - 10% device life time used
Pre EOL information [PRE_EOL_INFO: 0x01]
i.e. Normal
>> Check write once data
verify-write-once: (g=0): rw=read, bs=(R) 32.0KiB-32.0KiB, (W) 32.0KiB-32.0KiB, (T) 32.0KiB-32.4
fio-3.30
Starting 1 process
Jobs: 1 (f=1)
verify-write-once: (groupid=0, jobs=1): err= 0: pid=583: Fri Apr 29 20:04:38 2022
Description : [Verify write once area, used for testing data retention]
read: IOPS=4908, BW=153MiB/s (161MB/s)(256MiB/1669msec)
...
Run status group 0 (all jobs):
READ: bw=153MiB/s (161MB/s), 153MiB/s-153MiB/s (161MB/s-161MB/s), io=256MiB (268MB), run=166c
Disk stats (read/write):
mmcblk0: ios=1009/0, merge=0/0, ticks=2390/0, in_queue=2391, util=94.47%
>> Wear eMMC
write: (g=0): rw=write, bs=(R) 32.0KiB-32.0KiB, (W) 32.0KiB-32.0KiB, (T) 32.0KiB-32.0KiB, ioeng4
verify: (g=1): rw=read, bs=(R) 32.0KiB-32.0KiB, (W) 32.0KiB-32.0KiB, (T) 32.0KiB-32.0KiB, ioeng4
fio-3.30
Starting 2 processes
Jobs: 1 (f=1): [_(1),V(1)][100.0%][eta 00m:00s]
write: (groupid=0, jobs=1): err= 0: pid=590: Fri Apr 29 20:17:15 2022
Description : [Write r/w stress data area with random data]
write: IOPS=732, BW=22.9MiB/s (24.0MB/s)(14.4GiB/642435msec); 0 zone resets
...
verify: (groupid=1, jobs=1): err= 0: pid=607: Fri Apr 29 20:17:15 2022
Description : [Verify r/w stress data area]
read: IOPS=4812, BW=150MiB/s (158MB/s)(14.4GiB/97725msec)
...
Run status group 0 (all jobs):
WRITE: bw=22.9MiB/s (24.0MB/s), 22.9MiB/s-22.9MiB/s (24.0MB/s-24.0MB/s), io=14.4GiB (15.4GB),c
Run status group 1 (all jobs):
READ: bw=150MiB/s (158MB/s), 150MiB/s-150MiB/s (158MB/s-158MB/s), io=14.4GiB (15.4GB), run=9c
Disk stats (read/write):
mmcblk0: ios=58819/29449, merge=0/3732727, ticks=143387/81519893, in_queue=81663280, util=99.%
...
-------------------------------
4). 總結(jié)
本文基于 NXP i.MX8MM ARM 處理器平臺說明和演示了 eMMC 壽命磨損測試的流程,同時由于測試是線性寫入,得出的結(jié)果和實(shí)際應(yīng)用具體情況可能有不同,不過在實(shí)際應(yīng)用中,為了最大程度的增加 eMMC 存儲器件的壽命和可靠性,在寫入數(shù)據(jù)時候最好不要無論大小數(shù)據(jù)每次都直接寫入磁盤,最好使用緩存將要寫入的數(shù)據(jù)累積到一定量之后,根據(jù)具體 eMMC Optimal Write Size 來最終寫入磁盤,以盡可能減少 WAF,提高磨損壽命。

提交
NXP iMX8MP 處理器基于 Linux 關(guān)閉 Debug Console 輸出
ARM 處理器平臺 Ethernet Compliance 測試流程示例
基于 NXP iMX8QM 運(yùn)行 QNX
通過恢復(fù)模式更新 Toradex ARM 計算機(jī)模塊 BSP 鏡像
Yocto Linux BSP7 新版本介紹