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

嵌入式开发之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.lryc.cn/news/2403263.html

相关文章:

  • 分词算法BBPE详解和Qwen的应用
  • 关于ETL的BackgroundScheduler同步方案和misfire_grace_time
  • 多线程下使用缓存+锁Lock, 出现“锁失效” + “缓存未命中竞争”的缓存击穿情况,双重检查缓存解决问题
  • Playwright 测试框架 - .NET
  • 命令行以TLS/SSL显式加密方式访问FTP服务器
  • Mac 双系统
  • Linux配置yum 时间同步服务 关闭防火墙 关闭ESlinux
  • SpringBoot 系列之集成 RabbitMQ 实现高效流量控制
  • LLaMA-Factory和python版本的兼容性问题解决
  • 掌握子网划分:优化IP分配与管理
  • Linux中shell编程表达式和数组讲解
  • 每日算法-250605
  • 分布式锁-Redisson实现
  • HTTP 请求协议简单介绍
  • C++学习-入门到精通【14】标准库算法
  • 银行用户评分规则 深度学习
  • HarmonyOS运动语音开发:如何让运动开始时的语音播报更温暖
  • # 从底层架构到应用实践:为何部分大模型在越狱攻击下失守?
  • vscode使用系列之快速生成html模板
  • Thinkphp6软删除
  • 网页前端开发(基础进阶4--axios)
  • 软件安全:漏洞利用与渗透测试剖析、流程、方法、案例
  • Haproxy的基础配置
  • 考研系列—操作系统:冲刺笔记(1-3章)
  • 使用 Docker Compose 部署 Jenkins(LTS 版)持续集成环境
  • Java调用大模型API实战指南
  • C#中的路由事件(Routed Events)
  • [蓝桥杯]通电
  • 单片机0-10V电压输出电路分享
  • 从零开始,搭建一个基于 Django 的 Web 项目