STM32—FLASH闪存
1.FLASH简介
- STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分,通过闪存存储器接口(外设)可以对程序存储器和选项字节进行擦除和编程
- 我们怎么操作这些存储器呢?这就需要用到这个闪存存储器接口了,闪存存储器接口是一个外设,是这个闪存的管理员,毕竟闪存的操作很麻烦,涉及到擦除、编程、等待忙、解锁等等操作,所以这里,我们需要把我们的指令和数据,写入到这个外设的相应寄存器,然后这个外设就会自动去操作对应的存储空间,后面写这个外设可以对程序存储器和选项字节,这两部分,进行擦除和编程,对比上面的三个部分少了系统存储器这个区域,因为系统存储器是原厂写入的Bootloader程序,不允许我们修改
- 读写FLASH的用途:
- 利用程序存储器的剩余空间来保存掉电不丢失的用户数据
- 对于我们这个C8T6芯片来说,它的程序存储器容量是64K,一般我们写个简单的程序,可能就只占前面的很小一部分空间,剩下的大片空余空间可以加以利用,比如存储一些我们自定义的数据,这样就非常方便,而且可以充分利用盗源,不过这里要注意,我们在选取存储区域时,一定不要覆盖了原有的程序,要不然程序自己把自己给破坏了,之后程序就运行不了了,一般存储少量的数据,我们就选最后几页存储就行了
- 通过在程序中编程(IAP),实现程序的自我更新
- 我们在存储用户数据时要避开程序本身,以免破坏程序,但如果,我们就非要修改程序本身会发生什么呢?那这就是第二点提到的功能,在程序中编程,利用程序,来修改程序本身,实现程序的自我更新,这个在程序中编程,就是IAP
- 利用程序存储器的剩余空间来保存掉电不丢失的用户数据
- 在线编程(In-Circuit Programming-lCP)也可以叫在电路中编程,用于更新程序存储器的全部内容,它通过JTAG、SWD协议或系统加载程序(Bootloader)下载程序
- 这个JTAG、SWD,就是仿真器下载程序,就是我们目前用的STLINK使用SWD下载程序,每次下载,都是把整个程序壳全更新掉,那系统加载程序,就是系统存储器的Bootloader,也就是串口下载,串口下载,也是更新整个程序,这就是我们一直在用的ICP下载方式,
- 在程序中编程(In-Application Programming-IAP)可以使用微控制器支持的任一种通信接口下载程序
- 怎么实现?那比如,这是整个程序存储器,我们首先需要自己写一个Bootloader程序,并且存放在程序更新时,不会覆盖的地方,比如我们放在这后面,然后,需要更新程序时,我们控制程序跳转到这个自己写的Bootloader里来,在这里面,我们就可以接收任意一种通信接口传过来的数据,比如串口、USB、蓝牙转串口、WIFI转串口等等,这个传过来的数据,就是待更新的程序,然后我们控制FLASH读写,把收到的程序,写入到前面,程序正常运行的地方,写完之后,再控制程序跳转回正常运行的地方或者直接复位,这样程序就完成了自我升级,这个过程其实就是和系统存储器这个的Bootloader-样,因为程序要实现自我升级,在升级过程中肯定需要布置一个辅助的小机器人来临时干活,只不过是系统存储器的Bootloader写死了,只能用串口下载到指定位置 ,启动方式也不方便,只能配置BOOT引脚触发启动,而我们自己写Bootloader的话,就可以想怎么收怎么收,想写到哪就写到哪,想怎么启动就怎么启动,并且这整个升级过程,程序都可以自主完成,实现在程序中编程,更进一步,就可以直接实现远程升级了,对吧,非常方便
2.闪存模块组织
我们C8T6芯片的闪存容量是64K,属于中容量产,对于小容量产品和大容量产品,闪存的分配方式有些区别,可以参考手册
首先看一下第一列的几个块,这里分为了三个块,第一个是主存储器也就是我们刚才说的程序存储器,用来存放程序代码的,这是最主要,也是容量最大的一块,下面第二个,是信息块,里面又可以分为启动程序代码和用户选择字节,其中启动程序代码就是刚才说的系统存储器,存放的是原厂写入的Bootloader,用于串口下载,然后下面这个用户选择字节也就是刚才说的选项字节,存放一些独立的参数,这个选项字节,在手册里一直都称作选择字节,英文是Option Bytes,然后最后一块是闪存存储器接口寄存器,这一块的存储器,实际上并不属于闪存,你看它的地址就知道,地址都是40开头的,说明这个存储器接口寄存器就是一个普通的外设,和之前讲的GPIO、定时器、串口等等都是一个性质的东西,这些存储器,它们的存储介质,也都是SRAM,这个闪存存储器接口就是上面这些闪存的管理员,这些寄存器,就是用来控制擦除和编程这个过程的,只有程序存储器、系统存储器和选项字节才是真正的闪存
对于主存储器这里对它进行了分页,分页是为了更好地管理闪存,擦除和写保护,都是以而为单位的,这一点和之前W25Q64那一节的闪存一样,同为闪存,它们的特性基本一样,写入前必须擦除,擦除必须以最小单位进行,擦除后数据位全变为1,数据只能1写0,不能0写1,擦除和写入之后都需要等待忙,这些都是一样的,那W25064的分配方式是先分为块Block,再分为康区Sector比较复杂,这里,就比较简单了,它只有一个基本单位,就是页,每页的大小都是1K,0~127,总共128页,总容量就是128K,对于C8T6来说,它只有64K,所以C8T6的页只有一半,0~63,总共64页,共64K,然后看一下页的地址范围:第一个页的起始地址,就是程序存储器的起始地址,0x0800 0000,之后就是一个字节一个地址,依次线分配了,看一下每页起始地址的规律首先是0000然后0400、0300、0C00...到FC00,所以,地址只要以000、400、800、C00结尾的,都一定是页的起始地址,对吧
系统存储器,它的起始地址是0x1FFF F000,它的容量是2K,再下面,选项字节,起始地址是0X1FFF F800,容量是16个字节,里面只有几个字节的配置参数,我们平时说的,芯片闪存容量是64K、128K,它指的只是主存储器的容量,下面信息块的两个东西,虽然也是闪存,但是并不统计在这个容量里,这就是闪存的分配方式
那最后,就是这个闪存接口寄存器了,里面包括KEYR键寄存器、SR状态寄存器、CR控制寄存器等等,外设的起始地址是0x4002 2000,每个寄存器都是4个字节,也就是32位,这就是这个外设的寄存器
3.FLASH基本结构
整个闪存分为程序存储器、系统存储器和选项字节三部分,这里程序存储器我以C8T6为例,它是64K的共64页,最后一页的起始地址是0800 FC00,左边这里,是闪存存储器接口,手册里还有个名称闪存编程和擦除控制器(FPEC),然后,这个控制器,就是闪存的管理员,它可以对程序存储器进行擦除和编程,也可以对选项字节进行擦除和编程,当然系统存储器是不能擦除和编程的,之后选项字节,里面有很大一部分配置位,其实是配置主程序存储器的读写保护的,所以右边画的,写入选项字节,可以配置程序存储器的读写保护,当然选项字节还有几个别的配置参数
4.操作控制器FPEC
细节问题,如何操作这个控制器FPEC,来对程序存储器和选项字节进行擦除和编程,首先,第一步,是FLASH解锁,这个和之前W25Q64-样,W25064操作之前需要写使能,这个FLASH,操作之前需要解锁,目的,都是为了防止误操作,那这里,解锁的方式,和之前独立看门狗一样,都是通过在键寄存器写入指定的键值来实现,使用键寄存器的好处就是,更能防止误操作,每一个指令,必须输密码才能完成,,,,,,,,,,,,,,,,,,,,,
4.1FLASH解锁
5.使用指针访问存储器
因为STM32内部的存储器是直接挂在总线上的,所以这时,再读写某个存储器就非常简单了,直接使用C语言的指针,来访问即可,__IO对应C语言的关键字,volatile,volatile,直译就是,易变的数据,在这个数据类型前面加上volatile,是一个安全保障措施,用一句话来说,就是防止编译器优化,首先说一下,Keil编译器默认情况下是最低优化等级,这时,加不加这个volatile,都没有影响,如果,你要提高编译器优化等级,这时候就会有问题了,用途就是,可以去除无用的繁架代码,降低代码空间,提升运行效率,但优化之后,编译器在某些地方可能会弄巧成拙,比如,你想用变量计数空循环的方式实现延时函数,那编译器优化的时候,可能会说你这段延时函数好像没用啊还自白浪赛时间,我直接给你优化掉,这就弄巧成拙了,因为我们本意就是靠浪装时间来延时,这时,我们就可以在延时的变量定义前面加上volatile,告诉编译器我无论对这个变量干什么,你都原封不动地去执行,别给我优化掉了
另外,编译器还会利用缓存来加速代码,比如如果你要频繁读写内存的某个变量,那最常见的优化方式就是先把变量转移到高速缓存里来,在STM32内核里,有一个类似缓存的工作组寄存器,这些寄存器的访问速度最快,我先把变量放在缓存里,需要读写的时候,直接访问缓存就行了,用完之后,再写回内存,这是一个优化方案,但是,如果你的程序里有多个线程,比如中断函数,在中断函数里,你改变了这个原始变量,那可能缓存并不知道你更改了,下次程序还看缓存的变量,就会造成数据更改不同步的问题,这时,我们的做法也是,读取变量定义的前面加上一个volatile,告诉编译器这个变量是易变的,每次读取你都得执行到位,要直接从内存里找,不要再用缓存优化了,所以总结-下就是,如果开启了编译器优化,在无意义加减变量,多线程更改变量,读写与硬件相关的存储器时都需要加上volatile,防止被编译器优化,如果你默认,不开编译器优化,那就无所谓了,加不加都一样
其中,读取,可以直接读,写入,需要解锁,并且执行后面的流程
5.1 程序存储器全擦除
第 步是读取LOCK位,看一下芯片锁没锁,下面,如果LOCK位=1,锁住了,就执行解锁过程,在KEYR寄存器,先写入KEY1,再写入KEY2,这里,如果它当前没锁住就不用解锁了,在库函数中,并没有这个判断,库函数是直接执行解锁过程,解锁之后,首先,置控制寄存器里的MER(Mass Erase)位为1,然后再置STRT(Start)位为1,其中置STRT为1是触发条件,STRT为1之后,芯片开始干活,然后芯片看到,MER位是1,它就知道,接下来要干的活就是全擦除,这样内部电路就会自动执行全擦除的过程,然后继续擦除也是需要花一段时间的,所以擦除过程开始后程序要执行等待,判断状态寄存器的BSY(BuSy)位是否为1,BSY位表示芯片是否处于忙状态,BSY为1,表示芯片忙,所以这里,如果判断BSY=1,就跳转回来,继续循环判断,直到BSY=0,跳出循环,这样全擦除过程就结束了,最后一步,这里写的是读出并验证所有页的数据,读出并验证所有页的数据,这个是测试程序才要做的,正常情况下,全擦除完成了,我们默认就是成功了
5.2 程序存储器页擦除
第一步,上面这块一样的,是解锁的流程,第二步,这个方框里的置控制寄存器的PER(Page Erase) 位为1,然后,在AR(Address Register)地址寄存器中选择要擦除的页,最后,置控制寄存器的STRT位为1,置STRT为1,也是触发条件,STRT为1,芯片开始干活,然后芯片看到,PER=1,它就知道,接下来要执行页擦除,然后闪存不止一页,页擦除,芯片就要知道要具体要擦哪一页,所以,它会继续看AR寄存器的数据,AR寄存器我们要提前写入一个页起始地址,这样芯片就会把我们指定的一页,给擦除掉,然后擦除开始之后,我们也需要等待BSY位,最后,读出并验证数据,这个就不用看了,这就是页擦除的过程
5.3 程序存储器编程
擦除之后,我们就可以执行写入的流程了,另外说明一下,STM32的闪存在写入之前会检查指定地址有没有擦除,如果没有擦除就写入,STM32则不执行写入操作,除非写入的全是0,这一个数据是例外,因为不擦除就写入,可能会写入错误,但全写入0的话,写入肯定是没问题的,写入的第一步,也是解锁,然后第二步,我们需要置控制寄存器的PG(Programming)位为1,表示我们即将写入数据,之后第三步,就是在指定的地址写入半字,这步,我们需要用到刚才说的这句代码使用指针,在指定地址写入数据,想写入什么数据在这里指定即可,另外这里注意写入操作,只能以半字的新式写入,其中字,Word,就是32位数据,半字,HalfWord,就是16位数据,字节,Byte,就是8位数据,如果你要写入32位,就分两次完成,这个就比较麻烦了,如果你想单独写入一个字节,还要保留另一个字节的原始数据的话,那就只能把整页数据都读到SRAM,再随意修改SRAM数据,修改全部完成之后再把墪页都擦除,最后再把整页都写回去,所以,如果你想像SRAM一样随心所欲的读写,那最好的加法就是先把闪存的一页读到SRAM中,读写完成后,再擦除一页,整体写回去,那回到流程图这里,写入数据这个代码,就是触发开始的条件,不需要像擦除一样,置STRT位了,写入半字之后,芯片会处于忙状态,等待BSY位清0,这样写入数据的过程就完成了,那每执行这样一个流程,只能写入一个半字,如果要写入很多数据,那就不断循环调用这个流程,就可以了
6.选项字节
首先这里是选项字节的组织和用途,图里的起始地址就是我们刚才说的选项字节的起始地址1FFFF800,这一块的这些数据就是前面的用户选项字节,里面总共只有16个字节,其中有一半的名称,前面都带了个n,比如RDP和nRDP,这个意思就是你在写入RDP数据时,要同时在nRDP写入数据的反码,这样写入操作才是有效的,如果芯片检测到这两个存储器不是反码的关系,那就代表数据无效,有错误,对应的功能就不执行,这是一个安全保障措施,当然这个写入反码的过程,硬件会自动计算,并写入
1位保护4x8=32页,总共保护32*4=128页,正好对应中容量的最大128页
7.器件电子签名
也就是每个芯片的身份证号,这个数据存放的基地址是1FFFF7E8,每一个芯片的这96位数据都是不一样的,使用这个唯一ID号可以做一些加密的操作,比如你想写入一段程序只能在指定设备运行,那就可以在程序的多处加入ID号判断,如果不是指定设备的ID号,就不执行程序功能,,这样即使你的程序被盗,在别的设备上也难以运行,这就是STM32的电子签名
相关文章:

