工业控制器分级存储方案:EEPROM、NOR Flash与SD卡选型及可靠性设计
1. 工业控制器存储方案的整体设计思路工业控制器和消费类电子产品最大的区别在于它可能要在配电柜里连续跑十年断电重启上千次夏天柜内温度能到七十度冬天在户外又是零下二三十度。这种场景下数据存储方案如果选得随意后期维护的成本会高到让人怀疑人生。我做过好几个基于STM32加FPGA架构的控制器项目踩过存储相关的坑不算少这里把分级存储的完整思路和实操细节梳理一遍。先明确一个前提工业控制器里的数据不是一个东西它们的性质差别很大。有一类数据是出厂参数和校准系数比如传感器的零点偏移、量程标定值、PID的初始参数这些东西写入一次之后可能几年都不动但绝对不能丢丢了设备就得返厂重新标定。另一类是运行配置比如通信地址、波特率、报警阈值用户偶尔会改改动频率大概是几个月一次。还有一类是运行日志和过程数据比如每秒钟采集的温度、压力值用于事后追溯和故障分析数据量大、写入频繁但单条数据丢了影响不大。这三类数据的写入频率、容量需求、可靠性要求完全不同用同一种存储介质去扛要么成本浪费要么可靠性不够。所以分级存储的核心逻辑就是让合适的介质干合适的活。1.1 三类存储介质的角色分工在这个方案里EEPROM、NOR Flash、SD卡各自承担不同的职责这不是随便分配的而是由它们的物理特性决定的。EEPROM的特点是字节级可擦写不需要按扇区擦除写入次数可以到百万次级别。缺点是容量小、速度慢、单位成本高。它最适合存那种少量、关键、偶尔改的数据。我一般用I2C接口的EEPROM比如AT24C系列容量从2Kbit到512Kbit都有存标定参数和出厂配置绰绰有余。NOR Flash的特点是支持随机读取可以像内存一样按地址访问擦除要按扇区来通常4KB一个扇区擦写寿命大概十万次左右。它的容量比EEPROM大得多从几MB到几十MB都有。适合存固件备份、字库、较大的配置表这类数据。SPI接口的NOR Flash用起来很方便STM32的SPI外设直接驱动就行。SD卡的特点是容量大、单位成本极低几个GB的卡几十块钱。但它的写入寿命有限而且掉电保护做得不好写入过程中断电容易导致文件系统损坏。所以它适合存日志、历史数据这种量大但不那么关键的内容而且必须做好掉电保护策略。注意SD卡在工业环境下的可靠性一直有争议。我个人的经验是只要做好三点——选用工业级SLC卡、加掉电检测电路、文件系统定期做一致性检查——用在数据记录场景是没问题的。但绝对不要拿它存关键参数。1.2 为什么不用单一存储方案有人可能会想直接用一块大容量NOR Flash把所有数据都存了不就行了理论上可以但实际项目里不划算。NOR Flash的擦写寿命是十万次级别如果用它存每秒一条的日志数据一天就是86400条就算做了磨损均衡一块扇区也撑不了多久。而且NOR Flash按扇区擦除写日志需要频繁擦写整个扇区效率很低。反过来如果全用SD卡呢关键参数存在SD卡上一旦卡接触不良或者文件系统损坏设备直接罢工。我见过一个现场案例某设备用SD卡存配置参数结果因为卡座氧化导致接触不良设备反复重启排查了两天才找到原因。这种教训一次就够了。所以分级存储不是为了炫技而是用工程手段把可靠性、成本、容量三个维度同时优化。关键数据用最可靠的介质海量数据用最经济的介质各司其职。1.3 STM32与FPGA的分工逻辑这个方案里STM32和FPGA各管一摊。STM32负责系统控制、通信协议处理、人机交互同时管理EEPROM和SD卡。FPGA负责高速数据采集和预处理同时挂一片NOR Flash用于存储FPGA的配置数据和高速缓存。为什么这么分因为FPGA的并行处理能力适合做实时性要求高的任务比如多路ADC同步采集、PWM波形生成、编码器信号解码。而STM32的强项是协议栈和文件系统FatFs、USB、以太网这些中间件在STM32上跑得很成熟。让FPGA去管文件系统是自找麻烦让STM32去做纳秒级时序控制也不现实。两者之间的数据交互通过SPI或者FSMC总线完成。我一般用SPI接线简单速率调到10MHz以上足够传输采集数据。如果数据量特别大比如FPGA做图像处理那就上FSMC并口STM32这边配成外部SRAM模式读写速度能到几十MB/s。2. 硬件电路设计与关键器件选型硬件设计这块存储部分的电路看起来简单但细节没处理好后期调试能让人抓狂。我按三种介质分别说。2.1 EEPROM电路设计与I2C总线注意事项EEPROM用I2C接口是最常见的。以AT24C512为例容量512Kbit也就是64KB够存几千条参数了。电路上需要注意几个点。上拉电阻的取值很关键。I2C总线是开漏输出必须加上拉电阻。阻值太大会导致上升沿变缓高速通信时波形失真阻值太小会增加功耗而且灌电流可能超过器件的承受能力。标准模式100kHz下4.7kΩ是常用值快速模式400kHz下一般用2.2kΩ到4.7kΩ。我实测下来3.3V供电、总线电容在100pF以内的情况下2.2kΩ上拉到3.3V400kHz通信很稳。写保护引脚WC要处理好。AT24C512的WC引脚高电平时禁止写入低电平时允许写入。有些设计图省事直接把WC接地这样虽然方便但失去了硬件写保护的能力。我的做法是用STM32的一个GPIO控制WC平时拉低允许写入在系统检测到异常或者进入安全模式时拉高防止误写。这个GPIO最好加上拉电阻确保STM32复位期间WC处于高电平状态避免上电瞬间的误写。地址引脚A0/A1/A2决定器件地址。如果总线上只挂一片EEPROM全部接地就行。如果要挂多片扩展容量注意地址不要冲突。I2C的7位地址里AT24C512固定占用高4位1010低3位由A2/A1/A0决定所以一条总线上最多挂8片总容量512KB。实操心得I2C总线上挂多个器件时走线尽量短最好不超过10cm。如果必须走长线考虑用I2C缓冲器或者改成差分传输。我曾经在一个项目里把EEPROM放在离STM32二十厘米远的地方400kHz通信偶尔出错降到100kHz才稳定。后来加了I2C缓冲芯片才解决问题。2.2 NOR Flash选型与SPI接口设计NOR Flash选SPI接口的接线少驱动简单。常用型号有W25Q系列、SST25系列等。容量根据需求选存FPGA配置数据的话一般4MB到16MB够用。SPI模式要确认清楚。NOR Flash支持Mode 0和Mode 3STM32的SPI外设也支持这四种模式。关键是CPOL和CPHA要匹配。W25Q系列通常用Mode 0CPOL0CPHA0或者Mode 3CPOL1CPHA1。我一般用Mode 0空闲时时钟低电平第一个边沿采样。配置STM32的SPI时把CPOL和CPHA都设成0就行。片选信号CS的处理有讲究。SPI协议要求CS在传输期间保持低电平传输结束后拉高。如果CS控制不好Flash可能进入错误状态。我的做法是用STM32的硬件NSS或者普通GPIO控制CS在每次传输前拉低传输后拉高。注意CS拉高后要等几个时钟周期再发下一条命令给Flash内部状态机切换的时间。W25Q系列的datasheet里写了CS拉高后需要至少50ns的延时我一般延时1us保险。电源去耦不能省。NOR Flash在擦除和写入时电流会突然增大如果电源去耦不好可能导致电压跌落写入失败。每片Flash的VCC引脚旁边放一个0.1uF的陶瓷电容再并一个10uF的钽电容基本就够了。2.3 SD卡接口设计与掉电保护电路SD卡有两种接口模式SPI模式和SDIO模式。SPI模式接线简单但速度慢适合低速数据记录。SDIO模式速度快4位数据线可以到几十MB/s适合高速采集场景。STM32的SDIO外设支持4位模式我一般用SDIO。SDIO的时钟线、命令线、数据线都要加上拉电阻典型值10kΩ到50kΩ。SD卡规范里要求这些线在空闲时保持高电平上拉电阻提供这个电平。阻值太小会增加功耗太大可能导致上升沿不够快。我用10kΩ上拉到3.3V实测SDIO 4位模式48MHz时钟下读写稳定。掉电检测是SD卡方案的关键。SD卡在写入过程中断电文件系统很容易损坏。解决办法是加一个电压监测电路当电源电压降到阈值以下时提前通知STM32停止写入并给SD卡足够的时间完成当前操作。具体做法是用一个比较器监测电源电压输出接到STM32的外部中断引脚。阈值设在3.0V左右当电压降到3.0V时触发中断STM32在中断里立即停止文件操作调用f_sync把缓存数据刷入卡内。SD卡座的选择也有讲究。工业环境要用带金属屏蔽罩的卡座防止电磁干扰。卡座的插入检测引脚要接到STM32的GPIO用于检测卡的插拔。有些卡座还有写保护检测引脚虽然SD卡本身很少用写保护开关但留着这个引脚可以做硬件写保护。注意SD卡的热插拔一定要处理好。在卡拔出时如果文件系统还在操作可能导致数据损坏。我的做法是在插入检测中断里做防抖处理检测到卡拔出后立即卸载文件系统并标记卡状态为不可用。重新插入后重新挂载。3. 软件架构与分级存储实现软件这块是重头戏。三种存储介质、两种处理器怎么组织代码结构怎么保证数据一致性怎么处理异常情况都需要仔细设计。3.1 STM32端存储管理框架STM32这边我一般分三层硬件抽象层、存储服务层、应用接口层。硬件抽象层封装EEPROM、NOR Flash、SD卡的底层读写函数。EEPROM用I2C读写封装成eeprom_read(addr, buf, len)和eeprom_write(addr, buf, len)。NOR Flash用SPI封装成nor_read、nor_write、nor_erase_sector。SD卡用FatFs文件系统封装成sd_file_read、sd_file_write。存储服务层做数据管理和调度。这一层要解决几个问题数据怎么组织、写入怎么调度、异常怎么恢复。数据组织上我把EEPROM分成几个区域出厂参数区、用户配置区、校准数据区、备份区。每个区域有固定的起始地址和长度用宏定义好。比如出厂参数区从0x0000开始长度256字节用户配置区从0x0100开始长度512字节校准数据区从0x0300开始长度256字节备份区从0x0400开始长度512字节。备份区存的是关键参数的副本主区数据损坏时可以从备份区恢复。写入调度上EEPROM的写入不能太频繁否则寿命消耗快。我的做法是在RAM里维护一份参数副本应用层修改参数时只改RAM然后置一个脏标志。后台任务每隔一段时间检查脏标志如果有修改再写入EEPROM。这样可以把多次修改合并成一次写入减少EEPROM的擦写次数。异常恢复上每次写入EEPROM前先把旧数据读到备份区写入新数据后再校验。如果校验失败从备份区恢复。这个流程虽然多了一次写入但可靠性大大提高。3.2 FPGA端NOR Flash控制器设计FPGA这边要自己写NOR Flash的控制器。SPI接口的NOR Flash控制器不算复杂但时序要严格按datasheet来。控制器分几个模块SPI时钟生成、命令发送、数据收发、状态机控制。SPI时钟生成模块把系统时钟分频到SPI需要的频率。W25Q系列支持最高104MHz的SPI时钟但FPGA这边要考虑信号完整性我一般用50MHz稳定可靠。命令发送模块负责把读、写、擦除命令按SPI时序发出去。NOR Flash的命令格式是先拉低CS然后发送命令字节再发送地址最后是数据。比如读命令0x03后面跟3字节地址然后就可以读数据了。写命令要先发写使能0x06再发页编程命令0x02跟地址和数据。状态机控制模块管理整个操作流程。NOR Flash在写入和擦除时需要时间期间状态寄存器会显示忙状态。控制器要轮询状态寄存器直到操作完成。W25Q系列的页编程时间典型值0.7ms扇区擦除时间典型值45ms块擦除时间更长。状态机要处理好这些等待。// NOR Flash状态机核心片段 localparam IDLE 3d0; localparam SEND_CMD 3d1; localparam SEND_ADDR 3d2; localparam SEND_DATA 3d3; localparam WAIT_DONE 3d4; always (posedge clk) begin case(state) IDLE: begin if (start) state SEND_CMD; end SEND_CMD: begin if (cmd_done) state SEND_ADDR; end SEND_ADDR: begin if (addr_done) state SEND_DATA; end SEND_DATA: begin if (data_done) state WAIT_DONE; end WAIT_DONE: begin if (flash_ready) state IDLE; end endcase end实操心得FPGA写NOR Flash控制器时最容易出错的地方是时序。SPI的采样边沿和发送边沿要搞清楚。我一般用Mode 0在时钟上升沿发送数据下降沿采样数据。写testbench的时候要模拟Flash的响应包括忙状态的延时。仿真通过了再上板能省很多调试时间。3.3 SD卡文件系统与数据记录策略SD卡上用FatFs文件系统这是STM32社区最成熟的选择。FatFs的移植不难主要是配置好底层磁盘IO函数。数据记录策略上我一般按时间分文件。比如每天一个文件文件名用日期命名如LOG_20250101.CSV。文件内容用CSV格式每行一条记录包含时间戳和各个通道的数据。这样方便用Excel或者Python做后续分析。写入策略上不能每条数据都调用f_write那样效率太低。我的做法是在RAM里开一个缓冲区比如4KB攒够一批数据再一次性写入。同时每隔一段时间比如10秒调用f_sync把缓存刷入卡内防止掉电丢数据。掉电保护上除了前面说的硬件检测电路软件上也要配合。在掉电中断里立即停止数据采集调用f_sync然后关闭文件。如果时间来不及至少要把当前缓冲区的内容写入。我实测过从检测到掉电到SD卡完全停止工作大概有几十毫秒的时间窗口足够完成一次f_sync。// 掉电中断处理函数 void EXTI0_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line0) ! RESET) { // 立即停止数据采集 g_adc_running 0; // 刷入缓存数据 if (g_file_open) { f_write(g_file, g_buffer, g_buf_len, bw); f_sync(g_file); f_close(g_file); g_file_open 0; } // 标记掉电事件 g_power_fail_flag 1; EXTI_ClearITPendingBit(EXTI_Line0); } }4. 数据可靠性与异常处理机制工业控制器的存储方案可靠性是第一位。数据丢了、错了轻则设备异常重则出安全事故。这块我单独拎出来说。4.1 数据校验与冗余设计每种存储介质都要做数据校验。EEPROM和NOR Flash的写入都要带CRC校验。写入前计算数据的CRC32把CRC一起存进去。读取时重新计算CRC和存储的CRC比对不一致就说明数据损坏。冗余设计上关键参数存两份主份和备份。主份损坏时从备份恢复。备份区的位置要和主份隔开避免同一物理区域损坏导致两份都丢。EEPROM里主份存在0x0100备份存在0x0400中间隔了校准数据区物理地址上分开了。NOR Flash里FPGA的配置数据也存两份。一份在0x000000一份在0x100000。FPGA上电加载时先读主份CRC校验失败就读备份。这个逻辑在FPGA的配置加载状态机里实现。SD卡上的日志数据每条记录带一个序号和CRC。事后分析时如果发现序号不连续或者CRC错误就知道哪些数据有问题。虽然不能恢复但至少能识别出来。4.2 磨损均衡与寿命管理EEPROM和NOR Flash都有擦写寿命限制虽然工业控制器的写入频率不高但长期运行下来也要考虑。EEPROM的磨损均衡比较简单。因为EEPROM是字节级擦写没有扇区概念所以只要避免反复写同一个地址就行。我的做法是在EEPROM里划一块区域做日志式存储每次写入追加到下一个位置写满后擦除整块重新开始。这样每个字节的擦写次数就均匀了。NOR Flash的磨损均衡要复杂一些因为擦除是按扇区的。如果频繁写同一个扇区那个扇区很快就会坏。解决办法是在多个扇区之间轮换。比如分配4个扇区做日志存储写满一个扇区后切换到下一个4个都用完了再擦除第一个。这样每个扇区的擦写次数就是总写入量的四分之一。SD卡内部有控制器做磨损均衡应用层不需要操心。但要注意SD卡的写入放大问题。频繁写小文件会导致卡内部反复擦写同一块区域加速老化。所以日志文件要攒够一批再写不要一条一条写。4.3 常见故障排查速查表故障现象可能原因排查方法解决方案EEPROM读写失败I2C总线被拉低用示波器看SCL/SDA波形检查上拉电阻确认无器件拉死总线EEPROM数据错乱写入过程中断电读回数据比对CRC增加备份区写入前先备份NOR Flash擦除失败扇区地址未对齐检查擦除地址是否是4KB对齐擦除地址按扇区大小对齐NOR Flash写入超时状态寄存器一直忙读状态寄存器看忙位检查电源电压增加等待时间SD卡挂载失败文件系统损坏用读卡器在电脑上检查重新格式化或做磁盘检查SD卡写入速度慢卡本身速度等级低查看卡上的Class标识换Class 10以上的工业级卡SD卡掉电后文件损坏写入过程中断电检查掉电检测电路增加掉电中断提前刷缓存FPGA读NOR Flash数据错SPI模式不匹配对比datasheet的时序图确认CPOL/CPHA设置实操心得SD卡的问题最难排查因为卡本身是个黑盒。我遇到过一张卡在STM32上死活挂载不上换到电脑上却正常。后来发现是卡的初始化时间比较长STM32的SDIO初始化超时设得太短。把超时从100ms改成500ms就好了。所以SD卡相关的超时参数要留足余量。5. 实际项目中的调试经验与优化技巧理论说完了说点实际调试中的经验。这些东西在datasheet里找不到都是踩坑踩出来的。5.1 上电初始化顺序与延时处理系统上电时各个存储介质的初始化顺序有讲究。我的做法是先初始化EEPROM读取关键参数再初始化NOR Flash加载FPGA配置最后初始化SD卡挂载文件系统。为什么这个顺序因为EEPROM里存的是系统的基础配置比如通信地址、波特率这些参数决定了后续的操作。如果EEPROM读取失败系统应该进入安全模式而不是继续往下走。NOR Flash的初始化相对独立但FPGA配置加载需要时间放在中间比较合适。SD卡初始化最慢放在最后不影响系统启动。延时处理上每种介质上电后都需要一定的稳定时间。EEPROM上电后大概需要1ms才能响应命令NOR Flash需要更长时间大概10ms。SD卡最慢上电后需要至少74个时钟周期做内部初始化然后发送CMD0复位再发送CMD8、ACMD41等命令。整个初始化流程走下来几百毫秒是正常的。// 存储介质初始化顺序 void storage_init(void) { // 1. 初始化EEPROM eeprom_init(); delay_ms(2); // 读取关键参数 if (eeprom_read(PARAM_ADDR, g_params, sizeof(g_params)) ! OK) { // 读取失败加载默认参数 load_default_params(); } // 2. 初始化NOR Flash nor_init(); delay_ms(15); // 加载FPGA配置 fpga_load_config(); // 3. 初始化SD卡 if (sd_init() OK) { f_mount(g_fs, 0:, 1); g_sd_ready 1; } else { g_sd_ready 0; } }5.2 写入性能优化与缓存策略写入性能的瓶颈主要在SD卡。SPI模式的SD卡写入速度可能只有几百KB/sSDIO 4位模式能到几MB/s。如果数据采集频率高写入速度跟不上数据就会丢。优化策略有几个。第一是加大缓存。在RAM里开一个大的环形缓冲区比如64KB采集数据先写入缓冲区后台任务慢慢往SD卡写。这样能吸收突发的高采集率。第二是批量写入。攒够一个扇区的数据512字节再写减少文件系统的开销。第三是选择合适的文件系统配置。FatFs的_FS_TINY选项可以减小内存占用但会降低性能。如果RAM够用不要开这个选项。EEPROM的写入优化主要是减少写入次数。前面说的脏标志加后台写入是一种方法。另一种方法是在RAM里维护参数的影子副本应用层读参数时直接读RAM写参数时改RAM并置脏标志。这样应用层感觉不到EEPROM的慢速。NOR Flash的写入优化主要是用好页编程。NOR Flash的页大小通常是256字节一次页编程可以写256字节。如果数据量小于256字节也要占用一次页编程时间。所以尽量攒够一页再写。5.3 电磁兼容与抗干扰设计工业现场的电磁环境恶劣存储电路容易受干扰。我遇到过EEPROM数据莫名其妙变化的情况后来发现是附近的接触器动作时产生了强电磁脉冲通过I2C总线耦合进来。抗干扰措施有几个。第一是加磁珠。在I2C总线和SPI总线的信号线上串磁珠抑制高频干扰。磁珠选100MHz时阻抗在100Ω到1kΩ之间的。第二是加TVS管。在信号线和电源线上加TVS管钳位瞬态高压。第三是做好接地。存储芯片的接地引脚要就近接地接地面积尽量大。第四是软件滤波。I2C通信失败时重试几次连续失败才报错。EEPROM读取时连续读三次取多数结果。注意SD卡座的外壳要接到机壳地不要接到信号地。机壳地能屏蔽外部干扰信号地保持干净。两者之间用磁珠或者0Ω电阻连接。5.4 固件升级与存储空间管理工业控制器需要支持固件升级。STM32的固件升级可以通过SD卡或者通信接口。我的做法是把新固件放在SD卡里STM32读取固件文件写入NOR Flash的备份区然后跳转到Bootloader进行升级。存储空间管理上要预留足够的空间。EEPROM的容量一般够用但NOR Flash和SD卡要规划好。NOR Flash里FPGA配置占一部分STM32固件备份占一部分日志缓存占一部分。SD卡里日志文件会不断增长要定期清理旧文件。我的做法是保留最近30天的日志超过30天的自动删除。// 清理旧日志文件 void clean_old_logs(void) { FILINFO fno; DIR dir; char path[64]; time_t now get_current_time(); f_opendir(dir, /LOGS); while (f_readdir(dir, fno) FR_OK fno.fname[0]) { // 解析文件名中的日期 if (parse_log_date(fno.fname, file_time)) { if (now - file_time 30 * 24 * 3600) { sprintf(path, /LOGS/%s, fno.fname); f_unlink(path); } } } f_closedir(dir); }6. 方案对比与选型建议最后说一下不同场景下的选型建议。这个方案不是万能的要根据具体需求调整。6.1 三种介质的关键参数对比参数EEPROMNOR FlashSD卡容量范围2Kbit-512Kbit1MB-64MB1GB-128GB接口I2C/SPISPI/并行SDIO/SPI写入粒度字节页(256B)扇区(512B)擦除粒度字节扇区(4KB)内部管理擦写寿命100万次10万次1万次左右写入速度慢(ms级)中(ms级)快(us-ms级)读取速度慢快中单位成本高中极低掉电保护好好差适用场景关键参数固件/配置日志/大数据6.2 不同应用场景的配置建议小型控制器数据量不大参数为主。一片EEPROM加一片小容量NOR Flash就够了。EEPROM存参数NOR Flash存固件备份。不需要SD卡。中型控制器有数据记录需求但频率不高。EEPROM加NOR Flash加SD卡。EEPROM存关键参数NOR Flash存固件和配置SD卡存日志。大型控制器高速采集大数据量。EEPROM加NOR Flash加大容量SD卡或者eMMC。如果数据量特别大考虑用eMMC替代SD卡eMMC的可靠性和速度都比SD卡好但焊接要求高成本也高一些。高可靠性场景比如安全相关的控制器。EEPROM加NOR Flash加FRAM。FRAM是铁电存储器写入速度极快擦写寿命几乎无限但容量小、成本高。适合存那种需要频繁写入的关键数据。6.3 成本与可靠性的平衡选型的时候要在成本和可靠性之间找平衡。我的经验是关键数据不要省。EEPROM很便宜几块钱一片但存的是设备的身份证丢了就得返厂。SD卡很便宜但不要用它存关键数据。NOR Flash的价格和容量关系很大小容量的很便宜大容量的价格上升很快。如果只需要存几MB的数据NOR Flash很合适。如果需要几十MB考虑用NAND Flash或者eMMC。SD卡的选择上不要贪便宜买消费级的卡。工业级SLC卡的价格是消费级卡的好几倍但寿命和可靠性完全不是一个级别。我一般选SanDisk的工业级卡或者Swissbit的卡虽然贵但省心。实操心得SD卡买回来之后最好先做一次全盘写入测试把整个卡写满再读出来校验。这样能筛掉有坏块的卡也能让卡的内部控制器建立好映射表。我一般用H2testw这个工具做测试虽然慢但很彻底。7. 写在最后的一些个人体会这个方案我在好几个项目里用过从简单的数据采集器到复杂的多轴控制器整体表现稳定。但有几个点是我后来才慢慢意识到的。第一存储方案要在项目初期就定下来。我见过太多项目前期没考虑存储后期发现数据存不下临时加SD卡结果硬件改版、软件重写浪费大量时间。存储方案和硬件架构、软件架构都相关越早确定越好。第二测试要充分。存储相关的bug往往在特定条件下才出现比如掉电、高温、长时间运行。我一般会做几个专项测试反复掉电测试、高温老化测试、连续写入测试。这些测试能暴露很多问题。第三留好调试接口。存储芯片的引脚要引出测试点方便用示波器或者逻辑分析仪抓波形。软件上要留调试命令能读取存储状态、擦写次数、错误计数等信息。出问题时这些信息能大大加快排查速度。第四不要忽视文档。存储区的地址分配、数据格式、校验方式都要写清楚。过半年再来看代码没有文档根本记不住。我一般会在代码里用注释写清楚每个存储区的用途和格式另外单独维护一份存储映射表。这个方案后续还可以扩展。比如加入无线通信模块把SD卡里的日志定期上传到服务器。或者加入实时时钟给每条日志打上精确的时间戳。再或者加入数据压缩减少SD卡的写入量。这些扩展都不难核心的存储架构不用变。