STM32 Flash详解教程文章

news2025/4/1 5:23:18

 目录

Flash基本概念理解

Flash编程接口FPEC

Flash擦除/写入流程图

Flash选项字节基本概念理解

Flash电子签名

函数读取地址下存放的数据

Flash的数据处理限制部分


                                            编写不易,请勿搬运,感谢理解!!!

Flash基本概念理解

        STM32的Flash里面包含,程序存储器系统存储器选项字节,通过对Flash闪存的片上外设接口(接口地址在ram地址),可以对程序存储器跟选项字节进行擦除和编程。

·程序存储器:用来下载存放程序的位置

·系统存储器:用来存放BootoLoader芯片出厂自带程序

·选项字节:用来配置Flash读保护,写保护,等功能

        其常见在程序中的用法是,通过程序软件编程利用内部Flash数据掉电不丢失的特性与内部Flash通常不用使用完,将重要的参数存储在Flash的最后几页内

        和使用指针指向系统存储区域内,芯片的ID号地址,读取属于芯片自己的ID号,通过利用芯片不同的ID号,在程序执行时判断芯片ID号,如果不同则不执行程序,来实现程序只能在特定芯片上运行。

        最后一种用法就是通过对Flash的选项字节配置,来完成程序的读保护跟写保护,在程序中来配置。

                                                        flash分配地址详解

        在STM32F1系列芯片中,其中Flash每页的起始地址后三位均以 000 400 800 C00 开头。

Flash编程接口FPEC

        Flash编程控制器 FPEC 全称是 Flash Program/Erase Controller 用于对Flash存储器进行读写和擦除的硬件模块。该模块包含7个32位寄存器。

·FPEC键寄存器(FLASH_KEYR):用于解锁FPEC外设,允许进行Flash编程或擦除操作

·选择字节键寄存器(FLASH_OPTKEYR):用于解锁Flash选项字节的修改操作

·闪存控制寄存器(FLASH_CR):控制Flash编程和擦除操作的核心寄存器

·闪存状态寄存器(FLASH_SR):指示Flash当前状态和操作结果

·闪存地址寄存器(FLASH_AR):指定Flash操作的目标地址

·选择字节寄存器(FLASH_OBR):读取选项字节当前的配置状态

·写保护寄存器(FLASH_WRPR):指示和配置Flash的写保护状态

        7个寄存器中需要注意的是,Flash_SR寄存器的BSY位,当该位为1的时候代表正在进行flash操作,当为0的时候代表操作结束或者发生错误,通常来读取该位的值来判断flash操作是否完成结束。

        Flash_CR寄存器的PG位代表是否选择编程操作,PER位是否选择页擦除操作,MER位是否选择全擦除操作,OPTPG选择字节编程,OPTER擦除选择字节,STRT开始操作,该位为1的时候将触发擦除操作,只能由软件置1并在BSY为1的时候清除为0,LOCK锁为1代表FPEC和Flash_CR被锁住,为0代表解锁成功。

                                                            寄存器地址范围图

        在芯片复位后,FPEC模块是被保护的,Flash_CR寄存器不能被读写操作,首先需要对,Flash_KEYR写入特定键值KEY1  KEY2 来完成解锁操作,如果写入错误会在下次复位之前锁死,FPEC跟Flash_CR寄存器。

·RDPRT键 = 0x000000A5    //解除读保护

·KEY1 = 0x45670123           //KEY1+KEY2解除FPEC锁

·KEY2 = 0xCDEF89AB

        需要注意的是,在解锁FPEC对Flash_CR寄存器操作完成对Flash的读|写之后,需要设置Flash_CR中的LOCK位锁住FPEC跟Flash_CR位,来防止数据的误写入导致对Flash进行操作。

Flash擦除/写入流程图

                                                Flash写入数据流程图

                                                        Flash页擦除流程图

                                                        Flash全擦除流程图

        在三张流程图中只有擦除流程图需要置Flash_CR寄存器的STRT位为1,在上文有介绍过当为1的时候会执行擦除操作,然后当Flash_SR寄存器的BSY为0的是时候会将STRT位置0。

Flash选项字节基本概念理解

       在芯片地址中给选项字节分配了16个字节的地址,其中8个字节的地址用来备份,当前选项字节的数据,只有8个字节用来配置Flash选项字节。其中四个字节用来写保护,1个字节用来读保护,1个字节配置选项,2个字节存储用户数据。  

                                                        分配地址图

       需要注意的是,在完成对FPEC的解锁之后,还需要再次对Flash_OPTKKEYR写入KEY1 KEY2来完成对选项字节的解锁,同事置Flash_CR的OPTWRE位为1才能对选项字节进行写入操作。 

         

