天天看點

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