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操作笔记

一.在文件stm32f4xx_hal_flash_ex.h中有对应的文件标号定义如下:

/*--------------------------------------- STM32F40xxx/STM32F41xxx -------------------------------------*/ 
#if defined(STM32F405xx) || defined(STM32F415xx) || defined(STM32F407xx) || defined(STM32F417xx) || defined(STM32F412Zx) ||\
    defined(STM32F412Vx) || defined(STM32F412Rx) || defined(STM32F412Cx)  
#define OB_WRP_SECTOR_0       0x00000001U /*!< Write protection of Sector0     */
#define OB_WRP_SECTOR_1       0x00000002U /*!< Write protection of Sector1     */
#define OB_WRP_SECTOR_2       0x00000004U /*!< Write protection of Sector2     */
#define OB_WRP_SECTOR_3       0x00000008U /*!< Write protection of Sector3     */
#define OB_WRP_SECTOR_4       0x00000010U /*!< Write protection of Sector4     */
#define OB_WRP_SECTOR_5       0x00000020U /*!< Write protection of Sector5     */
#define OB_WRP_SECTOR_6       0x00000040U /*!< Write protection of Sector6     */
#define OB_WRP_SECTOR_7       0x00000080U /*!< Write protection of Sector7     */
#define OB_WRP_SECTOR_8       0x00000100U /*!< Write protection of Sector8     */
#define OB_WRP_SECTOR_9       0x00000200U /*!< Write protection of Sector9     */
#define OB_WRP_SECTOR_10      0x00000400U /*!< Write protection of Sector10    */
#define OB_WRP_SECTOR_11      0x00000800U /*!< Write protection of Sector11    */
#define OB_WRP_SECTOR_All     0x00000FFFU /*!< Write protection of all Sectors */
#endif /* STM32F405xx || STM32F415xx || STM32F407xx || STM32F417xx || STM32F412Zx || STM32F412Vx || STM32F412Rx || STM32F412Cx */
/*-----------------------------------------------------------------------------------------------------*/

对于头文件的定义internal_flash.h用户自定义,以1mb的内部flash的stm32为例:

#ifndef _INTERNAL_FLASH_H
#define _INTERNAL_FLASH_H

#include "main.h"


#define ADDR_FLASH_SECTOR_0     ((uint32_t)0x08000000) 	
#define ADDR_FLASH_SECTOR_1     ((uint32_t)0x08004000) 	
#define ADDR_FLASH_SECTOR_2     ((uint32_t)0x08008000) 	
#define ADDR_FLASH_SECTOR_3     ((uint32_t)0x0800C000) 	 
#define ADDR_FLASH_SECTOR_4     ((uint32_t)0x08010000) 	
#define ADDR_FLASH_SECTOR_5     ((uint32_t)0x08020000) 	
#define ADDR_FLASH_SECTOR_6     ((uint32_t)0x08040000) //程序存储区域
#define ADDR_FLASH_SECTOR_7     ((uint32_t)0x08060000) 	
#define ADDR_FLASH_SECTOR_8     ((uint32_t)0x08080000) 	
#define ADDR_FLASH_SECTOR_9     ((uint32_t)0x080A0000) 	 
#define ADDR_FLASH_SECTOR_10    ((uint32_t)0x080C0000) 	 
#define ADDR_FLASH_SECTOR_11    ((uint32_t)0x080E0000) 	 
#define ADDR_FLASH_SECTOR_12    ((uint32_t)0x08100000) 	


/*STM32F405 FLASH从前往后由4块16K,一块64K,7块128K字节的扇区组成,每片扇区在写之前要确保全为1,总共1024K*/
//BIN文件具体数据的存储地址
//#define NORMAL_APP_EXIST_FLAG_ADDR   ADDR_FLASH_SECTOR_5    //文件是否存在地址,为1表示文件存在//文件存储的的地址
#define NORMAL_APP_EXIST_FLAG_ADDR   ADDR_FLASH_SECTOR_7    //文件是否存在地址,为1表示文件存在//文件存储的的地址
#define NORMAL_APP_EXIST_FLAG_SIZE   4                      //设定4个字节
#define NORMAL_APP_Version_ADDR      NORMAL_APP_EXIST_FLAG_ADDR+NORMAL_APP_EXIST_FLAG_SIZE//BIN文件版本号存储的地址             
#define NORMAL_APP_Version_SIZE      4                     //设定4个字节
#define NORMAL_APP_CRC_ADDR          NORMAL_APP_Version_ADDR+NORMAL_APP_Version_SIZE//上位机发送下来的CRC32  
#define NORMAL_APP_CRC_SIZE          4//设定4个字节
#define NORMAL_APP_LEN_ADDR          NORMAL_APP_CRC_ADDR+NORMAL_APP_CRC_SIZE//文件长度设置为四个字节
#define NORMAL_APP_LEN_SIZE          4
#define NORMAL_APP_DATA_ADDR         NORMAL_APP_LEN_ADDR+NORMAL_APP_LEN_SIZE//接下来BIN文件具体数据的存储地址


