STM32 - FLASH 笔记

STM32F1系列的FLASH包含程序存储器、系统存储器和选项字节三个部分,通过闪存存储器接口(外设)可以对程序存储器和选项字节进行擦除和编程

读写FLASH的用途

  • 利用程序存储器的剩余空间来保存掉电不丢失的用户数据
  • 通过在程序中编程(IAP),实现程序的自我更新

在线编程(In-Circuit Programming -- ICP)用于更新程序存储器的全部内容,它通过JTAG、SWD协议或系统加载程序(Bootloader)下载程序

在程序中编程(In-Application Programming -- IAP)可以使用微控制器支持的任一种通信接口下载程序

内存映射

小容量产品(16K 至 32K)、中容量产品(64k 至 128k)、大容量产品(256K 至 512K)。

闪存存储器接口(外设)不属于闪存

FLASH基本结构

可以看出 闪存存储器接口(外设)整体结构

使用指针访问存储器

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

易读不易写 可以直接读或者像下面代码一样封装一个函数读

cpp 复制代码
/**
  * 函    数:FLASH读取一个32位的字
  * 参    数:Address 要读取数据的字地址
  * 返 回 值:指定地址下的数据
  */
uint32_t MyFLASH_ReadWord(uint32_t Address)
{
	return *((__IO uint32_t *)(Address));	//使用指针访问指定地址下的数据并返回
}

/**
  * 函    数:FLASH读取一个16位的半字
  * 参    数:Address 要读取数据的半字地址
  * 返 回 值:指定地址下的数据
  */
uint16_t MyFLASH_ReadHalfWord(uint32_t Address)
{
	return *((__IO uint16_t *)(Address));	//使用指针访问指定地址下的数据并返回
}

/**
  * 函    数:FLASH读取一个8位的字节
  * 参    数:Address 要读取数据的字节地址
  * 返 回 值:指定地址下的数据
  */
uint8_t MyFLASH_ReadByte(uint32_t Address)
{
	return *((__IO uint8_t *)(Address));	//使用指针访问指定地址下的数据并返回
}

程序存储器使用方法

FLASH锁

**擦除控制器(FPEC)**共有三个键值:

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

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

加锁: 设置FLASH_CR中的LOCK位锁住 FPEC 和 FLASH_CR

该环节库函数两行代码即可完成,实际操作并不复杂,只是这样侧面说明FLASH的复杂及不易出现问题导致丢失。

cpp 复制代码
    FLASH_Unlock();					//解锁
	
	FLASH_Lock();					//加锁

程序存储器全擦除

流程图

cpp 复制代码
/**
  * 函    数:FLASH全擦除
  * 参    数:无
  * 返 回 值:无
  * 说    明:调用此函数后,FLASH的所有页都会被擦除,包括程序文件本身,擦除后,程序将不复存在
  */
void MyFLASH_EraseAllPages(void)
{
	FLASH_Unlock();					//解锁
	FLASH_EraseAllPages();			//全擦除
	FLASH_Lock();					//加锁
}

程序存储器页擦除

流程图

cpp 复制代码
/**
  * 函    数:FLASH页擦除
  * 参    数:PageAddress 要擦除页的页地址
  * 返 回 值:无
  */
void MyFLASH_ErasePage(uint32_t PageAddress)
{
	FLASH_Unlock();					//解锁
	FLASH_ErasePage(PageAddress);	//页擦除
	FLASH_Lock();					//加锁
}

程序存储器编程

流程图

cpp 复制代码
/**
  * 函    数:FLASH编程字
  * 参    数:Address 要写入数据的字地址
  * 参    数:Data 要写入的32位数据
  * 返 回 值:无
  */
void MyFLASH_ProgramWord(uint32_t Address, uint32_t Data)
{
	FLASH_Unlock();							//解锁
	FLASH_ProgramWord(Address, Data);		//编程字
	FLASH_Lock();							//加锁
}

/**
  * 函    数:FLASH编程半字
  * 参    数:Address 要写入数据的半字地址
  * 参    数:Data 要写入的16位数据
  * 返 回 值:无
  */
void MyFLASH_ProgramHalfWord(uint32_t Address, uint16_t Data)
{
	FLASH_Unlock();							//解锁
	FLASH_ProgramHalfWord(Address, Data);	//编程半字
	FLASH_Lock();							//加锁
}

选项字节

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

nUSER及前面+ n 是反码

对于产品,选择字节WRPx 中的每一个比特位用于保护主存储器中 4 个存储页 (1K 字节 /
页 ) :

  • 0:实施写保护
  • 1:不实施写保护

中容量四个用户选择字节用于保护总共128K 字节的主存储器。

  • WRP0:第0~31页的写保护
  • WRP1:第32~63页的写保护
  • WRP2:第64~95页的写保护
  • WRP3:第96~127页的写保护

大容量产品 四个用户选择字节用于保护总共512K 字节的主存储器。

  • WRP0:第0~15页的写保护
  • WRP1:第16~31页的写保护
  • WRP2:第32~47页的写保护
  • WRP3:位0~6提供第48~61页的写保护;位7提供第62~255页的写保护

选项字节编程

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

选项字节擦除

  • 检查FLASH_SR的BSY位,以确认没有其他正在进行的闪存操作
  • 解锁FLASH_CR的OPTWRE位
  • 设置FLASH_CR的OPTER位为1
  • 设置FLASH_CR的STRT位为1
  • 等待BSY位变为0
  • 读出被擦除的选择字节并做验证
相关推荐
密码小丑43 分钟前
11月4日(内网横向移动(一))
笔记
Mr.谢尔比1 小时前
电赛入门之软件stm32keil+cubemx
stm32·单片机·嵌入式硬件·mcu·信息与通信·信号处理
LightningJie1 小时前
STM32中ARR(自动重装寄存器)为什么要减1
stm32·单片机·嵌入式硬件
鹿屿二向箔1 小时前
STM32外设之SPI的介绍
stm32
鸭鸭梨吖1 小时前
产品经理笔记
笔记·产品经理
齐 飞2 小时前
MongoDB笔记01-概念与安装
前端·数据库·笔记·后端·mongodb
西瓜籽@2 小时前
STM32——毕设基于单片机的多功能节能窗控制系统
stm32·单片机·课程设计
丫头,冲鸭!!!2 小时前
B树(B-Tree)和B+树(B+ Tree)
笔记·算法
听忆.3 小时前
手机屏幕上进行OCR识别方案
笔记
Selina K3 小时前
shell脚本知识点记录
笔记·shell