嵌入式开发之STM32学习笔记day22
STM32F103C8T6 FLASH闪存
1 FLASH简介
STM32F1系列微控制器的FLASH存储器是一种非易失性存储器,它在微控制器中扮演着至关重要的角色。以下是对STM32F1系列FLASH存储器及其相关编程方式的扩展说明:
【FLASH存储器的组成部分】
程序存储器:这是FLASH存储器的主要部分,用于存储微控制器运行的程序代码。程序存储器的大小取决于具体的STM32F1系列型号,通常从几KB到几十KB不等。
系统存储器:这部分存储器用于存储微控制器的启动代码和系统配置数据。系统存储器通常较小,但对微控制器的启动和运行至关重要。
选项字节:选项字节用于配置微控制器的一些特定功能,如启动模式选择、读写保护等。通过编程选项字节,可以灵活地配置微控制器的行为。
【FLASH存储器的读写用途】
保存用户数据:利用程序存储器的剩余空间来保存掉电不丢失的用户数据。这种数据通常包括配置参数、用户设置、传感器校准数据等。
程序自我更新:通过在程序中编程(IAP),实现程序的自我更新。IAP允许微控制器在运行过程中更新其程序存储器中的内容,而无需外部编程器。
在线编程(In-Circuit Programming – ICP)是一种通过微控制器的外部接口(如JTAG、SWD协议或系统加载程序Bootloader)下载程序的方法。ICP允许开发者在不拆卸微控制器的情况下更新程序存储器的全部内容,这在产品开发和调试阶段非常有用。
在程序中编程(In-Application Programming – IAP)是一种利用微控制器支持的任一种通信接口(如UART、SPI、I2C等)下载程序的方法。IAP允许微控制器在运行过程中更新其程序存储器中的内容,而无需外部编程器。IAP通常用于实现固件升级、错误修复和功能扩展等。
FLASH存储器的擦除和编程:STM32F1系列微控制器通过闪存存储器接口(外设)提供了对程序存储器和选项字节的擦除和编程功能。擦除操作通常用于清除存储器中的内容,为新的编程操作做准备。编程操作则用于将新的数据写入存储器。
【注意事项】
擦除和编程时间:FLASH存储器的擦除和编程操作需要一定的时间,因此在设计系统时需要考虑这些操作对系统性能的影响。
擦除和编程次数:FLASH存储器的擦除和编程次数有限,通常在几千到几万次之间。因此,在设计系统时需要合理规划擦除和编程操作,以延长存储器的使用寿命。
数据保护:为了防止意外擦除或编程,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,解锁
- 错误的操作序列会在下次复位前锁死FPEC和FLASH_CR
【加锁】
- 设置FLASH_CR中的LOCK位锁住FPEC和FLASH_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_SR的BSY位,以确认没有其他正在进行的编程操作
- 解锁FLASH_CR的OPTWRE位
- 设置FLASH_CR的OPTPG位为1
- 写入要编程的半字到指定的地址
- 等待BSY位变为0
- 读出写入的地址并验证数据
9.2 选项字节擦除
- 检查FLASH_SR的BSY位,以确认没有其他正在进行的闪存操作
- 解锁FLASH_CR的OPTWRE位
- 设置FLASH_CR的OPTER位为1
- 设置FLASH_CR的STRT位为1
- 等待BSY位变为0
- 读出被擦除的选择字节并做验证
10 器件电子签名
电子签名存放在闪存存储器模块的系统存储区域,包含的芯片识别信息在出厂时编写,不可更改,使用指针读指定地址下的存储器可获取电子签名:
闪存容量寄存器:
基地址:0x1FFF F7E0
大小:16位
产品唯一身份标识寄存器:
基地址: 0x1FFF F7E8
大小:96位