自检程序存储的地址和参数--扩展功能<需求未提出,此内容应该时存储标准板的bin文件>
#define SELCHECK_APP_EXIST_FLAG_ADDR   ADDR_FLASH_SECTOR_6    //文件是否存在地址,为1表示文件存在
#define SELCHECK_APP_EXIST_FLAG_SIZE   4             //字节
#define SELCHECK_APP_Version_ADDR      SELCHECK_APP_EXIST_FLAG_ADDR+SELCHECK_APP_EXIST_FLAG_SIZE  //BIN文件版本号存储的地址                
#define SELCHECK_APP_Version_SIZE      4
#define SELCHECK_APP_CRC_ADDR          SELCHECK_APP_Version_ADDR+SELCHECK_APP_Version_SIZE//上位机发送下来的CRC32  
#define SELCHECK_APP_CRC_SIZE          4
#define SELCHECK_APP_LEN_ADDR          SELCHECK_APP_CRC_ADDR+SELCHECK_APP_CRC_SIZE//文件长度设置为四个字节
#define SELCHECK_APP_LEN_SIZE          4
#define SELCHECK_APP_DATA_ADDR         SELCHECK_APP_LEN_ADDR+SELCHECK_APP_LEN_SIZE//接下来BIN文件具体数据的存储地址
/*****************************************************************************/



//flash存储的基本地址
#define STM32_FLASH_BASE      0x08000000 	
#define FLASH_WAITETIME  50000          //FLASH等待超时时间

void Flash_Write(uint32_t WriteAddr,uint32_t *pBuffer,uint32_t NumToWrite);
void Flash_Read(uint32_t ReadAddr,uint32_t *pBuffer,uint32_t NumToRead);
void Flash_Test(void);

#endif

internal_flash.c文件的定义如下:

#include "internal_flash.h"

/设置串口打印的宏定义,减少代码运行效率///
#if defined(flash_CONN_LOG)
#define flash_log_print(format, ...)      printf(format, ##__VA_ARGS__)
#else
#define flash_log_print(format, ...) 
#endif
/**
函数名:Flash_GetFlashSector
函数功能:用于获取扇区的标号
参数:地址
    

返回值:地址所在扇区的标号
**/
static uint8_t Flash_GetFlashSector(uint32_t addr)
{
	if(addr<ADDR_FLASH_SECTOR_1)return 0;
	else if(addr<ADDR_FLASH_SECTOR_2)return 1;
	else if(addr<ADDR_FLASH_SECTOR_3)return 2;
	else if(addr<ADDR_FLASH_SECTOR_4)return 3;
	else if(addr<ADDR_FLASH_SECTOR_5)return 4;
	else if(addr<ADDR_FLASH_SECTOR_6)return 5;
	else if(addr<ADDR_FLASH_SECTOR_7)return 6;
	else if(addr<ADDR_FLASH_SECTOR_8)return 7;
	else if(addr<ADDR_FLASH_SECTOR_9)return 8;
	else if(addr<ADDR_FLASH_SECTOR_10)return 9;
	else if(addr<ADDR_FLASH_SECTOR_11)return 10;
	else return 10; 
}


/**
函数名:Flash_ReadWord
函数功能:用于获取当前要读取的位置字节数据的地址
参数:读取的地址数据
    

返回值:返回数据地址
**/
static uint32_t Flash_ReadWord(uint32_t faddr)
{
	  return *(int32_t*)faddr; 
} 

