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
  • 读出被擦除的选择字节并做验证
相关推荐
ミ míSs °9 分钟前
MySQL做题笔记
笔记·mysql
陈两全18 分钟前
CSS笔记
前端·css·笔记
浩浩的科研笔记2 小时前
在树莓派5上使用pytroch进行模型训练—全流程笔记
pytorch·笔记·深度学习
LCS-3122 小时前
Qt+FFmpeg开发视频播放器笔记(二):界面UI搭建
笔记·qt·ffmpeg
孞㐑¥2 小时前
C语言—指针(2)
c语言·开发语言·经验分享·笔记
Akiiiira3 小时前
【学习笔记】Day 20
笔记·学习
魔理沙偷走了BUG3 小时前
【数学分析笔记】第2章第4节收敛准则(3)
笔记·数学分析
清流君4 小时前
【自动驾驶】控制算法(五)连续方程离散化与离散LQR原理
人工智能·笔记·自动驾驶·控制算法·lqr
s_little_monster4 小时前
【C++】vector(上)
开发语言·c++·经验分享·笔记·学习
海姐软件测试4 小时前
用 postman 的时候如何区分服务器还是自己的问题?
经验分享·笔记·其他·面试·职场和发展