STM32 Flash
FLASH简介
Flash是常用的用于存储数据的半导体器件,它具有容量大,可重复擦写,按“扇区/块”擦除、掉电后数据可继续保存的特性。
常见的FLASH主要有NOR FLASH和NAND FLASH两种类型。NOR和NAND是两种数字门电路,可以简单地认为FLASH内部存储单元使用哪种门作存储单元就是哪种类型的FLASH。
U盘,SSD,eMMC等为NAND型,而NOR FLASH则根据设计需要灵活应用于各类PCB上,如BIOS,手机等。

NOR与NAND在数据写入前都需要有擦除操作。
但实际上NOR FLASH的一个bit可以从1变成0,而要从0变1就要擦除后再写入,NAND这两种情况都需要擦除。
擦除操作的最小单位为“扇区/块”,这意味着有时候即使只写一字节的数据,这个扇区/块上之前的数据都可能会被擦除。
NOR的地址线和数据线分开,它可以按“字节”读写数据,符合CPU的指令译码执行要求,所以假如NOR上存储了代码指令,CPU给NOR一个地址,NOR就能向CPU返回一个数据让CPU执行,中间不需要额外的处理操作,其中依靠XIP(eXcutable In Place)。因此可以用NOR FLASH直接作为嵌入式MCU的程序存储空间。
NAND的数据和地址线共用,只能按块来读写数据,假如NAND上存储了代码指令,CPU给NAND地址后,它无法直接返回该地址的数据,所以不符合指令译码要求。
若代码存储在 NAND 上,可以把它先加载到 RAM 存储器上,再有 CPU 执行。所以在功能上可以认为 NOR 是一种断电后数据不丢失的 RAM,但它的擦除单位与 RAM 有区别,且读写速度比 RAM 要慢得多。
FLASH 也有对应的缺点,我们在使用过程中需要尽量去规避这些问题:一是 FLASH 的使用率,另一个是可能的位反转。
使用寿命体现在:读写上,FLASH的擦除次数都是有限的(NOR FLASH普遍是10万次左右),当它的使用接近寿命的时候,可能会出现写操作失败。由于NAND通常是整块擦写,块内有一位失效,整个块就会失败,这称为坏块。使用NAND FLASH最好通过算法扫描介质找出坏块并标记为不可用,因为坏块上的数据是不准确的。
位反转是数据位写入时为1,但经过一定时间的环境变化后可能实际变为0的情况,反之亦然。位反转的原因很多,可能是器件特性,也可能由于环境干扰。由于位反转的问题可能存在,所以FLASH存储器需要“探测/错误更正”算法来确保数据的正确性。
FLASH 芯片有很多种芯片型号,在我们的 norflash.h 头文件中有定义芯片 ID 的宏定义,对应的就是不同型号的 NOR FLASH 芯片,比如有:W25Q64、BY25Q64、NM25Q64,它们是来自不同的厂商的同种规格的 NOR FLASH 芯片,内存空间都是 64M 字,即 8M 字节。它们的很多参数、操作都是一样的,所以我们的实验都是兼容它们的。
由于这么多的芯片,我们就不一一进行介绍了,就拿其中一款型号进行介绍即可,其他的型号都是类似的。
下面我们以华邦的 W25Q64 为例,认识一下具体的 NOR FLASH 的特性。




FLASH模拟EEPROM
EEPROM是一种掉电后数据不丢失的存储器,常用来存储一些配置信息,在系统重新上电时就可以加载。
STM32本身没有自带EEPROM,但是STM32具有IAP(在应用编程)功能,所以我们可以把FLASH当成EEPROM来使用。


STM32内部FLASH简介
在STM32芯片内部有一个FLASH存储器,主要用于存储代码。

根据内存容量划分为几个密度等级:

不同密度等级的FLASH,其组织结构也不一样。

内部FLASH构成
内部FLASH主要由三部分组成:主存储器、信息块、闪存存储器接口寄存器。

