zoukankan      html  css  js  c++  java
  • STM32内部Flash读写操作接口

    源文件

    /*
    *********************************************************************************************************
    *	函 数 名: GetSector
    *	功能说明: 根据地址计算扇区首地址
    *	形    参:  无
    *	返 回 值: 扇区首地址
    *********************************************************************************************************
    */
    uint32_t GetSector(uint32_t Address)
    {
    	uint32_t sector = 0;
    
    	if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
    	{
    		sector = FLASH_Sector_0;
    	}
    	else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
    	{
    		sector = FLASH_Sector_1;
    	}
    	else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
    	{
    		sector = FLASH_Sector_2;
    	}
    	else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
    	{
    		sector = FLASH_Sector_3;
    	}
    	else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
    	{
    		sector = FLASH_Sector_4;
    	}
    	else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
    	{
    		sector = FLASH_Sector_5;
    	}
    	else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
    	{
    		sector = FLASH_Sector_6;
    	}
    	else if((Address < ADDR_FLASH_SECTOR_8) && (Address >= ADDR_FLASH_SECTOR_7))
    	{
    		sector = FLASH_Sector_7;
    	}
    	else if((Address < ADDR_FLASH_SECTOR_9) && (Address >= ADDR_FLASH_SECTOR_8))
    	{
    		sector = FLASH_Sector_8;
    	}
    	else if((Address < ADDR_FLASH_SECTOR_10) && (Address >= ADDR_FLASH_SECTOR_9))
    	{
    		sector = FLASH_Sector_9;
    	}
    	else if((Address < ADDR_FLASH_SECTOR_11) && (Address >= ADDR_FLASH_SECTOR_10))
    	{
    		sector = FLASH_Sector_10;
    	}
    	else	/*(Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_11))*/
            {
    		sector = FLASH_Sector_11;
    	}
    	return sector;
    }
    
    /*
    *********************************************************************************************************
    *	函 数 名: ReadCpuFlash
    *	功能说明: 读取CPU Flash的内容
    *	形    参:  _ucpDst : 目标缓冲区
    *			 _ulFlashAddr : 起始地址
    *			 _ulSize : 数据大小(单位是字节)
    *	返 回 值: 0=成功,1=失败
    *********************************************************************************************************
    */
    uint8_t ReadCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpDst, uint32_t _ulSize)
    {
    	uint32_t i;
    
    	/* 如果偏移地址超过芯片容量,则不改写输出缓冲区 */
    	if (_ulFlashAddr + _ulSize > FLASH_BASE_ADDR + FLASH_SIZE)
    		return 1;
    
    	/* 长度为0时不继续操作,否则起始地址为奇地址会出错 */
    	if (_ulSize == 0)
    		return 1;
    
    	for (i = 0; i < _ulSize; i++)
    	{
    		*_ucpDst++ = *(uint8_t *)_ulFlashAddr++;
    	}
    	return 0;
    }
    /*
    *********************************************************************************************************
    *	函 数 名: CmpCpuFlash
    *	功能说明: 比较Flash指定地址的数据.
    *	形    参: _ulFlashAddr : Flash地址
    *			 _ucpBuf : 数据缓冲区
    *			 _ulSize : 数据大小(单位是字节)
    *	返 回 值:
    *			FLASH_IS_EQU		0   Flash内容和待写入的数据相等,不需要擦除和写操作
    *			FLASH_REQ_WRITE		1	Flash不需要擦除,直接写
    *			FLASH_REQ_ERASE		2	Flash需要先擦除,再写
    *			FLASH_PARAM_ERR		3	函数参数错误
    *********************************************************************************************************
    */
    uint8_t CmpCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpBuf, uint32_t _ulSize)
    {
    	uint32_t i;
    	uint8_t ucIsEqu;	/* 相等标志 */
    	uint8_t ucByte;
    
    	/* 如果偏移地址超过芯片容量,则不改写输出缓冲区 */
    	if (_ulFlashAddr + _ulSize > FLASH_BASE_ADDR + FLASH_SIZE)
    		return FLASH_PARAM_ERR;		/* 函数参数错误 */
    
    	/* 长度为0时返回正确 */
    	if (_ulSize == 0)
    		return FLASH_IS_EQU;		/* Flash内容和待写入的数据相等 */
    
    	ucIsEqu = 1;			/* 先假设所有字节和待写入的数据相等,如果遇到任何一个不相等,则设置为 0 */
    	for (i = 0; i < _ulSize; i++)
    	{
    		ucByte = *(uint8_t *)_ulFlashAddr;
    
    		if (ucByte != *_ucpBuf)
    		{
    			if (ucByte != 0xFF)
    			{
    				return FLASH_REQ_ERASE;		/* 需要擦除后再写 */
    			}
    			else
    			{
    				ucIsEqu = 0;	/* 不相等,需要写 */
    			}
    		}
    
    		_ulFlashAddr++;
    		_ucpBuf++;
    	}
    
    	if (ucIsEqu == 1)
    		return FLASH_IS_EQU;	/* Flash内容和待写入的数据相等,不需要擦除和写操作 */
    	else
    		return FLASH_REQ_WRITE;	/* Flash不需要擦除,直接写 */
    }
    
    /*
    *********************************************************************************************************
    *	函 数 名: WriteCpuFlash
    *	功能说明: 写数据到CPU 内部Flash。
    *	形    参: _ulFlashAddr : Flash地址
    *			 _ucpSrc : 数据缓冲区
    *			 _ulSize : 数据大小(单位是字节)
    *	返 回 值: 0-成功,1-数据长度或地址溢出,2-写Flash出错(估计Flash寿命到)
    *********************************************************************************************************
    */
    uint8_t WriteCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpSrc, uint32_t _ulSize)
    {
    	uint32_t i;
    	uint8_t ucRet;
    
    	/* 如果偏移地址超过芯片容量,则不改写输出缓冲区 */
    	if (_ulFlashAddr + _ulSize > FLASH_BASE_ADDR + FLASH_SIZE)
    		return 1;
    
    	/* 长度为0时不继续操作  */
    	if (_ulSize == 0)
    		return 0;
    
    	ucRet = bsp_CmpCpuFlash(_ulFlashAddr, _ucpSrc, _ulSize);
    	if (ucRet == FLASH_IS_EQU)
    		return 0;
    
    	__set_PRIMASK(1);  		/* 关中断 */
    
    	/* FLASH 解锁 */
    	FLASH_Unlock();
    
      	/* Clear pending flags (if any) */
    	FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR |
                      FLASH_FLAG_PGAERR | FLASH_FLAG_PGPERR|FLASH_FLAG_PGSERR);
    
    	/* 需要擦除 */
    	if (ucRet == FLASH_REQ_ERASE)
    	{
    		FLASH_EraseSector(bsp_GetSector(_ulFlashAddr), VoltageRange_3);
    	}
    	/* 按字节模式编程(为提高效率,可以按字编程,一次写入4字节) */
    	for (i = 0; i < _ulSize; i++)
    	{
    		FLASH_ProgramByte(_ulFlashAddr++, *_ucpSrc++);
    	}
      	/* Flash 加锁,禁止写Flash控制寄存器 */
      	FLASH_Lock();
      	__set_PRIMASK(0);  		/* 开中断 */
    	return 0;
    }
    
    

    头文件

    #ifndef _BSP_CPU_FLASH_H_
    #define _BSP_CPU_FLASH_H_
    
    #define FLASH_BASE_ADDR	0x08000000			/* Flash基地址 */
    #define	FLASH_SIZE		(1*1024*1024)		/* Flash 容量 */
    
    /* Base address of the Flash sectors */
    #define ADDR_FLASH_SECTOR_0     ((uint32_t)0x08000000) /* Base @ of Sector 0, 16 Kbytes */
    #define ADDR_FLASH_SECTOR_1     ((uint32_t)0x08004000) /* Base @ of Sector 1, 16 Kbytes */
    #define ADDR_FLASH_SECTOR_2     ((uint32_t)0x08008000) /* Base @ of Sector 2, 16 Kbytes */
    #define ADDR_FLASH_SECTOR_3     ((uint32_t)0x0800C000) /* Base @ of Sector 3, 16 Kbytes */
    #define ADDR_FLASH_SECTOR_4     ((uint32_t)0x08010000) /* Base @ of Sector 4, 64 Kbytes */
    #define ADDR_FLASH_SECTOR_5     ((uint32_t)0x08020000) /* Base @ of Sector 5, 128 Kbytes */
    #define ADDR_FLASH_SECTOR_6     ((uint32_t)0x08040000) /* Base @ of Sector 6, 128 Kbytes */
    #define ADDR_FLASH_SECTOR_7     ((uint32_t)0x08060000) /* Base @ of Sector 7, 128 Kbytes */
    #define ADDR_FLASH_SECTOR_8     ((uint32_t)0x08080000) /* Base @ of Sector 8, 128 Kbytes */
    #define ADDR_FLASH_SECTOR_9     ((uint32_t)0x080A0000) /* Base @ of Sector 9, 128 Kbytes */
    #define ADDR_FLASH_SECTOR_10    ((uint32_t)0x080C0000) /* Base @ of Sector 10, 128 Kbytes */
    #define ADDR_FLASH_SECTOR_11    ((uint32_t)0x080E0000) /* Base @ of Sector 11, 128 Kbytes */
    
    #define FLASH_IS_EQU		0    /* Flash内容和待写入的数据相等,不需要擦除和写操作 */
    #define FLASH_REQ_WRITE		1    /* Flash不需要擦除,直接写 */
    #define FLASH_REQ_ERASE		2    /* Flash需要先擦除,再写 */
    #define FLASH_PARAM_ERR		3    /* 函数参数错误 */
    
    uint8_t ReadCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpDst, uint32_t _ulSize); /* 按地址读取指定大小的内容 */
    uint8_t WriteCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpSrc, uint32_t _ulSize); /* 按地址写入指定大小的内容 */
    uint8_t CmpCpuFlash(uint32_t _ulFlashAddr, uint8_t *_ucpBuf, uint32_t _ulSize); /* 比较flash内容 */
    
    #endif
    
    Posted By veis
  • 相关阅读:
    Struts系列教材 (四)- 基础
    Struts系列教材 (三)- 基础
    Struts系列教材 (一)- 基础
    Hibernate系列教材 (三十)- 注解
    网络之AFNetworking
    iOS网络学习之“远离NSURLConnection 走进NSURLSession”
    ios中常见数据存储方式以及SQLite常用的语句
    利用"仿射变换"制作“酷炫特效”
    图片滚动新闻和新闻的滚动菜单
    简易聊天窗口
  • 原文地址:https://www.cnblogs.com/veis/p/14702716.html
Copyright © 2011-2022 走看看