·RDP:写入RDPRT键(0x000000A5)后解除读保护

·USER:硬件看门狗配置 停机模式|待机模式 是否产生复位

·Data:用户自定义数据

·WRP:该位置用来配置写保护

Flash电子签名

        电子签名是芯片出厂的时候由芯片制造商写入的信息,存放地址实在系统存储区域,用来表示芯片的唯一性跟芯片的flash容量大小。

·0x1FFFF7E0 ~ 0x1FFFF7E3 存放flash大小

·0x1FFFF7E8 ~ 0x1FFFF7EF 存储 UID。

        其中UID Uniqune Device ID 唯一设备标识,共96位12字节改信息用户不可更改,可以利用指针进行访问。

函数读取地址下存放的数据

       上文中提到了在大多数单片机程序中因为自身Flash没有被使用完,因此可以对剩余Flash空间进行读写数据操作函数如下。

uint32_t FlashR_Word(uint32_t address)
{
    return *((__IO uint32_t *)(address))
}

        函数中__IO来自官方定义库文件定义如下

#define __IO  voliate

        将宏定义带入到函数中就能得到下面代码

(__IO uint32_t *)(address) = (volitate uint32_t *)(address)

        改代码作用是将函数局部变量参数转化为指向该参数的uint32_t,指针类型,同时括号外面的*就是指针解引用的意思,就是返回指针指向该地址下的数值,这里因为声明的指针类型为uint32_t类型所以就能返回一个字的地址。

        也就是32位数据,4个字节的数据,同理可以得到读取16位数据的函数,还有读取一个字节的函数,只要把函数内声明的指针类型给改了就行了

uint16_t FlashR_HWord(uint32_t address)
{
    return *((__IO uint16_t *)(address))
}

uint8_t FlashR_Byte(uint32_t address)
{
    return *((__IO uint8_t *)(address))
}
//这里因为改变了 内部声明的指针类型 跟返回值类型所以能获取的数据大小也被限制了

Flash的数据处理限制部分

        在对Flash进行数据存储的通常情况下需要再程序中定义一个 uint16_t data[512] 数组,大小是1024也就是一个Flash页面大小,先将数据写入ram的数组里面然后再写入Flash里面进行存储,通常这种情况是因为Flash本身的写入限制问题。

       首先Flash擦除的最小单位是页,同时在Flash进行写入的时候不存在数据覆盖这种写法,也就是将数据0x12345对改地址重新写入数据0x56787是写不进去的是因为Flash中的数据只能从1->0,而不能从0->1,而在擦除完单页Flash之后,该页存储的数据全部为0xFFFF FFFF 也就是全部是1。

        这就导致了如果直接对Flash进行数据写入,会发现在数据写入到最后的时候如果想要更改前面的数据大概率是需要擦除才能进行写入的,但是如果进行擦除其他位的数据又丢失,所以通常常用的数据数据手段也就是。

        将Flash单页数据读出保存在一个Flash页大小的数组里面进行更改数据,然后将整页数据重新写入到Flash数组里面来完成操作,跟将需要写入的数据先在数组里面进行覆盖,最后统一写入Flash里面。

Step 1:先从 Flash 读取数据到 RAM
Step 2:在 RAM 修改数据
Step 3:擦除 整个 Flash Page(Flash 只能整页擦除)。
Step 4:将 RAM 数据重新写入 Flash