STM32—FLASH闪存
1.FLASH简介 STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分,通过闪存存储器接口(外设)可以对程序存储器和选项字节进行擦除和编程 我们怎么操作这些存储器呢?这就需要用到这个闪存存储器接口了,闪…...

AP上线的那些事儿(1)capwap建立过程、设备初始化以及二层上线
1、了解FITAP与AC的建立过程 之前我们已经知道了FATAP与FIT是一对双胞胎一样的兄弟,FAT哥哥能够直接独立使用当AP桥接、路由器等,而弟弟FIT则比较薄弱,独自发挥不出功效,需要一位师傅(AC)来带领,…...

10 django管理系统 - 管理员管理 - 新建管理员(通过模态框和ajax实现)
在文章“04 django管理系统 - 部门管理 - 新增部门”中,我们通过传统的新增页面来实现部门的添加。 在本文中,我们通过模态框和ajax来实现管理员的新增。 首先在admin_list.html中新建入口,使用按钮 <div class"panel-heading&quo…...

Mysql中表字段VARCHAR(N)类型及长度的解释
本文将针对MySQL 中 varchar (N)类型字段的存储方式进行解释,主要是对字符和字节的关系的理解。 1. varchar (N) 中的 N varchar (N) 中的 N 表示字符数,而不是字节数。这意味着 N 表示你可以存储多少个字符。 字符数:指的是字符的个数&…...

