IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32---内部FLASH -> 正文阅读

[嵌入式]STM32---内部FLASH

FLASH

1.FLASH介绍

image-20220406140553245

**主存储器:**分为4个16KB扇区、1个64KB扇区和7个128KB扇区。boot0/boot1都接GND时从0x08000000开始运行代码。

**系统存储器:**器件在系统存储器自举模式下从该存储器启动,主要存放芯片的bootloader代码,此代码出厂时固化在芯片内部了。用于给主存储器下载代码。当boot0接3.3V、boot1接GND时从此处开始运行,即进入串口下载模式。

**OTP区域:**512字节OTP(一次性可编程),用于存储用户数据。OTP区域还有额外的16个字节,用于锁定对应的OTP数据块。

**选项字节:**用于配置读写保护、BOR级别、软件/硬件看门狗以及器件处于待机或停止模式下的复位。

1.1闪存的编程和擦除

STM32F4的闪存编程由6个32位寄存器控制:

(1)FLASH访问控制寄存器(FLASH_ACR)

(2)FLASH秘钥寄存器(FLASH_KEYR)

(3)FLASH选项秘钥寄存器(FLASH_OPTKEYR)

(4)FLASH状态寄存器(FLASH_SR)

(5)FLASH控制寄存器(FLASH_CR)

(6)FLASH选项控制寄存器(FLASH_OPTCR)

STM32F4复位后,FLASH编程操作是被保护的,不能写入FLASH_CR。

FALSH_CR解锁步骤为:

(1)写0X45670123到FLASH_KEYR

(2)写0XCDEF89AB到FLASH_KEYR

STM32F4闪存的编程位数通过FLASH_CR的PSIZE字段设置,PSIZE的设置必须和电源电压匹配。

image-20220406142602205

STM32F4标准编程步骤:

(1)检查FLASH_SR中的BSY位,确保当前未执行任何FLASH操作。

(2)将FLASH_CR寄存器中的PG位置1,激活FLASH编程。

(3)执行写入操作

(4)等待BSY位清零,完成一次编程。

扇区擦除步骤:

(1)检查FLASH_CR的LOCK是否解锁,如果没有先解锁

(2)检查FLASH_SR寄存器中的BSY位,确保当前未执行任何FLASH操作

(3)在FLASH_CR寄存器中,将SER位置1,并从主存储块的12个扇区中选择要擦除的扇区(SNB)

(4)将FLASH_CR寄存器中的STRT位置1,触发擦除操作

(5)等待BSY位清零

2.相关寄存器

3.配置方法

3.1 内部flash分步操作