#include "stm32f10x.h"
#include "Store.h"
#include "MyFlash.h"
//数组内512个数据 每个数据类型是 uint16_t 也就是2个字节 数组能存放1024字节数据 也就是对应Flash一页的容量
uint16_t Store_Data[512];
//在ram 里面定义一个数组 需要备份的时候统一转到闪存里面
void Flash_Init(void)
{

	if(Flash_WHWord(0x08000000)!=0xA5A5)
	{
		Earse_FlashPage(0x08000000);
		Flash_WHWord(0x08000000 ,0xA5A5 );
		for(uint16_t i = 1;i<512;i++)
		{
			Flash_WHWord(0x08000000 +i*2 ,0x0000 );
		}
	}
	//将Flash里面数据保存读到ram里面
	for(uint16_t i = 0; i<512;i++)
	{
		Store_Data[i] = FlashRH_Word(0x08000000 + i*2);
	
	}
}
void Flash_Save(void)
{
	//先擦除Flash在进行写入,不然会发现写不进去
	Earse_FlashPage(0x08000000);
	for(uint16_t i = 0;i<512;i++)
	{
		Flash_WHWord(0x08000000 + i*2,Store_Data[i] );
	}
}
//函数用来清除数组 Flash里面的数据
void Flah_Clear(void)
{
	for(uint16_t i = 0;i<512;i++)
	{
		Store_Data[i] = 0x0000;
	}
	Flash_Save();
}

                                                                代码部分

        这里需要注意的是i*2问题,因为在Flash里面最小写入单元跟最小存储单元室一个半字,也就是16位,4个字节,举个例子就是0x0800 0000是单元起始地址,到0x0800 0001 地址该单元结束,该地址指向存储单元,每个地址指向的存储单元能够存储 2个字节。

        所以在数据数据进行写入的时候,地址的起始地址都是用2的倍数开头的,因为像0x0800 0001这种是不合法地址,是没有办法进行写入半字数据。

        这种用法通常是用在单片机程序很小,自身Flash占用不完的情况下使用,而有没有办法知道自己的程序占用多少字节,同时改变程序烧录的位置,无论程序大小都不能烧录到自己保存数据的Flash数据部分这种方法也是有的。

                                        查看程序自身大小方法图

        魔术棒里面有程序的起始地址还有结束地址,只要把在Keil5里面可以更改这两个地址从而达到更改程序的烧录地址的效果。

                                欢迎指正,希望对你,有所帮助!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2300068.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

小米 R3G 路由器刷机教程(Pandavan)

小米 R3G 路由器刷机教程&#xff08;Pandavan&#xff09; 一、前言 小米 R3G 路由器以其高性价比和稳定的性能备受用户青睐。然而&#xff0c;原厂固件的功能相对有限&#xff0c;难以满足高级用户的个性化需求。刷机不仅可以解锁路由器的潜能&#xff0c;还能通过第三方固…

红队视角出发的k8s敏感信息收集——Kubernetes API 扩展与未授权访问

针对 Kubernetes API 扩展与未授权访问 的详细攻击视角分析&#xff0c;聚焦 Custom Resource Definitions (CRD) 和 Aggregated API Servers 的潜在攻击面及利用方法&#xff1a; ​ 攻击链示例 1. 攻击者通过 ServiceAccount Token 访问集群 → 2. 枚举 CRD 发现数据库配…

11. Docker 微服务实战(将项目打包生成镜像,在 Docker 当中作为容器实例运行)