git提交信息写错处理方式
在Git中,你可以通过使用rebase命令来合并提交记录。以下是一个简单的步骤来合并一系列提交: 使用git rebase -i开始交互式变基。在打开的编辑器中,你会看到一个提交列表。若要合并提交,将要合并的提交前面的pick改为squash或s。保…...

C#从零开始学习(用unity探索C#)(unity Lab1)
初次使用Unity 本章所有的代码都放在 https://github.com/hikinazimi/head-first-Csharp Unity的下载与安装 从 unity官网下载Unity Hub Unity的使用 安装后,注册账号,下载unity版本,然后创建3d项目 设置窗口界面布局 3D对象的创建 点击对象,然后点击Move Guzmo,就可以拖动…...

【SpringBoot】15 Echarts+Thymeleaf 绘制各种图表
Gitee仓库 https://gitee.com/Lin_DH/system 介绍 ECharts是百度开源的一个前端组件。它是一个使用 JavaScript 实现的开源可视化库,可以流畅的运行在 PC 和移动设备上,兼容当前绝大部分浏览器(IE8/9/10/11,Chrome,…...

网络学习笔记
一、网络的结构与功能 网络的鲁棒性与抗毁性 如果在移走少量节点后网络中的绝大部分节点仍然是连通的,那么就该网络的连通性对节点故障具有鲁棒性 网络上的动力学 动力系统:自旋、振子或混沌的同步、可激发系统 传播过程:信息传播与拥堵…...

