|
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
: 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
% 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
) 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
, ?+ 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
- C1 m7 n" d$ H/ V1 E' e8 g
rxsv2yqvpan64019996138.gif
7 S9 b8 T9 M! M
点击阅读原文,更精彩~ |
|