当前位置: 首页 > ds >正文

嵌入式开发之STM32学习笔记day22

STM32F103C8T6  FLASH闪存

1 FLASH简介

        STM32F1系列微控制器的FLASH存储器是一种非易失性存储器,它在微控制器中扮演着至关重要的角色。以下是对STM32F1系列FLASH存储器及其相关编程方式的扩展说明:

        【FLASH存储器的组成部分】

  1. 程序存储器:这是FLASH存储器的主要部分,用于存储微控制器运行的程序代码。程序存储器的大小取决于具体的STM32F1系列型号,通常从几KB到几十KB不等。

  2. 系统存储器:这部分存储器用于存储微控制器的启动代码和系统配置数据。系统存储器通常较小,但对微控制器的启动和运行至关重要。

  3. 选项字节:选项字节用于配置微控制器的一些特定功能,如启动模式选择、读写保护等。通过编程选项字节,可以灵活地配置微控制器的行为。

        【FLASH存储器的读写用途】

  1. 保存用户数据:利用程序存储器的剩余空间来保存掉电不丢失的用户数据。这种数据通常包括配置参数、用户设置、传感器校准数据等。

  2. 程序自我更新:通过在程序中编程(IAP),实现程序的自我更新。IAP允许微控制器在运行过程中更新其程序存储器中的内容,而无需外部编程器。

        在线编程(In-Circuit Programming – ICP)是一种通过微控制器的外部接口(如JTAG、SWD协议或系统加载程序Bootloader)下载程序的方法。ICP允许开发者在不拆卸微控制器的情况下更新程序存储器的全部内容,这在产品开发和调试阶段非常有用。

        在程序中编程(In-Application Programming – IAP)是一种利用微控制器支持的任一种通信接口(如UART、SPI、I2C等)下载程序的方法。IAP允许微控制器在运行过程中更新其程序存储器中的内容,而无需外部编程器。IAP通常用于实现固件升级、错误修复和功能扩展等。

        FLASH存储器的擦除和编程:STM32F1系列微控制器通过闪存存储器接口(外设)提供了对程序存储器和选项字节的擦除和编程功能。擦除操作通常用于清除存储器中的内容,为新的编程操作做准备。编程操作则用于将新的数据写入存储器。

        【注意事项】

  1. 擦除和编程时间:FLASH存储器的擦除和编程操作需要一定的时间,因此在设计系统时需要考虑这些操作对系统性能的影响。

  2. 擦除和编程次数:FLASH存储器的擦除和编程次数有限,通常在几千到几万次之间。因此,在设计系统时需要合理规划擦除和编程操作,以延长存储器的使用寿命。

  3. 数据保护:为了防止意外擦除或编程,STM32F1系列微控制器提供了读写保护功能。通过编程选项字节,可以启用或禁用存储器的读写保护。

2 闪存模块组织

3 FLASH基本结构

        该图展示了STM32微控制器的存储器结构,其中程序存储器(C8T6-64K)被分为多个1K大小的页面,从0x0800 0000地址开始,共有64个页面,而系统存储器包含Bootloader(2K)和选项字节(16字节),分别位于0x1FFF F000和0x1FFF F800地址。闪存存储器接口/闪存编程和擦除控制器(FPEC)负责管理程序存储器和选项字节的擦除与编程操作,同时配置读写保护,确保存储器的安全和数据的持久性。

4 FLASH解锁

        【FPEC共有三个键值】

  • RDPRT= 0x000000A5
  • KEY1 = 0x45670123
  • KEY2 = 0xCDEF89AB

        【解锁】

  • 复位后,FPEC被保护,不能写入FLASH_CR
  • 在FLASH_KEYR先写入KEY1,再写入KEY2,解锁
  • 错误的操作序列会在下次复位前锁死FPECFLASH_CR

        【加锁】

  • 设置FLASH_CR中的LOCK位锁住FPECFLASH_CR

5 访问存储器

使用指针读指定地址下的存储器:uint16_t Data = *((__IO uint16_t *)(0x08000000));使用指针写指定地址下的存储器:*((__IO uint16_t *)(0x08000000)) = 0x1234;其中:#define    __IO    volatile

6 程序存储器编程

代码如下:

FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
{FLASH_Status status = FLASH_COMPLETE;/* Check the parameters */assert_param(IS_FLASH_ADDRESS(Address));/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation(ProgramTimeout);if(status == FLASH_COMPLETE){/* if the previous operation is completed, proceed to program the new data */FLASH->CR |= CR_PG_Set;*(__IO uint16_t*)Address = Data;/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation(ProgramTimeout);/* Disable the PG Bit */FLASH->CR &= CR_PG_Reset;} /* Return the Program Status */return status;
}