3.1.1解锁和锁定
#define FLASH_KEY1               ((uint32_t)0x45670123)
#define FLASH_KEY2               ((uint32_t)0xCDEF89AB)
#define FLASH_CR_LOCK            ((uint32_t)0x80000000)
//解锁函数
void FLASH_Unlock(void)
{
  if((FLASH->CR & FLASH_CR_LOCK) != RESET)
  {
    /* Authorize the FLASH Registers access */
    FLASH->KEYR = FLASH_KEY1;
    FLASH->KEYR = FLASH_KEY2;
  }  
}
//锁定函数
void FLASH_Lock(void)
{
  /* Set the LOCK Bit to lock the FLASH Registers access */
  FLASH->CR |= FLASH_CR_LOCK;
}
3.1.2写操作
//写入双字
FLASH_Status FLASH_ProgramDoubleWord(uint32_t Address, uint64_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();
  
  if(status == FLASH_COMPLETE)
  {
    /* if the previous operation is completed, proceed to program the new data */
    FLASH->CR &= CR_PSIZE_MASK;
    FLASH->CR |= FLASH_PSIZE_DOUBLE_WORD;
    FLASH->CR |= FLASH_CR_PG;
  
    *(__IO uint64_t*)Address = Data;
        
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation();

    /* if the program operation is completed, disable the PG Bit */
    FLASH->CR &= (~FLASH_CR_PG);
  } 
  /* Return the Program Status */
  return status;
}
//写入字
FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_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();
  
  if(status == FLASH_COMPLETE)
  {
    /* if the previous operation is completed, proceed to program the new data */
    FLASH->CR &= CR_PSIZE_MASK;
    FLASH->CR |= FLASH_PSIZE_WORD;
    FLASH->CR |= FLASH_CR_PG;
  
    *(__IO uint32_t*)Address = Data;
        
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation();

    /* if the program operation is completed, disable the PG Bit */
    FLASH->CR &= (~FLASH_CR_PG);
  } 
  /* Return the Program Status */
  return status;
}
//写入半字
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();
  
  if(status == FLASH_COMPLETE)
  {
    /* if the previous operation is completed, proceed to program the new data */
    FLASH->CR &= CR_PSIZE_MASK;
    FLASH->CR |= FLASH_PSIZE_HALF_WORD;
    FLASH->CR |= FLASH_CR_PG;
  
    *(__IO uint16_t*)Address = Data;
        
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation();

    /* if the program operation is completed, disable the PG Bit */
    FLASH->CR &= (~FLASH_CR_PG);
  } 
  /* Return the Program Status */
  return status;
}
//写入字节
FLASH_Status FLASH_ProgramByte(uint32_t Address, uint8_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();
  
  if(status == FLASH_COMPLETE)
  {
    /* if the previous operation is completed, proceed to program the new data */
    FLASH->CR &= CR_PSIZE_MASK;
    FLASH->CR |= FLASH_PSIZE_BYTE;
    FLASH->CR |= FLASH_CR_PG;
  
    *(__IO uint8_t*)Address = Data;
        
    /* Wait for last operation to be completed */
    status = FLASH_WaitForLastOperation();

    /* if the program operation is completed, disable the PG Bit */
    FLASH->CR &= (~FLASH_CR_PG);
  } 

  /* Return the Program Status */
  return status;
}
3.1.3擦除操作
//FLASH_Sector:选择擦除扇区
//VoltageRange:选择电源电压范围
FLASH_Status FLASH_EraseSector(uint32_t FLASH_Sector, uint8_t VoltageRange); 
FLASH_Status FLASH_EraseAllSectors(uint8_t VoltageRange); 
FLASH_Status FLASH_EraseAllBank1Sectors(uint8_t VoltageRange); 
FLASH_Status FLASH_EraseAllBank2Sectors(uint8_t VoltageRange);
3.1.4获取FLASH状态
FLASH_Status FLASH_GetStatus(void)
{
  FLASH_Status flashstatus = FLASH_COMPLETE;
  
  if((FLASH->SR & FLASH_FLAG_BSY) == FLASH_FLAG_BSY) 
  {
    flashstatus = FLASH_BUSY;
  }
  else 
  {  
    if((FLASH->SR & FLASH_FLAG_WRPERR) != (uint32_t)0x00)
    { 
      flashstatus = FLASH_ERROR_WRP;
    }
    else
    {
      if((FLASH->SR & FLASH_FLAG_RDERR) != (uint32_t)0x00)
      { 
        flashstatus = FLASH_ERROR_RD;
      } 
      else 
      {
        if((FLASH->SR & (uint32_t)0xE0) != (uint32_t)0x00)
        {
          flashstatus = FLASH_ERROR_PROGRAM; 
        }
        else
        {
          if((FLASH->SR & FLASH_FLAG_OPERR) != (uint32_t)0x00)
          {
            flashstatus = FLASH_ERROR_OPERATION;
          }
          else
          {
            flashstatus = FLASH_COMPLETE;
          }
        }
      }
    }
  }
  /* Return the FLASH Status */
  return flashstatus;
}

返回值是通过枚举类型定义的

typedef enum
{ 
  FLASH_BUSY = 1,//操作忙
  FLASH_ERROR_RD,//读保护错误
  FLASH_ERROR_PGS,//编程顺序错误
  FLASH_ERROR_PGP,//编程并行位数错误
  FLASH_ERROR_PGA,//编程对齐错误
  FLASH_ERROR_WRP,//写保护错误
  FLASH_ERROR_PROGRAM,//编程错误
  FLASH_ERROR_OPERATION,//操作错误
  FLASH_COMPLETE//操作结束
}FLASH_Status;
3.1.5等待操作完成

在执行闪存写操作时,任何对闪存的读操作都会锁住总线,在写操作完成后 读操作才能正确地进行;既在进行写或擦除操作时,不能进行代码或数据的读取操作。所以在每次操作之前,我们都要等待上一次操作完成这次操作才能开始。