[论文笔记]HERMES 3 TECHNICAL REPORT
引言 今天带来论文HERMES 3 TECHNICAL REPORT,这篇论文提出了一个强大的工具调用模型,包含了训练方案介绍。同时提出了一个函数调用标准。 为了简单,下文中以翻译的口吻记录,比如替换"作者"为"我们"。 聊天模…...

MySQL-19.多表设计-一对多-外键
一.多表问题分析 二.添加外键 三.外键约束的问题...

MySQL程序介绍<一>
目录 MySQL程序简介 mysqld - MySQL 服务器 编辑 mysql - MySQL 命令⾏客⼾端 MySQL程序简介 1.MySQL安装完成通常会包含如下程序: Linux系统程序⼀般在 /usr/bin⽬录下,可以通过命令查看 windows系统⽬录: 你的安装路径\MySQL Server…...

Leetcode 第 419 场周赛题解
Leetcode 第 419 场周赛题解 Leetcode 第 419 场周赛题解题目1:3318. 计算子数组的 x-sum I思路代码复杂度分析 题目2:3319. 第 K 大的完美二叉子树的大小思路代码复杂度分析 题目3:思路代码复杂度分析 题目4:3321. 计算子数组的 …...

那些年 我们说走就走
那些年 我们说走就走 —— 2022-03-20 二月十八 春分 我总是钟情于原生景色,犹如那句 “落霞与孤鹜齐飞,秋水共长天一色。” 所绘。 我热爱骑行,向往自然,对有着 “中国人的景观大道” 之称的 318 国道川藏线憧憬已久。 17 年暑…...