7 程序存储器页擦除

代码如下:

FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
{FLASH_Status status = FLASH_COMPLETE;/* Check the parameters */assert_param(IS_FLASH_ADDRESS(Page_Address));/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation(EraseTimeout);if(status == FLASH_COMPLETE){ /* if the previous operation is completed, proceed to erase the page */FLASH->CR|= CR_PER_Set;FLASH->AR = Page_Address; FLASH->CR|= CR_STRT_Set;/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation(EraseTimeout);/* Disable the PER Bit */FLASH->CR &= CR_PER_Reset;}/* Return the Erase Status */return status;
}

8 程序存储器全擦除

代码如下:

FLASH_Status FLASH_EraseAllPages(void)
{FLASH_Status status = FLASH_COMPLETE;/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation(EraseTimeout);if(status == FLASH_COMPLETE){/* if the previous operation is completed, proceed to erase all pages */FLASH->CR |= CR_MER_Set;FLASH->CR |= CR_STRT_Set;/* Wait for last operation to be completed */status = FLASH_WaitForLastOperation(EraseTimeout);/* Disable the MER Bit */FLASH->CR &= CR_MER_Reset;}/* Return the Erase Status */return status;
}

9 选项字节

  • RDP:写入RDPRT键(0x000000A5)后解除读保护
  • USER:配置硬件看门狗和进入停机/待机模式是否产生复位
  • Data0/1:用户可自定义使用
  • WRP0/1/2/3:配置写保护,每一个位对应保护4个存储页(中容量)

 9.1 选项字节编程

  • 检查FLASH_SRBSY位,以确认没有其他正在进行的编程操作
  • 解锁FLASH_CROPTWRE
  • 设置FLASH_CROPTPG位为1
  • 写入要编程的半字到指定的地址
  • 等待BSY位变为0
  • 读出写入的地址并验证数据

9.2 选项字节擦除

  • 检查FLASH_SRBSY位,以确认没有其他正在进行的闪存操作
  • 解锁FLASH_CROPTWRE
  • 设置FLASH_CROPTER位为1
  • 设置FLASH_CRSTRT位为1
  • 等待BSY位变为0
  • 读出被擦除的选择字节并做验证

10 器件电子签名

        电子签名存放在闪存存储器模块的系统存储区域,包含的芯片识别信息在出厂时编写,不可更改,使用指针读指定地址下的存储器可获取电子签名:

闪存容量寄存器

基地址:0x1FFF F7E0

大小:16

产品唯一身份标识寄存器

基地址: 0x1FFF F7E8

大小:96

 

http://www.xdnf.cn/news/12604.html

相关文章:

  • 深入解析:为什么 Redis 比 MySQL 快
  • 如何轻松、安全地管理密码(新手指南)
  • 创客匠人:如何通过精准定位实现创始人IP打造与知识变现
  • [C语言实战]C语言操作MySQL数据库(八)
  • Ubuntu18.6 学习QT问题记录以及虚拟机安装Ubuntu后的设置
  • 下载和安装Visual Studio(开发ASP.NET MVC应用)
  • 华为仓颉语言初识:并发编程之同步机制(上)
  • TensorFlow安装全攻略:快速搭建AI开发环境
  • 图像识别预处理(配合pytesseract使用)
  • 基于最大相邻夹角的边缘点提取(matlab)
  • 华为大规模——重塑生产力
  • 软信天成:数据驱动型背后的人工智能,基于机器学习的数据管理
  • FPGA定点和浮点数学运算-实例对比
  • opencv2/opencv.hpp里面有哪些常用的函数
  • 从混乱到秩序:探索管理系统如何彻底改变工作流程
  • Spring 团队详解:AOT 缓存实践、JSpecify 空指针安全与支持策略升级
  • Python 构建法律DeepSeek RAG
  • 35.成功解决编写关于“江协科技”编写技巧第二期标志位积累的问题
  • PostgreSQL 的扩展pg_freespacemap
  • Webhook 配置备忘
  • Imprompter: Tricking LLM Agents into Improper Tool Use
  • VUE解决页面请求接口大规模并发的问题(请求队列)
  • 通过跳板机连接远程主机
  • 【佳易王个体诊所电子处方软件】助力智慧诊疗! #医疗数字化 #电子处方效率提升
  • MySQL体系架构解析(三):MySQL数据存储的揭秘
  • 从0到1写一个适用于Node.js的User Agent生成库
  • 矩阵和向量范数的区别分析
  • GAN模式奔溃的探讨论文综述(一)
  • SQL进阶之旅 Day 17:大数据量查询优化策略
  • C++.OpenGL (9/64)复习(Review)