- 主存储器:用来存放代码和数据常量(如const类型的数据)
- 信息块:分为两个部分,系统存储(启动程序代码)、选项字节(用户选项字节)
- 闪存存储器接口寄存器:用于控制闪存读写等,是整个闪存模块的控制结构
主存储器,该部分用来存放代码和数据常数(如 const 类型的数据)。对于大容量产品,其被划分为 256 页,每一页 2K 字节。注意,小容量和中容量产品则每页只有 1K 字节。从上图可以看出主存储器的起始地址就是 0x08000000,B0、B1 都接 GND 的时候,就是从0x08000000 开始运行代码的。
信息块,该部分分为2个小部分,其中启动程序代码,用来存储ST自带的启动程序,用来串口下载代码。当 B0 接 3V3,B1 接 GND 的时候,运行的就是这部分代码。用户选中字节,则一般用于配置写保护、读保护等功能。
闪存存储器接口寄存器,该部分用于控制闪存读写等,是整个闪存模块的控制结构。
对主存储器和信息块的写入由内嵌的闪存编程/擦除控制器(FPEC)管理;编程与擦除的高电压由内部产生。
在执行闪存写操作时,任何对闪存的读操作都会锁住总线,在写操作完成后读操作才能正确地进行。既在进行写或擦除操作时,不能进行代码或数据的读取操作。
FLASH读写过程
对FLASH的核心操作就是读和写。
FLASH的物理特性:只能写0,不能写1,写1靠擦除。
闪存的读取
直接在通用地址空间直接寻址,任何32位数据的读操作都能访问闪存模块的内容并得到相对应的数据。

CPU通过ICode指令总线访问FLASH指令,通过DCode数据总线访问FLASH数据。
CPU运行速度比FLASH快得多,STM32F103的FLASH最快访问速度≤24MHz,CPU超过这个速度,得加入等待时间,否则读写FLASH可能出错,导致死机等情况。
正确设置好等待周期后,利用指针读取数据。
从地址addr,读取数据(字节为8位,半字为16位,字为32位)
data = *(volatile uint8_t *)addr; /* 读取一个字节数据 */
data = *(volatile uint16_t *)addr; /* 读取一个半字数据 */
data = *(volatile uint32_t *)addr; /* 读取一个字的数据 */
将addr强制转换为uintx_t指针,然后取该指针所指向地址的值,即可获得addr地址的数据。
在这个代码片段中,‘volatile’关键字用于告诉编译器,所涉及的内存位置可能会在程序的执行过程中被意外地更改,而不是由程序代码直接引起的。
通常来说,编译器会对代码进行优化,例如缓存变量的值,假设在执行流程中它们不会在未被程序代码显示修改的情况下改变。这种优化可能会导致对某些变量的读取操作不会实时地从内存中获取值,而是使用已经缓存的值。在一些特殊情况下,这种优化可能会导致问题,特别是在与硬件相关的代码中,其中寄存器的值可能会由硬件异步地发生变化。
通过使用’volatile’,告诉编译器不要对这个变量进行优化,而是始终从内存中读取起当前值。这对于需要实时地反映硬件状态变化的情况非常重要,因此在嵌入式系统、驱动程序等场景中经常会看到 volatile 的使用。
闪存的写入
闪存编程是由FPEC(闪存编程和擦除控制器)模块处理的。
这个模块包含 7 个 32位寄存器,它们分别是:
⚫ FPEC 键寄存器(FLASH_KEYR)
⚫ 选择字节键寄存器(FLASH_OPTKEYR)
⚫ 闪存控制寄存器(FLASH_CR)
⚫ 闪存状态寄存器(FLASH_SR)
⚫ 闪存地址寄存器(FLASH_AR)
⚫ 选择字节寄存器(FLASH_WRPR)
其中 FPEC 键寄存器总共有 3 个键值:
RDPRT 键 = 0X0000 00A5
KEY1 = 0X4567 0123
KEY2 = 0XCDEF 89AB
写操作有四步:
- 解锁
- 擦除
- 写数据
- 上锁
STM32复位后,FPEC模块是被保护的,不能写入FLASH_CR;通过写入特定的序列到 FLASH_KEYR 寄存器可以打开 FPEC 模块(即写入 KEY1 和 KEY2),只有在写保护被解除后,我们才能操作相关寄存器。

