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
  • 读出被擦除的选择字节并做验证
相关推荐
阿川!34 分钟前
嵌入式软件--stm32 DAY 9 定时器
stm32·单片机·嵌入式硬件
ssjnbnbnb1 小时前
数据库概述(学习笔记)
数据库·笔记·学习
笑衬人心。1 小时前
JVM 笔记:类加载、内存管理、垃圾收集与垃圾收集器
java·jvm·笔记
无妄之灾|2 小时前
HCIP笔记(第一、二章)
笔记·hcip
22:30Plane-Moon2 小时前
SQL 查询语法笔记
数据库·笔记·sql
_Kayo_2 小时前
VUE2 学习笔记8 v-text/html/cloak/once/pre/自定义
笔记·学习
星星火柴9362 小时前
开发笔记 | 实现人物立绘的差分效果
笔记·unity·游戏程序·优香
杨DaB2 小时前
【SpringMVC】MVC中Controller的配置 、RestFul的使用、页面重定向和转发
java·笔记·后端·学习·spring·mvc·restful
吃不得辣条3 小时前
网络安全笔记
笔记·web安全·智能路由器
_Kayo_4 小时前
VUE2 学习笔记11 脚手架
vue.js·笔记·学习