FLASH_Status FLASH_WaitForLastOperation(void)
{ 
  __IO FLASH_Status status = FLASH_COMPLETE;
   
  /* Check for the FLASH Status */
  status = FLASH_GetStatus();

  /* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
     Even if the FLASH operation fails, the BUSY flag will be reset and an error
     flag will be set */
  while(status == FLASH_BUSY)
  {
    status = FLASH_GetStatus();
  }
  /* Return the operation status */
  return status;
}
3.1.6读取FLASH指定地址数据
//读取指定地址的字(32 位数据) 
//faddr:读地址 
//返回值:对应数据. 
u32 STMFLASH_ReadWord(u32 faddr) 
{ return *(u32*)faddr; }

3.2FLASH读数据函数

//从指定地址开始读出指定长度的数据
//ReadAddr:起始地址
//pBuffer:数据指针
//NumToRead:字(4位)数
void STM32_FLASH_Read(u32 ReadAddr,u32 *pBuffer,u32 NumToRead)   	
{
	u32 i;
	for(i=0;i<NumToRead;i++)
	{
		pBuffer[i]=STM32_FLASH_ReadWord(ReadAddr);//读取4个字节.
		ReadAddr+=4;//偏移4个字节.	
	}
}

3.3FLASH写数据函数

//从指定地址开始写入指定长度的数据
//特别注意:因为STM32F4的扇区实在太大,没办法本地保存扇区数据,所以本函数
//         写地址如果非0XFF,那么会先擦除整个扇区且不保存扇区数据.所以
//         写非0XFF的地址,将导致整个扇区数据丢失.建议写之前确保扇区里
//         没有重要数据,最好是整个扇区先擦除了,然后慢慢往后写. 
//该函数对OTP区域也有效!可以用来写OTP区!
//OTP区域地址范围:0X1FFF7800~0X1FFF7A0F
//WriteAddr:起始地址(此地址必须为4的倍数!!)
//pBuffer:数据指针
//NumToWrite:字(32位)数(就是要写入的32位数据的个数.) 
void STM32_FLASH_Write(u32 WriteAddr,u32 *pBuffer,u32 NumToWrite)	
{ 
	FLASH_Status status = FLASH_COMPLETE;
	u32 addrx=0;
	u32 endaddr=0;	
	if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return;	//非法地址
	FLASH_Unlock();									//解锁 
	FLASH_DataCacheCmd(DISABLE);//FLASH擦除期间,必须禁止数据缓存
 		
	addrx=WriteAddr;				//写入的起始地址
	endaddr=WriteAddr+NumToWrite*4;	//写入的结束地址
	if(addrx<0X1FFF0000)			//只有主存储区,才需要执行擦除操作!!
	{
		while(addrx<endaddr)		//扫清一切障碍.(对非FFFFFFFF的地方,先擦除)
		{
			if(STM32_FLASH_ReadWord(addrx)!=0XFFFFFFFF)//有非0XFFFFFFFF的地方,要擦除这个扇区
			{   
				status=FLASH_EraseSector(STM32_FLASH_GetFlashSector(addrx),VoltageRange_3);//VCC=2.7~3.6V之间!!
				if(status!=FLASH_COMPLETE)break;	//发生错误了
			}else addrx+=4;
		} 
	}
	if(status==FLASH_COMPLETE)
	{
		while(WriteAddr<endaddr)//写数据
		{
			if(FLASH_ProgramWord(WriteAddr,*pBuffer)!=FLASH_COMPLETE)//写入数据
			{ 
				break;	//写入异常
			}
			WriteAddr+=4;
			pBuffer++;
		} 
	}
	FLASH_DataCacheCmd(ENABLE);	//FLASH擦除结束,开启数据缓存
	FLASH_Lock();//上锁
} 
//这个宏定义用法保存一下,挺好
const u8 text_buf[]="www.prechin.net";
#define TEXTLEN sizeof(text_buf)
#define TEXTSIZE (TEXTLEN/4+((TEXTLEN%4)?1:0))

讲解不到位的希望大家指出,有需要我讲解的部分,希望大家提出,我会出文档讲解。

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-09 18:36:52  更:2022-04-09 18:39:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 4:44:16-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码