MySQL初识
在了解什么是MySQL前,我们先了解一下什么是数据库?? 1. 数据库简介 1.1 什么是数据库 数据库是20世纪60年代末发展起来的⼀项重要技术,已经成为计算机科学与技术的⼀个重要分⽀。数据库技术主要是⽤来解决数据处理的⾮数值计算问…...

基于Java微信小程序的的儿童阅读系统的详细设计和实现(源码+lw+部署文档+讲解等)
详细视频演示 请联系我获取更详细的演示视频 项目运行截图 技术框架 后端采用SpringBoot框架 Spring Boot 是一个用于快速开发基于 Spring 框架的应用程序的开源框架。它采用约定大于配置的理念,提供了一套默认的配置,让开发者可以更专注于业务逻辑而不…...

利用 OBS 推送 WEBRTC 流到 smart rtmpd
webrtc whip 推流 & whep 拉流简介 RFC 定义 通用的 webrtc 对于 SDP 协议的交换已经有对应的 RFC 草案出炉了。这就是 WHIP( push stream ) & WHEP ( pull stream ) . WHIP RFC Link: https://www.ietf.org/archive/id/draft-ietf-wish-whip-01.html WHEP RFC Link:…...

【python】极简教程3-函数
函数是将代码组织到可重用块中的一种方法。 函数调用 Python提供了许多内置函数,例如print: print(Hello, World!)函数调用通常包含函数名,后跟圆括号,括号内是参数列表。参数是传递给函数的数据,函数会基于这些数据执行操作。 数学函数 使用math函数前需要先导入mat…...

