电子产业一站式赋能平台

PCB联盟网

搜索
查看: 29|回复: 0
收起左侧

如何延长NAND闪存和eMMC使用寿命

[复制链接]

939

主题

939

帖子

7793

积分

高级会员

Rank: 5Rank: 5

积分
7793
发表于 3 天前 | 显示全部楼层 |阅读模式

yj2vyigx0df64019995537.gif

yj2vyigx0df64019995537.gif
& d0 X. Z0 X- b! C! w% m
点击上方蓝色字体,关注我们, b9 O" d: d% Q7 A; J
6 I* M/ A1 a* f( f" M
每当闪存单元进行写入或擦除操作时,存储单元中的氧化层都会受到磨损,导致浮栅中的电子控制能力下降。
! J/ N, l6 }: V, Q
5 X2 @, Q- \& v9 n. y最终,随着擦写次数的增加,NAND闪存会逐步失效,无法继续正常工作。! ^) W4 N' H( K" x3 P% G, f( S" W

1 ^  u% E6 f  U; s  P* `6 A8 s根据不同的存储介质类型,NAND闪存可以分为SLC(单级单元)、MLC(多级单元)、TLC(三层单元)和QLC(四层单元),其中SLC的擦写寿命最长,而QLC的擦写寿命最短。
, r1 p3 a; |* }* ?! f
. h7 n, S% ~3 _$ x9 I- ^eMMC是基于NAND闪存的一种存储介质,其内部包含了NAND闪存和控制器,因而其寿命和NAND闪存密切相关。1 l7 T& A- y1 ^
$ u' ~" n1 {5 B, E0 H) F# z; e4 }: K

bqymrqccnhj64019995638.png

bqymrqccnhj64019995638.png

: y- \# X+ u8 r; y根据闪存颗粒的不同,eMMC的擦写次数通常也受到限制,尤其是MLC、TLC和QLC类型的eMMC。( w" a- j5 E  t) V3 p
9 t( @9 b5 @& P7 V, T; z
闪存的寿命可通过以下公式预测:
8 }: k6 t+ r7 Q5 C. _$ o' V8 S
% X5 U; c# b1 t: P( S+ q/ v

er3kuxus02w64019995738.png

er3kuxus02w64019995738.png
% F# a- l2 u9 B3 V4 _: A
3 b$ d* V$ R9 e0 N* y, y4 w
其中,写入放大是影响寿命的关键因素之一。通过优化写入放大,可以显著延长NAND闪存和eMMC的使用寿命。 8 U; D) v3 d8 G1 |! o
2
8 S/ O: x% U+ R' x3 H2 s' ^" q写入放大的影响/ |! J, h, A* \5 S$ z" v  |
NAND闪存的写入操作通常需要先进行擦除。# _2 T8 y) E$ V, h* a; l0 ]
! v' t" Q& ]; k) r( J* s) h9 ^7 W
擦除的粒度通常远大于写入的粒度,导致写入操作必须涉及更多的闪存单元。这一过程称为写入放大
2 [3 C$ x9 c0 G9 s+ |4 W; \' [3 B- B
写入放大效应会导致闪存的实际写入次数远高于理论上的写入次数,从而加速闪存的磨损。
, L6 f/ {+ O+ {) q  i/ T2 _- O* v1 ?2 z- k. F- c5 A/ ~
写入放大可以通过以下公式计算:
9 Z( _, Z& N# I1 {- d3 p) o# U; T% B+ x

p5vrgmgwic264019995838.png

p5vrgmgwic264019995838.png
) m6 y; j( E4 M# b, w4 D( c7 ]* w
6 G( e" m8 R4 m* ~! o

0 p2 I% D; o% A, o影响写入放大的因素
7 }4 W6 {; Y+ a* R# @% }% p1 P
  • 垃圾回收:启用垃圾回收机制(Wear Leveling)能有效减小写入放大。
  • 预留空间:适当增加预留空间,有助于降低写入放大效应。
  • 顺序写入与随机写入:顺序写入的写入放大效应最小,随机写入会显著增加写入放大。
  • 数据压缩:压缩数据后写入可减少每次写入的数据量,降低写入放大。
  • 删除重复数据:通过删除不必要的数据,减少对闪存的占用,从而减小写入放大。4 Y8 m0 I* a4 E: x
    3
    # B, R0 h( |8 y  f+ w优化措施8 _( O4 g# h+ I
    为了延长NAND闪存和eMMC的使用寿命,必须从应用软件层面进行优化。& y; t/ G3 G# I$ n) T8 o! b

    : G) @% D7 D- r; n3.1 合理分区与动静数据分离% ?" H: B& ?3 ?3 D4 t
    动静数据分离是一种有效的优化方法。' J$ R; g8 K, ?7 c

    9 ^3 q. r* [1 \! b! h9 Z将系统数据和频繁更新的数据分开存储,可以避免系统分区因频繁写入而提前损坏。8 n9 e3 `3 A" r% K+ `' \

    ; p5 P7 v2 N& u& t/ z" s( y' F具体来说,可以将系统分区与数据分区分开,确保系统分区只用于存储系统文件而不受到频繁的数据写入的影响。
    0 }" H+ p0 P6 p$ Z4 y5 m$ ^0 k% {5 e* _
    此外,将日志文件和应用程序的日志信息存储在RAM文件系统中,避免直接写入闪存,能够减少闪存的写入次数。; l/ [" U$ {/ C8 x/ [' L; ]
    ' i! q9 M* e+ F8 p. o. U1 i2 \
    仅在发生系统异常时,定期将日志写入闪存。8 R+ V$ v* y( b. F; x
  • #define LOG_FILE_PATH "/ramdisk/log.txt"// 定义一个日志缓冲区#define LOG_BUFFER_SIZE 1024char log_buffer[LOG_BUFFER_SIZE];// 模拟写入日志数据voidwrite_log_to_ram(constchar *log_entry){    FILE *log_file = fopen(LOG_FILE_PATH, "a");    if (log_file == NULL) {        printf("Error opening RAM file for logging: s& P2 Y8 @* a# L. S
    ");        return;    }    fprintf(log_file, "%s
    1 i. h* B; B8 j$ r- L4 M", log_entry);    fclose(log_file);}// 定期将日志写入NAND闪存voidflush_logs_to_flash(){    FILE *log_file = fopen(LOG_FILE_PATH, "r");    if (log_file == NULL) {        printf("Error opening RAM file for flushing
    & B- E! Q& |# }- Y8 g");        return;    }    FILE *flash_log_file = fopen("/mnt/flash/log.txt", "a");    if (flash_log_file == NULL) {        printf("Error opening NAND flash file
    5 u# n( W* H" q' L");        fclose(log_file);        return;    }    char line[256];    while (fgets(line, sizeof(line), log_file)) {        fprintf(flash_log_file, "%s", line);    }    fclose(log_file);    fclose(flash_log_file);}intmain(){    // 挂载RAM文件系统    if (mount("tmpfs", "/ramdisk", "tmpfs", 0, "size=2M") == -1) {        perror("Failed to mount RAM filesystem");        return-1;    }    // 模拟写入日志    write_log_to_ram("System started successfully");    // 定期将日志写入NAND闪存(可以通过定时器触发)    flush_logs_to_flash();    return0;}3.2 减少数据写入次数$ p! G4 Y, J* T: n! j6 P: I
    通过将频繁修改的数据先暂存在内存中,可以减少频繁写入闪存的次数。
    ( T" a! \5 y% t& X4 T4 J0 I5 w, \" A$ W2 r* x% E9 f4 M
    例如,可以使用Ramdisk来暂存数据,待数据积累到一定程度后再统一写入闪存。/ e( u& t6 P1 b' j* Z- G9 ]

    & l/ j- B/ S  ?. i4 |. N1 U通过此方式,系统可以减少写入频次,延长NAND闪存和eMMC的寿命。
    - F$ N7 [" E" ]+ O& n! G; x
    . d5 S% q: q0 k+ V' L3 H  U3.3 避免零碎数据写入
    9 c% A9 d/ z$ T1 L9 [# vNAND闪存的擦除粒度较大,因此在进行写入操作时,尽量确保数据块的大小为擦除块大小的整数倍。- }4 E; K* X5 c* k* r
    $ C' J2 v( u3 v
    避免零碎数据写入能够有效减少不必要的擦除操作,从而减小写入放大效应。
    ! @% X$ Y2 d' c$ ^- }+ T0 o' S5 {3 ^6 v+ v5 B/ W& x
  • #define FLASH_DEVICE "/dev/mtd0"// 假设使用的是MTD设备接口// 执行数据写入时,合并写入块voidwrite_data_to_flash(constchar *data, size_t data_len){    FILE *flash_device = fopen(FLASH_DEVICE, "wb");    if (flash_device == NULL) {        printf("Error opening flash device for writing
    6 n* ^) {: ^( r& r8 S");        return;    }    // 写入数据前,确保数据长度为闪存页大小的倍数    size_t page_size = 4096;  // 假设每页为4KB    size_t padded_len = (data_len + page_size - 1) & ~(page_size - 1);  // 向上取整到页大小的倍数    char *padded_data = (char *)malloc(padded_len);    if (!padded_data) {        printf("Memory allocation failed
    5 @" Y+ K" N. ^% X");        fclose(flash_device);        return;    }    // 填充数据    memset(padded_data, 0, padded_len);    memcpy(padded_data, data, data_len);    // 写入闪存    fwrite(padded_data, 1, padded_len, flash_device);    free(padded_data);    fclose(flash_device);}int main(){    // 要写入的数据    constchar *data = "This is a test data for NAND flash.";    write_data_to_flash(data, strlen(data));    return0;}3.4 维持合理的分区占用率# D7 }+ |2 Y' [
    合理的磁盘占用率对于延长NAND闪存和eMMC的寿命至关重要。
    7 h: Q& s/ }" }6 u) s  b
    4 Z1 P, }" w( k! u) p* N不要让存储介质处于接近满容量的状态,保持较低的磁盘占用率,可以有效减小写入放大效应。
    * J( k4 [0 e7 p9 W  \8 _" b( V, q& G
    对于eMMC闪存,可以通过启用文件系统的磁盘配额管理来确保磁盘使用率合理。6 a4 Y. q( ^0 ^
    " b* p2 L% |$ O1 y0 p2 a
    而对于NAND闪存,则可以通过编写磁盘占用率监控程序,在磁盘占用率达到阈值时自动清理无用文件。
    - E- ?( g5 b  J! P' S6 I% O" K% f! D  S+ P) h1 Z4 I: B' j0 q! y5 ]$ Q
    3.5 定期坏块检测与替换
    ! g. s0 K# @0 i9 }4 _: j7 r6 tNAND闪存存在坏块问题,长时间使用后可能出现坏块,导致数据丢失。
    % _- v0 @9 T+ N. k, d1 r5 O% e4 f  d6 o3 f) R) j% V; p( f1 t/ c* w
    定期进行坏块检测并进行坏块替换,能够防止系统使用坏块数据区域,从而保证数据的安全性。
    % P2 [' f1 ^7 T$ p4 x; s3 Y1 {0 E0 W; D+ B7 P/ L/ |
  • #define FLASH_DEVICE "/dev/mtd0"// 假设NAND闪存有2048个块#define TOTAL_BLOCKS 2048// 检查坏块的函数boolis_bad_block(int block_number){    // 这里只是示例,实际中需要通过硬件或驱动来检查坏块    // 一般来说,设备会返回一个坏块标记    return (block_number % 10 == 0);  // 假设每隔10个块就是坏块}// 替换坏块的函数voidreplace_bad_block(int block_number){    printf("Bad block detected at block %d. Replacing...4 P2 }: W  x, v* z' n+ z7 n
    ", block_number);    // 实际中可以使用闪存控制器提供的API进行坏块替换}intmain(){    // 检查每个块是否有坏块    for (int block = 0; block         if (is_bad_block(block)) {            replace_bad_block(block);        }    }    return0;}3.6、闪存健康管理
    , @# Y, i8 o/ H* \  r/ c对于eMMC,可以通过mmc_erase_info文件查看eMMC的擦写次数,以判断eMMC的健康状况。
    & O6 J1 v# t' v" p% y( G) C2 ]3 U: D# Z
    如果擦写次数接近厂商理论值,应及时采取预防措施,避免数据丢失。
    3 v( g# Q8 j7 m* p5 c
    ' f9 E# g% r! M& m对于NAND闪存,虽然不像eMMC那样直接提供擦写次数的统计,但可以通过自主统计擦写次数,并结合寿命预测公式对闪存的健康状态进行评估。7 f/ R1 G* I7 g  |, N, g/ s0 ?0 R7 U
    8 r: H" d1 J3 p( p2 {

    k2bbkuobvzq64019995938.png

    k2bbkuobvzq64019995938.png

    , ?+ R5 T0 }  x2 A/ H% f! }. P$ f' l  y- w/ B- S$ A! ~
    通过在嵌入式开发中采用适当的软件优化措施,如合理分区、数据压缩、避免零散写入等,可以显著延长NAND闪存和eMMC的使用寿命。+ Z% r2 _$ a! k/ y7 h- F

    ' [; b7 D% j1 d9 V# X. |! r( q优化写入放大、减少写入次数、避免不必要的擦除操作等技术方法,是提升闪存可靠性和降低故障发生率的有效途径。  ]7 h! }- ~6 T* T* S6 u& F# v

    * W# ]) d' X# J6 ~针对闪存的健康管理和坏块检测,也为系统的稳定性提供了保障。
    % l, }/ ?  q! y
    & U: @  m2 \$ [# b. @最终,这些优化措施将帮助提升嵌入式设备的可靠性,延长其服务周期。
    ; n: }8 Q& e: X5 U" {

    3x4rtsxcxaa64019996038.jpg

    3x4rtsxcxaa64019996038.jpg

    - C1 m7 n" d$ H/ V1 E' e8 g

    rxsv2yqvpan64019996138.gif

    rxsv2yqvpan64019996138.gif
    7 S9 b8 T9 M! M
    点击阅读原文,更精彩~
  • 回复

    使用道具 举报

    发表回复

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则


    联系客服 关注微信 下载APP 返回顶部 返回列表