初学stm32 --- flash模仿eeprom

news/2025/1/18 15:50:18/

目录

STM32内部FLASH简介

 内部FLASH构成(F1)

FLASH读写过程(F1)

闪存的读取

闪存的写入

内部FLASH构成(F4 / F7 / H7)

 FLASH读写过程(F4 / F7 / H7)

闪存的读取 

闪存的写入

FLASH接口寄存器(写入 & 擦除相关)

FLASH相关HAL库函数简介(F1 / F4 / F7 / H7)

FLASH相关结构体:FLASH_EraseInitTypeDef

F103ZET6 stmflash_write思路

可操作的地址怎么确定?


STM32内部FLASH简介

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

 内部FLASH构成(F1)

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

主存储器:

        地址范围为0x0800 0000 ~ 0x0807 FFFF,分为256页,每页2KB(小/中容量为1K)。

        当BOOT0接地,系统将从0x0800 0000地址处开始读取代码(从主存储器启动)

信息块:

        系统存储大小为2KB,用来存储ST自带的启动程序,用来串口下载代码。

        选项字节大小为16B,一般用于设置内存的写保护、读保护

        当BOOT0VCCBOOT1GND (串口下载程序) ,系统运行的就是这部分代码

FLASH读写过程(F1)

  FLASH的核心操作就是

          FLASH的物理特性:只能写0,不能写1,写1擦除

闪存的读取

        直接在通用地址空间直接寻址,任何32位数据的读操作都能访问闪存模块的内容并得到相对应的数据。

        CPU运行速度比FLASH快得多,STM32F103FLASH最快访问速度≤24MHzCPU频率超过这个速度,得加入等待时间,否则读写FLASH可能出错,导致死机等情况。

        正确设置好等待周期后,利用指针读取数据。

        从地址addr,读取数据(字节为8位,半字为16位,字为32位)

                data = *(volatile uint8_t *)addr;  /* 读取一个字节数据 */

                data = *(volatile uint16_t *)addr;  /* 读取一个半字数据 */

                data = *(volatile uint32_t *)addr;  /* 读取一个字数据 */

        将addr强制转换为uintx_t指针,然后取该指针所指向地址的值,即可获得addr地址的数据。

        注意: 在进行写或擦除操作时,不能进行代码或数据的读取操作。

     

闪存的写入

        闪存编程是由FPEC(闪存编程和擦除控制器)模块处理的。

        写操作有四步:解锁 à 擦除 à 写数据 à 上锁