11. Docker 微服务实战(将项目打包生成镜像&#xff0c;在 Docker 当中作为容器实例运行) 文章目录 11. Docker 微服务实战(将项目打包生成镜像&#xff0c;在 Docker 当中作为容器实例运行)2. 最后&#xff1a; 建 Module - docker_boot 编辑 pom <?xml version"1.0&…

计算机视觉:卷积神经网络(CNN)基本概念(二)

第一章&#xff1a;计算机视觉中图像的基础认知 第二章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(一) 第三章&#xff1a;计算机视觉&#xff1a;卷积神经网络(CNN)基本概念(二) 第四章&#xff1a;搭建一个经典的LeNet5神经网络 接上一篇《计算机视觉&am…

【数据结构-红黑树】

文章目录 红黑树红黑树介绍红黑树的五个基本性质红黑树的平衡原理红黑树的操作红黑树的操作 代码实现节点实现插入和查询操作 红黑树 红黑树介绍 红黑树&#xff08;Red-Black Tree&#xff09;是一种自平衡的二叉查找树&#xff08;Binary Search Tree, BST&#xff09;&…

dify.ai 配置链接到阿里云百练等云厂商的 DeepSeek 模型

要将 dify.ai 配置链接到阿里云百练等云厂商的 DeepSeek 模型. 申请阿里云百练的KEY 添加模型 测试模型

应用分层、三层架构和MVC架构

前言 在前面中&#xff0c;我们已经学习了Spring MVC 的一些基础操作&#xff0c;那么后面就用一些简单的案例来巩固一下。 在开始学习做案例之前&#xff0c;我们先来了解一下在软件开发中常见的设计模式和架构。 应用分层 含义 应用分层是一种软件开发设计思想&#xff0…

Apache Struts2 - 任意文件上传漏洞 - CVE-2024-53677

0x01&#xff1a;漏洞简介 Apache Struts 是美国 Apache 基金会的一个开源项目&#xff0c;是一套用于创建企业级 Java Web 应用的开源 MVC 框架&#xff08;将软件分为模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;和控制器&#xff08;Controller&a…

传统混合专家模型MoE架构详解以及python示例(DeepSeek-V3之基础)

我们已经了解到DeepSeek-V3的框架结构基于三大核心技术构建:多头潜在注意力(MLA)、DeepSeekMoE架构和多token预测(MTP)。而DeepSeekMoE架构的底层模型采用了混合专家模型(Mixture of Experts,MoE)架构。所以我们先了解一下传统混合专家模型MoE架构。 一、传统混合专家模…

安全筑基,智能赋能:BeeWorks IM引领企业协同新纪元

在数字经济高速发展的今天&#xff0c;企业通讯系统已从单纯的信息传递工具演变为支撑业务创新的核心平台。传统通讯工具在安全性、智能化、协同性等方面的不足&#xff0c;严重制约着企业的数字化转型进程。BeeWorks IM系统以其创新的技术架构和智能化功能&#xff0c;正在重新…

solidworks零件的绘制学习

1、拉伸凸台拉伸切除可以在一个零件中打孔&#xff0c;如下图&#xff1a; 2、旋转凸台配合旋转切除&#xff1b; 3、薄壁特征&#xff1a;在拉伸凸台&#xff0c;旋转凸台中都有&#xff1b;在一个面中画完草图&#xff0c;然后选择拉伸凸台或旋转凸台&#xff0c;里面就会出…

llama.cpp部署 DeepSeek-R1 模型

一、llama.cpp 介绍 使用纯 C/C推理 Meta 的LLaMA模型&#xff08;及其他模型&#xff09;。主要目标llama.cpp是在各种硬件&#xff08;本地和云端&#xff09;上以最少的设置和最先进的性能实现 LLM 推理。纯 C/C 实现&#xff0c;无任何依赖项Apple 芯片是一流的——通过 A…

Spring源码分析のBean创建流程(上)

文章目录 前言一、preInstantiateSingletons1.1、getMergedLocalBeanDefinition1.2、isFactoryBean 二、getBean 前言 原生Spring在refresh方法中&#xff0c;会在finishBeanFactoryInitialization&#xff1a;preInstantiateSingletons方法中直接创建所有非懒加载的单例Bean。…

DeepSeek笔记(二):DeepSeek局域网访问

如果有多台电脑&#xff0c;可以通过远程访问&#xff0c;实现在局域网环境下多台电脑共享使用DeepSeek模型。在本笔记中&#xff0c;首先介绍设置局域网多台电脑访问DeepSeek-R1模型。 一、启动Ollama局域网访问 1.配置环境变量 此处本人的操作系统是Windows11&#xff0c;…

基于大数据的全国热门旅游景点数据分析系统的设计与实现

【大数据】基于大数据的全国热门旅游景点数据分析系统的设计与实现&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统主要包括登录注册、系统首页、图表分析、数据管理和个人信息五大功能模…

【Unity3D】Jenkins Pipeline流水线自动构建Apk

目录 一、准备阶段 二、创建Pipeline流水线项目 三、注意事项 四、扩展 1、Pipeline添加SVN更新项目Stage阶段 一、准备阶段 1、安装tomcat 10.0.5 Index of apache-local/tomcat/tomcat-10 2、安装jdk 17 Java Archive Downloads - Java SE 17.0.13 and later 3、…

Edge浏览器翻译|自动翻译设置

文章目录 Edge浏览器翻译|自动翻译设置右键翻译显示原文 Edge浏览器翻译|自动翻译设置 在 Microsoft Edge 浏览器中使用 Microsoft Translator - Microsoft 支持 进入浏览器设置,从首选语言列表中移除多余的语言设置 网站将以受支持语言列表中的第一种语言进行显示。若要重新…

基于微信小程序的场地预约设计与实现

第3章 系统设计 3.1系统设计目标 本系统的实现可以帮助体育馆场地信息的管理。帮助管理员对注册用户管理以及用户预约管理。同时可以帮助用户进行场地预约。本系统可以实现用户足不出户预约到需要的场地&#xff0c;为用户提供场地信息了解的平台。 3.2系统功能结构图 本系统的…

腾讯发布混元-3D 2.0: 首个开源高质3D-DiT生成大模型

在之前的文章中已经和大家介绍过腾讯HunYuan-3D 1.0&#xff0c;感兴趣的小伙伴可以点击下面链接阅读~ HunYuan-3D 是首个开源高质3D-DiT生成大模型&#xff0c;几何与纹理解藕生成&#xff0c;一键将创意具象化。 2.0模型架构图及介绍 2.0模型将几何和纹理生成解耦&#xff0…

计算机性能与网络体系结构探讨 —— 基于《计算机网络》谢希仁第八版

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言&#xff0c;数据结构&#xff0c;Linux基础&#xff0c;ARM开发板&#xff0c;网络编程等领域UP&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff0…