/**
函数名:Flash_Read
函数功能:读取相应地址的数据
参数:要读的地址
			存储数据的数据缓存地址
			读取的长度

返回值:
**/
void Flash_Read(uint32_t ReadAddr,uint32_t *pBuffer,uint32_t NumToRead)   	
{
	uint32_t i;
	for(i=0;i<NumToRead;i++)
	{
	  pBuffer[i]=Flash_ReadWord(ReadAddr);//读取开始地址到NumToRead个数据放到缓存区
	  ReadAddr+=4;
	}
}
/**
函数名:Flash_Write
函数功能:向flash写入数据
参数:要写入的首地址
			存储要写的数据的地址
			长度

返回值:
**/
void Flash_Write(uint32_t WriteAddr,uint32_t *pBuffer,uint32_t NumToWrite)
{
	FLASH_EraseInitTypeDef FlashEraseInit;//要进行擦除的结构体初始化
	HAL_StatusTypeDef FlashStatus=HAL_OK; //flash状态共用体,初始化
	uint32_t SectorError=0;
	uint32_t addrx=0,endaddr=0;
	if(WriteAddr<STM32_FLASH_BASE||WriteAddr%4)return; //非法地址,小于0x08000000,不是4的整数倍
	HAL_FLASH_Unlock(); //解锁
	addrx=WriteAddr; //写入的起始地址
	endaddr=WriteAddr+NumToWrite*4; //写入的结束地址
	if(addrx<ADDR_FLASH_SECTOR_12)//判断写入地址是否超出界限
	{
		while(addrx<endaddr) //扫清一切障碍.(对非 FFFFFFFF 的地方,先擦除)
		{
			if(Flash_ReadWord(addrx)!=0XFFFFFFFF)//读取要写的地址是否无有数据,有数据时执行if操作。
			{
				FlashEraseInit.TypeErase=FLASH_TYPEERASE_SECTORS; //类型扇区擦除
				FlashEraseInit.Sector=Flash_GetFlashSector(addrx); //要擦除的扇区
				FlashEraseInit.NbSectors=1; //一次只擦除一个扇区
				FlashEraseInit.VoltageRange=FLASH_VOLTAGE_RANGE_3;//VCC=2.7~3.6V 按照字进行擦除
				if(HAL_FLASHEx_Erase(&FlashEraseInit,&SectorError)!=HAL_OK)
				{
					break;//发生错误了
				}
			}
			else
				addrx+=4;//地址偏移到下一个字,进行循环擦除
				FLASH_WaitForLastOperation(FLASH_WAITETIME); //等待上次操作完成
			}
	}
	FlashStatus=FLASH_WaitForLastOperation(FLASH_WAITETIME); //等待上面的擦除操作彻底完成
	
	if(FlashStatus==HAL_OK)
	{
		while(WriteAddr<endaddr)//写数据
		{
			if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,WriteAddr,*pBuffer)!=HAL_OK)//写入数据
			{
				break; //写入异常
			}
			WriteAddr+=4;
			pBuffer++;
		}
	}
	HAL_FLASH_Lock(); //上锁

}
/**
函数名:Flash_Test
函数功能:用来测试写入和读取操作正常否
参数:
    

返回值:
**/
void Flash_Test(void)
{
	uint32_t test = 0x01020304;
	uint32_t test1 = 0xaabbccdd; 
	uint32_t test2 = 0xaabb4098;

	Flash_Write(SELCHECK_APP_EXIST_FLAG_ADDR,  &test, 1);//文件是否存在地址,为1表示文件存在
	Flash_Read(SELCHECK_APP_EXIST_FLAG_ADDR, &test, 1);
	flash_log_print("test:%x\n",test);

	Flash_Write(SELCHECK_APP_Version_ADDR,  &test1, 1); //BIN文件版本号存储的地址    
	Flash_Read(SELCHECK_APP_Version_ADDR, &test1, 1);
	flash_log_print("test1:%x\n",test1);

	Flash_Write(NORMAL_APP_CRC_ADDR,  &test2, 1);//文件长度设置为四个字节
	Flash_Read(NORMAL_APP_CRC_ADDR, &test2, 1);
	flash_log_print("test2:%x\n",test2);

}
  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-12-14 16:07:28  更:2021-12-14 16:09:51 
 
开发: 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 14:32:02-

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