相关文章:
STM32 Flash
FLASH简介 Flash是常用的用于存储数据的半导体器件,它具有容量大,可重复擦写,按“扇区/块”擦除、掉电后数据可继续保存的特性。 常见的FLASH主要有NOR FLASH和NAND FLASH两种类型。NOR和NAND是两种数字门电路,可以简单地认为FL…...
文件批量重命名技巧:图片文件名太长怎么办?告别手动改名方法
在日常生活中,常常会遇到文件名过长导致的问题。尤其是在处理大量图片文件时,过长的文件名可能会使得文件管理变得混乱不堪。现在来看下云炫文件管理器如何批量重命名,让图片文件名变得更简洁,提高工作效率。 操作1、在云炫文件…...
微信小程序手写滑动tab
微信小程序手写滑动tab index.wxml <view class"tab-bar"> <scroll-view scroll-x class"tab-scroll"> <block wx:for"{{tabs}}" wx:key"index"> <view class"tab-item {{currentIndex index ? acti…...
一文读懂如何安全地存储密码
目录 引言 明文存储 基本哈希存储 加盐哈希存储 适应性哈希算法 密码加密存储 小结 引言 密码是最常用的身份验证手段,既简单又高效。密码安全是网络安全的基石,对保护个人和组织信息的安全具有根本性的作用。然而有关密码泄漏的安全问题一再发生…...
【运维面试100问】(六)buffer和cache的区别
本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》:python零基础入门学习 《python运维脚本》: python运维脚本实践 《shell》:shell学习 《terraform》持续更新中:terraform_Aws学习零基础入门到最佳实战 《k8…...
创建域名邮箱邮件地址的方法与步骤
如何创建域名邮箱邮件地址?使用Zoho Mail创建域名邮箱邮件地址的步骤简单易懂,操作便捷。从其他邮箱迁移到Zoho Mail的过程也相当顺畅,您可以轻松为所有员工创建具有企业邮箱域名的电子邮件地址。 步骤1:添加并验证您的域名 首先,…...
Qt框架学习(1)
1.安装Qt官网 安装需注意的是,要安装开源版(有钱当我没说),而安装包都是一样的,主要是在注册账户时选择个人开发,而不要选公司,否则在安装时登录账号后会安装商业版Qt. 2.Qt中的快捷键 快捷键解释F4头文件和实现文件切换ShiftF…...
3D电路板在线渲染案例
从概念上讲,这是有道理的,因为PCB印制电路板上的走线从一个连接到下一个连接的路线基本上是平面的。 然而,我们生活在一个 3 维世界中,能够以这种方式可视化电路以及相应的组件,对于设计过程很有帮助。本文将介绍KiCad中基本的3D查看功能,以及如何使用NSDT 3DConvert在线…...
ResizeObserver loop limit exceeded报错解决方案
前言: 控制台没有报错,但是开发Vue项目过程中一直报ResizeObserver loop limit exceeded 错,找到以下解决方式。在main.js文件中重写 ResizeObserver 方法。 main.js文件 (完整版) import { createApp } from "v…...
【OpenCV实现图像:使用OpenCV进行图像处理之透视变换】
文章目录 概要计算公式举个栗子实际应用小结 概要 透视变换(Perspective Transformation)是一种图像处理中常用的变换手段,它用于将图像从一个视角映射到另一个视角,常被称为投影映射。透视变换可以用于矫正图像中的透视畸变&…...
Vue中学习笔记-数据代理
文章目录 前文提要数据代理的概念MVVM模型和Vue中的数据代理M,模型V,视图VM,视图模型 前文提要 本人仅做个人学习记录,如有错误,请多包涵 数据代理的概念 使用一个对象代理对另一个对象中属性的操作。 MVVM模型和Vu…...
IDEA 配置maven结合案例使用篇
1. 项目需求和结构分析 需求案例:搭建一个电商平台项目,该平台包括用户服务、订单服务、通用工具模块等。 项目架构: 用户服务:负责处理用户相关的逻辑,例如用户信息的管理、用户注册、登录等。 spring-context 6.0.…...
基于白鲸算法优化概率神经网络PNN的分类预测 - 附代码
基于白鲸算法优化概率神经网络PNN的分类预测 - 附代码 文章目录 基于白鲸算法优化概率神经网络PNN的分类预测 - 附代码1.PNN网络概述2.变压器故障诊街系统相关背景2.1 模型建立 3.基于白鲸优化的PNN网络5.测试结果6.参考文献7.Matlab代码 摘要:针对PNN神经网络的光滑…...
Android使用Kotlin利用Gson解析多层嵌套Json数据
文章目录 1、依赖2、解析 1、依赖 build.gradle(app)中加入 dependencies { implementation com.google.code.gson:gson:2.8.9 }2、解析 假设这是要解析Json数据 var responseStr "{"code": 200,"message": "操作成功","data&quo…...
DOM事件的传播机制
DOM事件的传播机制是指当一个事件在DOM树中触发时,它是如何在各个元素之间传播的。DOM事件传播机制分为三个阶段:捕获阶段、目标阶段和冒泡阶段。此外,还有一种常用的技术称为事件委托,它能够简化事件处理程序的绑定和管理。本文将…...
gitlab利用CI多工程持续构建
搭建CI的过程中有多个工程的时候,一个完美的构建过程往往是子工程上的更新(push 或者是merge)触发父工程的构建,这就需要如下建立一个downstream pipeline 子仓库1 .gitlab-ci.yml stages:- buildbuild_job:stage: buildtrigger:project: test_user/tes…...
【C++初阶】四、类和对象(构造函数、析构函数、拷贝构造函数、赋值运算符重载函数)
相关代码gitee自取: C语言学习日记: 加油努力 (gitee.com) 接上期: 【C初阶】三、类和对象 (面向过程、class类、类的访问限定符和封装、类的实例化、类对象模型、this指针) -CSDN博客 引入:类的六个默认成员函数…...
js粒子效果(二)
效果: 代码: <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Particle Animation</title><…...
01.让自己习惯C++
让自己习惯C 条款1:视C为一个语言联邦 条款1中提到了将C看作为一个“语言联邦”的概念。具体来说,“语言联邦”是指将C看作由多种不同的子语言组成的联邦。每种子语言都有自己的惯用法、工具和库,可以用来解决特定的问题。因此,…...
ElementUI table+dialog实现一个简单的可编辑的表格
table组件如何实现可编辑呢? 我的需求是把table组件那样的表格,实现它点击可以弹出一个框,然后在这个框里面输入你的东西,然后将他回显回去,当然,输入的有可能是时间啥的。 为什么要弹出弹层不在框上直接…...
内存分配函数malloc kmalloc vmalloc
内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
【Linux】C语言执行shell指令
在C语言中执行Shell指令 在C语言中,有几种方法可以执行Shell指令: 1. 使用system()函数 这是最简单的方法,包含在stdlib.h头文件中: #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...
高频面试之3Zookeeper
高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个?3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制(过半机制࿰…...
【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例
文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...
【论文笔记】若干矿井粉尘检测算法概述
总的来说,传统机器学习、传统机器学习与深度学习的结合、LSTM等算法所需要的数据集来源于矿井传感器测量的粉尘浓度,通过建立回归模型来预测未来矿井的粉尘浓度。传统机器学习算法性能易受数据中极端值的影响。YOLO等计算机视觉算法所需要的数据集来源于…...
【Go语言基础【13】】函数、闭包、方法
文章目录 零、概述一、函数基础1、函数基础概念2、参数传递机制3、返回值特性3.1. 多返回值3.2. 命名返回值3.3. 错误处理 二、函数类型与高阶函数1. 函数类型定义2. 高阶函数(函数作为参数、返回值) 三、匿名函数与闭包1. 匿名函数(Lambda函…...
GitFlow 工作模式(详解)
今天再学项目的过程中遇到使用gitflow模式管理代码,因此进行学习并且发布关于gitflow的一些思考 Git与GitFlow模式 我们在写代码的时候通常会进行网上保存,无论是github还是gittee,都是一种基于git去保存代码的形式,这样保存代码…...
[ACTF2020 新生赛]Include 1(php://filter伪协议)
题目 做法 启动靶机,点进去 点进去 查看URL,有 ?fileflag.php说明存在文件包含,原理是php://filter 协议 当它与包含函数结合时,php://filter流会被当作php文件执行。 用php://filter加编码,能让PHP把文件内容…...