解锁:将两个特定的解锁序列号(KEY1:0x45670123 KEY2:0xCDEF89AB依次写入FLASH_KEYR

擦除:FLASH物理特性(只能写0,不能写1),所以写FLASH之前需要擦除,将要写入的区域变为0xFFFF。擦除操作分为:页擦除和批量擦除

写数据:擦除完成,可以向FLASH写数据,每次只能16位方式写入

上锁:写入数据完成,需要设置FLASH_CR[LOCK]1,重新上锁,以防数据不小心被修改。

 

内部FLASH构成(F4 / F7 / H7)

        内部FLASH主要由四部分组成:主存储器、系统存储器、OPT区域和选项字节。

        闪存存储器接口寄存器,该部分用于控制闪存读写等,是整个闪存模块的控制机构。

         注意:对于H7来说,在Bank1内部有2KB大小的用户选项字节,不过没有映射到内存地址上,可通过FLASH相关寄存器访问。

        STM32F7的FLASH访问路径有两条:AXIMITCM,对应不同的地址映射。

F767 Bank1M闪存组织结构(默认)双Bank详看《STM32F7xx参考手册

 

 FLASH读写过程(F4 / F7 / H7)

        对FLASH的核心操作就是

        FLASH的物理特性:只能写0,不能写1,写1擦除

闪存的读取 

        正确设置好等待周期后,利用指针读取数据。

        从地址addr,读取数据(字节为8位,半字为16位,字为32位)

                data = *(volatile uint8_t *)addr;  /* 读取一个字节数据 */

                data = *(volatile uint16_t *)addr;  /* 读取一个半字数据 */

                data = *(volatile uint32_t *)addr;  /* 读取一个字数据 */

        将addr强制转换为uintx_t指针,然后取该指针所指向地址的值,即可获得addr地址的数据。

        注意: 在进行写或擦除操作时,不能进行代码或数据的读取操作。

        

闪存的写入

        STM32F4/F7/H7 FLASH进行写操作或擦除,电源电压会影响数据的最大操作位数

        最大操作位数会影响擦除和写入的速度。 

        开发板使用的电压是3.3VPSIZE设置10,即32并行位数。擦除或者写入都以32位为单位。

        写操作有四步:解锁 à 擦除 à 写数据 à 上锁

解锁:将两个特定的解锁序列号(KEY1:0x45670123 KEY2:0xCDEF89AB依次写入FLASH_KEYR

擦除:FLASH物理特性(只能写0,不能写1),所以写FLASH之前需要擦除,将要写入的区域变为0xFFFF。擦除操作分为:页扇区擦除和整片擦除

写数据:擦除完成,可以向FLASH写数据,根据PSIZE设置写入数据的单位

PSZIE:00 字节、PSIZE:01 半字、PSIZE:10 字、PSIZE:11 双字

上锁:写入数据完成,需要设置FLASH_CR[LOCK]1,重新上锁,以防数据不小心被修改。

      注意:对于STM32H7 FLASH写入的规则:写入首地址必须是32的倍数,写入数据长度必须是32字节的倍数。  

FLASH接口寄存器(写入 & 擦除相关)

FLASH_CR

LOCK:指示FLASH_CR寄存器是否被锁住(10未锁)

STRT:用于开始一次擦除操作(1开始)

PSIZE:用于设置编程宽度(3.3V PSIZE2

SNB:用于选择要擦除的扇区编号

SER:用于选择扇区擦除操作(页擦除置1

PG:用于选择编程操作,往FLASH写数据需置1

         对于H7还有FLASH_CCR 清除与控制寄存器用于清除相关错误。

FLASH相关HAL库函数简介(F1 / F4 / F7 / H7)

FLASH相关结构体:FLASH_EraseInitTypeDef

F1:

uint32_t	TypeErase	 	/* 擦除类型 */
uint32_t	Banks		/* 擦除的bank编号(整片擦除) */
uint32_t 	PageAddress	/* 擦除页面地址 */
uint32_t 	NbPages		/* 擦除的页面数 */

F4/F7/H7

uint32_t	TypeErase	 	
uint32_t	Banks		
uint32_t 	Sector	
uint32_t 	NbSectors
uint32_t	VoltageRange	

F103ZET6 stmflash_write思路

        每个扇区()2KB,也就是2048个地址,写任何一个地址前,如果该地址的值并不是0xFF,需先擦除再写入

根据w_addr,确定No.sector号以及w_addr在该sector的偏移

根据w_addrlength,确定写入的内容是否跨sector

确定好要操作的sector以及sector的地址范围

遍历要写的地址区域数据是否都是0xFF,如果都是不用擦除,否则需要先读出保存在buf后擦除

把该sector要操作的数据,也写到buf,最后一次性把buf写入到这个对应的sector即可

        跨扇区:需要注意偏移(扇区地址 / 扇区中的偏移 / 写入数据的偏移 / 写地址偏移 / 写入长度)

可操作的地址怎么确定?

        不能影响原有已存放有用数据的FLASH区域,通过MDK编译完成提示或者map文件可得占用flash大小。

        占用FLASH大小 4058827360 + 12868 + 360

        占用SRAM大小 4496360 + 4136

Code段:表示程序代码占用FLASH的大小(FLASH 

RO-data段,即Read Only-Data,程序定义的所有常量(FLASH 

RW-data段,即Read Write-Data,已经初始化的所有静态变量,占用FLASH空间(存储初值)和RAM(读写操作)

ZI-data(Zero initialized)段:未初始化的静态变量

RO(Read Only)段:指代码Code以及只读数据RO-data的统称,占用FLASH空间 


http://www.ppmy.cn/news/1564185.html

相关文章

图像识别opencv翻转

运行界面 以下是代码: import cv2 import numpy #读取图像 img cv2.imread("../image/cat.jpg") #1,0,-1代表不一样的翻转效果 flipped cv2.flip(img, 1) #显示结果 cv2.imshow("Flip", flipped) cv2.imshow("original", img) cv2…

【C++ 类和对象 进阶篇】—— 逻辑森林的灵动精灵,舞动类与对象的奇幻圆舞曲

欢迎来到ZyyOvO的博客✨,一个关于探索技术的角落,记录学习的点滴📖,分享实用的技巧🛠️,偶尔还有一些奇思妙想💡 本文由ZyyOvO原创✍️,感谢支持❤️!请尊重原创&#x1…

4、dockerfile实现lnmp

dockerfile实现lnmp: nginx centos7 172.111.0.10 mysql centos7 172.111.0.20 php centos7 172.111.0.30 自定义镜像来实现整个架构 nginx dockerfile配置文件 nginx配置文件 创建镜像 声明网段 创建…

MYSQL的第一次作业

目录 前情提要 题目解析 连接并使用数据库 创建employees表 创建orders表 创建invoices表 ​查看建立的表 前情提要 需要下载mysql并进行配置,建议下载8.0.37,详情可见MySQL超详细安装配置教程(亲测有效)_mysql安装教程-CSDN博客 题目解析 …

SpringBoot开发——使用ObjectMapper处理JSON数据

文章目录 1. 基本对象到JSON的转换2. 基本JSON到对象的转换3. 使用注解自定义JSON字段名称4. 序列化时忽略字段5. 处理未知的JSON字段6. 将对象列表转换为JSON7. 在Spring Boot控制器中使用ObjectMapper8. 将JSON文件转换为对象9. 美化打印JSON输出10. 自定义ObjectMapper配置本…

【C++】构造函数与析构函数

写在前面 构造函数与析构函数都是属于类的默认成员函数! 默认成员函数是程序猿不显示声明定义,编译器会中生成。 构造函数和析构函数的知识需要建立在有初步类与对象的基础之上的,关于类与对象不才在前面笔记中有详细的介绍:点我…

深入了解卷积神经网络(CNN):图像处理与深度学习的革命性技术

深入了解卷积神经网络(CNN):图像处理与深度学习的革命性技术 导语 卷积神经网络(CNN)是现代深度学习领域中最重要的模型之一,特别在计算机视觉(CV)领域具有革命性的影响。无论是图…

MySQL8数据库全攻略:版本特性、下载、安装、卸载与管理工具详解

大家好,我是袁庭新。 MySQL作为企业项目中的主流数据库,其5.x和8.x版本尤为常用。本文将详细介绍MySQL 8.x的特性、下载、安装、服务管理、卸载及管理工具,旨在帮助用户更好地掌握和使用MySQL数据库。 1.MySQL版本及下载 企业项目中使用的…