Python案例小练习——小计算器
文章目录 前言一、代码展示二、运行展示 前言 这是用python实现一个简单的计器。 一、代码展示 def calculate(num1, op, num2):if op "":return float(num1) float(num2)elif op "-":return float(num1) - float(num2)elif op "*":return…...

仓储数字化蓝图
1、仓储能力建设 2、仓储数字化建设...

【数字图像处理】第5章 图像空域增强方法
上理考研周导师的哔哩哔哩频道 我在频道里讲课哦 目录 5.1 图像噪声 相关概念 ①图像噪声的产生 ② 图像噪声分类 ③ 图像噪声特点 5.2 图像增强方法分类 ①图像增强概念 ②图像增强目的 ③图像增强技术方法: 5.3 基于灰度变换的图像增强 1. 概述: 2. 灰度变换…...

idea 发布jar包
当你有一个能正常编译的项目,以springboot为例,有两步步骤 打包配置 打包 一、打包配置 1.点击右上角快捷按钮/文件-->项目结构,打开项目结构设置 2.项目结构-->Artifacts,如图所示选择 3.在Create JAR from Modules配置…...

c语言字符串函数strstr,strtok,strerror
1,strtok函数的使用和模拟实现 char * strtok(char * str,const char * sep) 会有static修饰变量,有记忆功能,会保存字符串的位置,下次找再继续找。 1)sep参数指向一个字符串,它包含了0个或者多个由sep字符中一个或…...

【Java】—JavaBean转换方法详解
JavaBean间的转换 ⭐⭐⭐⭐⭐⭐ Github主页👉https://github.com/A-BigTree 笔记链接👉https://github.com/A-BigTree/Code_Learning ⭐⭐⭐⭐⭐⭐ 如果可以,麻烦各位看官顺手点个star~😊 文章目录 JavaBean间的转换1 Apache Co…...

[Vue3核心语法] setup语法糖
一、setup 概述 setup是Vue3中一个新的配置项,值是一个函数,它是 Composition API “表演的舞台”,组件中所用到的:数据、方法、计算属性、监视......等等,均配置在setup中。 特点: setup函数返回的对象中…...

RabbitMQ 入门(三)SpringAMQP五种消息类型(Basic Queue)
一、Spring AMQP 简介 SpringAMQP是基于RabbitMQ封装的一套模板,并且还利用SpringBoot对其实现了自动装配,使用起来非常方便。 SpringAmqp的官方地址:https://spring.io/projects/spring-amqp SpringAMQP提供了三个功能: - 自动…...

2024双十一买什么好?双十一高性价比数码好物推荐!
双十一购物狂欢节即将来临,这是一年中家电和数码产品优惠力度较大的时候。然而,随着产品种类越来越丰富,选择一款合适的商品也变得越发困难。今天,我为大家推荐一些双十一期间值得入手的高品质好物,让我们一同来了解…...

MySQL 查找连续相同名称的记录组,并保留每组内时间最大的一条记录
要求:查找连续相同名称的记录组,并保留每组内时间最大的一条记录,同时计算每组记录的 num 总和。 今天有人问了我一个问题,大致就是下面这样的数据结构(原谅我实在不知道怎么描述这个问题) 然后需要得到下面…...

three.js 使用geojson ,实现中国地图区域,边缘流动效果
three.js 使用geojson ,实现中国地图区域,边缘流动效果 在线链接:https://threehub.cn/#/codeMirror?navigationThreeJS&classifyexpand&idgeoBorder 国内站点预览:http://threehub.cn github地址: https://github.co…...

数据中台业务架构图
数据中台的业务架构是企业实现数据驱动决策和业务创新的关键支撑。它主要由数据源层、数据存储与处理层、数据服务层以及数据应用层组成。 数据源层涵盖了企业内部各个业务系统的数据,如 ERP、CRM 等,以及外部数据来源,如社交媒体、行业数据…...

Docker学习笔记(2)- Docker的安装
1. Docker的基本组成 镜像(image):Docker镜像就像是一个模板,可以通过这个模板来创建容器服务。通过一个镜像可以创建多个容器。最终服务运行或者项目运行就是在容器中。容器(container):Docker…...