一、单片机的“不掉电笔记本”
嵌入式Flash就是焊在单片机(MCU)里的一小块非易失存储器。
你写好的程序(固件)、设备的序列号、校准参数、运行日志,全放在里面。
一旦断电,它不会忘事;重新上电,程序从Flash的第一条指令开始跑,就像翻开笔记本接着干活。
它本质上是NOR Flash,能像内存一样直接提供指令给CPU执行(这叫XIP),所以它既是“硬盘”又是“可执行程序仓库”。
但千万别把它当普通RAM用。它脾气不小,写起来又慢又讲究。
二、一群被关在绝缘牢笼里的电子
1. 记忆单元:浮栅晶体管
每个记忆细胞是一个特殊的MOS管,里面埋着一块被绝缘层(氧化物)完全包裹的“浮栅”,就像悬空孤岛。
数据就靠浮栅里有没有囚禁住电子来表示:
写入(编程):通过高电压(>10V)把电子强行“注入”浮栅,或者用量子隧穿推进去。这会使晶体管更难导通,我们定义为0。
擦除:用更高的电压把电子从浮栅里“吸”出来(量子隧穿),晶体管变容易导通,定义为1。
物理本质决定了:
编程只能把1改成0,擦除只能把0变回1,且擦除得一大片一起干,绝不可能单比特翻转。
2. 读飞快,还能就地执行(XIP)
读的时候只要给个地址,就能直接获取0/1状态,速度极快(几十纳秒)。
因为NOR Flash支持随机寻址,CPU能直接取指令执行,不必先复制到RAM,这让廉价MCU用很少的RAM就能跑大程序。
3. 写入/擦除的粒度严重不对等
擦除的最小单位是扇区/块,常见512字节、2KB、4KB甚至128KB。一擦就是一整块全变1。
编程(写)的单位可能是字节、半字或128位一页,只能把1写成0。
所以——“改单个字节”是个大工程:
你得把那字节所在整个扇区先读到RAM,修改某个值,然后擦除整个扇区,再把改好的数据写回去。只改1个字节,整个扇区都要被折磨一次。
三、工程上必须面对的“原罪”
1. 擦写次数有限,是消耗品
每次擦写都用高压破坏氧化层,造成物理磨损,终有一天关不住电子。
一般嵌入式NOR Flash标称1万~10万次擦写。
温度一高,这个次数断崖下跌——85°C下只能保证1万次甚至更低,因为氧化物老化加速。
2. 写前必须擦除,不能覆盖
Flash没有办法原地把0翻成1,必须先用擦除清空整个扇区。你哪怕只是想更新一个字节也得拉着整个扇区“陪葬”,导致写放大(写入实际物理量远超逻辑修改量)。
3. 写入和擦除慢得令人发指
读:几十纳秒
写一页(比如128位):几十微秒,比读慢上千倍
擦一个扇区:几十毫秒(典型值20-50ms),比读慢百万倍
在擦除或写入期间,如果CPU还想从同一Bank取指令,就会暂停,中断也不响应。工程上要么把关键代码转到RAM执行,要么用双Bank Flash。
4. 数据不是永远有效的
浮栅里的电子会慢慢泄漏(尤其是高温),时间长了可能丢数据。规格书常保证常温20年保持,但在85°C环境下可能只有几年。寿命与保持时间是耦合的:擦写次数越多、温度越高,数据越容易丢失。
5. 位翻转与ECC纠错
偶尔有个别比特因为辐射、漏电等自己翻转,所以现代Flash内部或要求用户软件加ECC。
ECC保护有一个非常重要的约束:必须一次写满整个ECC字(如64位数据+8位ECC),不能分多次修改,否则下次读出时ECC校验不通过,直接报不可纠正错误,系统可能宕机。
6. 当不了普通变量
你不能声明一个指针指向Flash地址,然后直接赋值。一切写入必须走解锁序列、擦除、编程、校验固件操作,完全不是RAM那回事。
四、跨过去就等着出事
1. 电压边界
读操作:一般1.8V~3.6V都行。
擦除/编程:电荷泵需要稳定高压,供电低于下限(比如1.7V)时,编程可能不完全,数据变成垃圾,甚至变砖。
掉电是最大的杀手。升级固件时如果断电,如果没做掉电保护(大电容、备份区、掉电检测),设备直接成砖头。
2. 温度边界
擦写操作必须在规格书允许的温度范围内(如-40°C~105°C)。
低温下电荷泵效率差,可能擦写失败。
高温下数据保持时间锐减,擦写寿命按阿伦尼乌斯指数式缩短:温度每升高10~15°C,寿命可能减半。
3. 时序与等待状态
CPU主频高了,Flash响应跟不上,必须插入等待周期。现代MCU有Flash加速器(预取/缓存),可以把等待周期隐藏起来,让执行近似零等待,否则读出的指令数据会错。
操作写/擦时,一定要查询状态寄存器,确认操作完成并达到最大超时时间,否则访问Flash返回非法数据。
4. 扇区对齐与编程页边界
擦除地址必须是扇区大小的整数倍,编程必须按页对齐(比如128位地址对齐),且不能跨页。违反则硬件错误或数据全毁。
5. ECC原子写入边界
必须一次写满一个ECC保护单元,否则那个单元读出来就是ECC错误。这在软件设计上要严格约束。
6. 安全保护机制(量产必须重视)
芯片提供多种保护,必须用起来:
读保护(RDP):封锁调试口,防止固件被读出抄板。
写保护(WRP):保护关键区域(Bootloader、校准数据)不被意外擦写。
PCROP:阻止CPU从该区域取指,保护核心算法,但允许当数据读。
OTP区域:只能写一次,用于存储唯一序列号或密钥。
忘加保护,固件、算法随便被带走,量产事故。
7. 双Bank与分区结构
很多MCU内部Flash分大小不等的扇区(小16KB+大128KB),方便把Bootloader放小扇区里。双Bank设计还能让你一个Bank写新固件,另一个Bank同时跑程序,完全不停机。
五、它到底都用在哪儿
1. 固件存储与就地执行
这是最根本的:上电从Flash取第一个指令,接着跑整个程序。XIP让系统RAM需求很低,成本控制到极致。
2. Bootloader + 固件升级(OTA)
Flash被划分为Bootloader区和App区(甚至A/B双区)。
升级时,新固件写入App区,启用前必须校验完整性,并且要结合掉电安全设计(双备份标志、电容储能),确保无论如何断电都不变砖。
3. 模拟EEPROM,存非易失参数
你要存配置、校准值、累积里程,但Flash不能字节覆写,于是用软件在Flash里划一个区域模拟EEPROM:每次修改写一条新记录,标记老记录失效,扇区满了再整理回收。这背后必须有磨损平衡算法,避免频繁修改的地址提前报废。
注意:掉电瞬间可能丢失最后一条记录或状态,上电恢复需扫描最新有效记录,这会增加启动时间。
4. 运行日志/黑匣子
安全关键系统(汽车、医疗)把故障码和传感器数据周期性存入Flash,形成环形日志。
得考虑扇区擦除耗时与寿命,以及掉电时数据的完整性。
5. 存储静态资源(字库、图片、声音)
带屏或语音的MCU,把不小的资源放在内部Flash(或外挂QSPI Flash),通过XIP直接映射或DMA读出。外挂Flash本质也是NOR,规律一致。
6. 多固件冗余(安全OTA)
物联网设备常保存两份App镜像,一个运行,一个升级,切换前校验,失败还能回退,杜绝变砖风险。这全靠Flash被合理分区和双Bank能力。
六、总结
请把嵌入式Flash当成一个需要小心伺候、有寿命的慢速块设备:
写它的时候,关中断、把操作代码搬到RAM执行、确认电源充裕。
产品十年寿命规划里,必须把擦写次数、高温保持时间、磨损均衡算得明明白白。
安全保护不是可选项,是出厂前的必选项。
掉电保护不做,等于把整个设备押上命运的轮盘。
以上是个人的一些浅见,如有不当之处,欢迎批评指正。