ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

江科大STM32入门:FLASH闪存详解——从结构原理到读写保护

江科大STM32入门:FLASH闪存详解——从结构原理到读写保护 STM32学习笔记适用平台本文基于 STM32F103C8T6中容量产品64KB Flash讲解使用标准库开发。前言为什么非要学FLASH学到这里很多小伙伴可能有个疑问我程序不是已经能跑了吗GPIO、定时器、中断都玩溜了这个FLASH跟我有啥关系别急先想两个问题你的单片机掉电后之前记的数据比如密码、校准参数、运行次数还在吗RAM里的东西可是掉电就丢的。你想过没有以后做产品能不能像手机OTA升级一样通过串口或蓝牙给单片机隔空更新程序这两个问题的答案都指向了今天的主角——内部FLASH。它不只是存程序的地方更是我们能直接操作的掉电不丢失的存储空间。搞懂它你的STM32才算真正入门了。一、FLASH简介它到底是个啥STM32F1系列的内部FLASH说白了就三块东西组成部分作用人话解释程序存储器存放我们烧录的程序代码就是你Keil编译生成的hex文件住的家系统存储器存放ST出厂的Bootloader芯片原厂自带的引导程序用于串口下载选项字节配置读写保护、看门狗等FLASH的设置面板管着安全权限读写FLASH主要有两大用途存用户数据利用程序存储器的剩余空间保存那些掉电不能丢的参数。比如你的智能台灯要记忆亮度档位总不能每次上电都让用户重新调吧IAP在应用编程程序运行过程中通过串口、蓝牙等接口接收新程序把自己更新掉。这就是很多设备在线升级的底层原理。这里还要区分两个概念ICP在线编程通过JTAG、SWD或者系统存储器里的Bootloader把整个FLASH重新烧一遍。这是我们平时用ST-Link下载程序的方式。IAP在程序中编程程序自己跑起来后用代码去改写FLASH里的内容。比如你做一个Bootloader分区专门负责接收新程序。我的理解你可以把ICP想象成拆机换硬盘IAP就是手机在线系统更新。我们平时调程序用ICP做产品升级就要靠IAP了。二、FLASH的内部结构拆解它的五脏六腑2.1 闪存模块组织中容量产品先上一张户型图看看FLASH这块地皮是怎么划分的图1闪存模块组织中容量产品从这张表可以看出STM32F1的FLASH分为三大块1. 主存储器程序存储器中容量产品共有128页Page 0 ~ Page 127每页1KB。等等C8T6不是64KB吗怎么有128页这里要注意中容量产品的定义是64KB或128KBC8T664KB实际上只用到页0~页63。后面多出来的页在C8T6上是不存在的或者说超出范围了。地址从0x0800 0000开始每页递增0x400也就是1024字节。2. 信息块系统存储器地址0x1FFF F000大小2KB住着ST的Bootloader。用户选择字节选项字节地址0x1FFF F800大小16字节专门管配置。3. 闪存存储器接口寄存器从0x4002 2000开始是FPEC闪存编程和擦除控制器的操控面板。包括FLASH_ACR访问控制、FLASH_KEYR密钥、FLASH_SR状态、FLASH_CR控制、FLASH_AR地址等。2.2 FLASH基本结构框图​图2FLASH基本结构框图这张图更直观左边绿色的FPEC闪存编程和擦除控制器是大管家所有擦除和编程操作都必须经过它。右边橙色的三部分就是刚才说的程序存储器、系统存储器、选项字节。注意那个配置读写保护的箭头它告诉我们选项字节可以反过来控制主存储器的访问权限。这就好比小区大门的门禁系统选项字节就是物业的管理后台。我的理解FPEC就像FLASH的保安队长你想动FLASH里的内容得先过它这关。而且它不是摆设写错了钥匙或者操作顺序不对它真给你把门锁死。三、FLASH的解锁机制为什么要有钥匙3.1 三个关键键值FPEC手里有三把钥匙键值名称数值用途RDPRT键0x000000A5解除读保护KEY10x45670123解锁FPEC的第一步KEY20xCDEF89AB解锁FPEC的第二步3.2 解锁流程复位后FPEC默认是上锁状态FLASH_CR寄存器写不进去。这时候你想擦除或编程门儿都没有。正确解锁姿势往FLASH_KEYR密钥寄存器写入KEY1再往同一个寄存器写入KEY2顺序必须对值必须准。这两步走完后FPEC就解锁了你可以操作FLASH_CR了。⚠️ 风险说明如果你解锁时写错了值或者顺序颠倒了FPEC会被锁死在下次复位之前你再也动不了FLASH了。这不是吓唬人是手册里写的。3.3 加锁操作完成后记得设置FLASH_CR的LOCK位为1把FPEC重新锁上。这就像你进房间拿完东西要关门一样防止程序跑飞后误写FLASH。我的理解这个解锁机制其实是ST给我们的一层保险。你想啊如果程序跑飞了指针乱指万一指到FLASH地址上乱写一通那程序不就彻底崩了吗有了这把锁至少得对暗号才能动手大大降低了误操作的风险。四、如何读写FLASH——指针访问与操作流程4.1 使用指针直接访问存储器FLASH本质上就是一片地址空间。程序存储器从0x0800 0000开始那我们直接用指针就能读写读操作uint16_t Data *((__IO uint16_t *)(0x08000000));写操作*((__IO uint16_t *)(0x08000000)) 0x1234;这里__IO被定义为volatile。为什么非要加volatile因为编译器可能会自作聪明地优化掉你的读写操作。加了volatile就是告诉编译器这个地址是硬件寄存器每次读写都必须真去访问内存不准偷懒边界意识STM32F1的主存储器编程最小单位是半字16位。你不能像操作RAM那样一个字节一个字节地写必须16位一起写。而且写入的地址必须是偶数地址半字对齐。4.2 程序存储器编程流程​图5程序存储器编程流程看图说话编程写入的标准流程检查LOCK位如果LOCK1先执行解锁序列KEY1 KEY2。置PG位把FLASH_CR的PG位编程位置1告诉FPEC我要开始写数据了。写入半字在目标地址写入一个16位数据。等待BSY位清零FLASH_SR的BSY位忙标志为1表示FPEC正在干活你得轮询等它变0。读校验写入完成后把刚才的地址读出来看看是不是你写的那个数。⚠️ 核心知识点必考FLASH有个怪脾气——写入前必须先擦除而且擦除后所有位变成1写入只能把1改成0不能把0改成1。如果你直接往已经有数据的地址上写结果会是按位与的关系数据绝对不是你想要的。4.3 程序存储器页擦除流程​图6程序存储器页擦除流程既然写之前必须擦除那怎么擦检查并解锁同上。置PER位把FLASH_CR的PER位页擦除位置1。写地址把要擦除的页的起始地址写入FLASH_AR地址寄存器。置STRT位把FLASH_CR的STRT位开始位置1FPEC就开始擦了。等待BSY0。验证读出这一页确认全是0xFFFF擦除后就是全1。我的理解页擦除就像整块黑板擦掉重写。你不可能只擦掉黑板上的某一个字必须整页擦。所以规划FLASH存储时要把经常改动的数据放在同一页避免频繁擦除影响寿命。4.4 程序存储器全擦除流程​程序存储器全擦除流程全擦除就更简单了解锁。置MER位把FLASH_CR的MER位全擦除位置1。置STRT位开始擦除。等BSY0验证所有页。⚠️ 风险说明全擦除会把你的程序也擦掉如果你在程序运行过程中误触发了全擦除那芯片就变砖了只能重新用ST-Link烧程序。所以写代码时MER位一定要谨慎操作。五、选项字节那些隐藏配置5.1 选项字节的组织结构​信息块选项字节的组织结构选项字节一共16个字节但STM32用了一种冗余设计每个配置都存了原值和反值比如RDP和nRDP。这样芯片上电时可以互相校验防止配置因干扰出错。各字段含义字段作用RDP读保护级别。写入0xA5解除读保护其他值会开启不同级别的保护USER配置硬件看门狗IWDG_SW、停机/待机模式是否产生复位Data0/1用户可自定义一般存一些设备标识或校准参数WRP0~3写保护位每一位对应保护4个存储页中容量产品我的理解选项字节就像是FLASH的保险箱密码和权限设置。RDP读保护一旦开启别人用J-Link就读不出你的程序了对知识产权保护很重要。但注意开启读保护后如果要解除FLASH会被全部擦除这是ST设计的防破解机制。5.2 选项字节的编程与擦除选项字节和主存储器的操作类似但多了几道安检编程流程检查FLASH_SR的BSY位确认FPEC空闲。解锁FLASH_CR的OPTWRE位选项字节写使能。置FLASH_CR的OPTPG位选项字节编程位为1。写入半字到指定地址。等待BSY0。读出验证。擦除流程检查BSY位。解锁OPTWRE位。置FLASH_CR的OPTER位选项字节擦除位为1。置STRT位为1。等待BSY0。读出验证。我的理解选项字节操作比主存储器多一个OPTWRE解锁这相当于双重认证。毕竟改选项字节可能影响整个芯片的访问权限ST当然得谨慎点。六、器件电子签名芯片的身份证每颗STM32芯片出厂时ST都在系统存储区域烧写了一组不可更改的电子签名包含两个信息寄存器基地址大小用途闪存容量寄存器0x1FFF F7E016位表示芯片的FLASH容量单位KB。比如C8T6读出来就是64产品唯一身份标识寄存器0x1FFF F7E896位全球唯一的芯片ID每颗芯片都不一样这有啥用闪存容量寄存器程序可以自动识别自己跑在什么容量的芯片上做自适应配置。唯一身份标识可以做设备的硬件指纹。比如你想做一机一码的加密或者给每个设备分配独立序列号读这个寄存器就行了。因为它是出厂固化、不可更改的比存在FLASH里的数据靠谱多了。我的理解这就像是芯片的身份证号和户口本。96位的唯一ID全世界没有两颗一样的芯片做产品追溯、防复制、加密绑定都特别好使。七、我的理解 / 心得学FLASH之前我一直以为它只能存程序。现在明白了只要规划好地址完全可以把用户数据存在程序后面的空白页里。比如C8T6的64KB程序只占用了前20KB后面44KB就是自由空间。关于擦除寿命FLASH的擦写次数是有限的手册标称1万次。所以做数据存储时不能频繁擦同一页。如果要做EEPROM效果可以考虑磨损均衡算法或者直接用STM32的备份寄存器、外接EEPROM。八、踩坑记录踩坑场景现象原因解决办法未解锁直接写FLASH程序卡死或数据没写入FLASH_CR处于锁定状态严格按KEY1→KEY2顺序解锁写入前未擦除读出来的数据和写入值不一致FLASH只能1变0不能0变1写入前必须执行页擦除擦除/编程时掉电芯片变砖无法下载程序操作过程中断导致FLASH损坏确保电源稳定或加掉电检测选项字节误操作无法通过SWD下载程序开启了读保护或写保护按住复位键在Keil点击下载瞬间松开复位指针未加volatile开启优化后代码失效编译器优化掉了寄存器访问所有硬件寄存器指针前加__IO或volatile九、总结表格知识点核心内容注意事项FLASH组成程序存储器 系统存储器 选项字节C8T6程序存储器为64KB64页主存储器页大小每页1KB擦除最小单位是页写入最小单位是半字16位解锁键值KEY10x45670123KEY20xCDEF89AB顺序不能错错则锁死编程前提必须先擦除擦除后全为1写入只能1变0编程流程解锁→置PG→写半字→等BSY→校验地址必须半字对齐页擦除流程解锁→置PER→写地址→置STRT→等BSY会擦除整页1KB数据全擦除流程解锁→置MER→置STRT→等BSY会擦掉程序本身慎用选项字节RDP/USER/Data/WRP每项存原值反值操作前需额外解锁OPTWRE电子签名容量寄存器96位唯一ID出厂固化不可改可用于设备加密和序列号写这篇文章的时候我把江科大的视频又回顾了一遍结合《STM32F10xxx参考手册》把FLASH的寄存器位一个个核对过去才发现之前很多想当然的理解都是错的。比如我以为FLASH可以像RAM一样随便写实际上必须先擦除我以为解锁就是走个形式实际上写错真的会锁死。STM32的FLASH模块虽然看起来就是擦了写、写了读但里面的门道真不少——解锁机制、选项字节、读写保护每一步都是ST为了可靠性设计的保险丝。搞懂这些不只是为了应付考试更是为了以后做产品时少踩坑。开发环境Keil5 STM32F103C8T6最小系统板 ST-Link参考资料江科大STM32入门教程、《STM32F10xxx参考手册》如果本文对你有帮助欢迎点赞 收藏 ⭐ 有任何问题欢迎在评论区交流一起学习进步
返回列表