封裝對STM32的Flash讀寫操作

此封裝對上層應用接口友好,支持任意長度數據,可從操作失敗的地方再次操作(不用重新開始),是IAP必備之選!

Flsh.h文件內容如下

#ifndef __FLASH_H
#define __FLASH_H

/* Includes ------------------------------------------------------------------*/
#include "stm32f10x.h"

/* Define the STM32F10x FLASH Page Size depending on the used STM32 device */
#if defined (STM32F10X_HD) || defined (STM32F10X_HD_VL) || defined (STM32F10X_CL) || defined (STM32F10X_XL)
  #define FLASH_PAGE_SIZE    ((uint16_t)0x800)
#else
  #define FLASH_PAGE_SIZE    ((uint16_t)0x400)
#endif

/* Interface functions ---------------------------------------------------------*/
void Flash_InitOperation(void);
FLASH_Status Flash_WriteOperation(const void* pBuffer, uint16_t Length);
void Flash_EndOperation(void);


#endif


Flsh.c文件內容如下

#include "Flash.h"

/* Private define ------------------------------------------------------------*/
#define  FLASH_WriteAddress     ((uint32_t)0x08005000)		//前20KB留給IAP,APP從0x08005000開始運行

typedef enum {FAILED = 0, PASSED = !FAILED} STATUS;

/* Private variables ---------------------------------------------------------*/ 
uint16_t EraseCounter;
uint32_t WriteAddress;
uint16_t RemainSpace;

/* Private functions ---------------------------------------------------------*/
STATUS Flash_CompareOperation(const void* pBuffer, uint32_t Address, uint16_t Length);

void Flash_InitOperation(void)
{
	EraseCounter = 0;
	WriteAddress = FLASH_WriteAddress;
	RemainSpace = 0;
	FLASH_LockBank1();
	
	/* Unlock the Flash Bank1 Program Erase controller */
  FLASH_UnlockBank1();

  /* Clear All pending flags */
  FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);	
}

FLASH_Status Flash_WriteOperation(const void* pBuffer, uint16_t Length)
{
	FLASH_Status FLASHStatus = FLASH_COMPLETE;
	uint16_t i, j, off;
	uint16_t NbrOfPage = 0;
	uint16_t* p16 = NULL;
	uint32_t* p32 = NULL;
	uint8_t* p8 = NULL;

	if(Length > RemainSpace)
	{
		NbrOfPage = (Length-RemainSpace)/FLASH_PAGE_SIZE + 1;
	}
	
	for(j = 0; (j < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); j++, EraseCounter++)
  {
    FLASHStatus = FLASH_ErasePage(FLASH_WriteAddress + (FLASH_PAGE_SIZE * EraseCounter));
  }
	
	i = 0;
	off = 0;
	p32 = (uint32_t*)pBuffer;
	while((i*4 < Length-3) && (FLASHStatus == FLASH_COMPLETE))
  {
    FLASHStatus = FLASH_ProgramWord(WriteAddress, p32[i++]);
    WriteAddress += 4;
  }
	
	off = i*4;
	p16 = (uint16_t*)pBuffer;
	if((off+1 < Length) && (FLASHStatus == FLASH_COMPLETE))
	{
		FLASHStatus = FLASH_ProgramHalfWord(WriteAddress, p16[i*2]);
    WriteAddress += 2;
		off += 2;
	}
	
	p8 = (uint8_t*)pBuffer;
	if((off < Length) && (FLASHStatus == FLASH_COMPLETE))
	{
		FLASHStatus = FLASH_ProgramOptionByteData(WriteAddress, p8[off]);
    WriteAddress += 1;
	}

	FLASH_LockBank1();	//如果不關閉,Flash讀操作有可能會擦除Flash - 2014.06.24
	
	if( PASSED == Flash_CompareOperation(pBuffer, WriteAddress-Length, Length) )
	{
		RemainSpace += FLASH_PAGE_SIZE*j - Length;
	}
	else
	{
		WriteAddress -= Length;
		EraseCounter -= j;
		FLASH_ErasePage(WriteAddress);
		FLASHStatus = FLASH_ERROR_PG;
	}

	FLASH_UnlockBank1();
	
	return FLASHStatus;
}

STATUS Flash_CompareOperation(const void* pBuffer, uint32_t Address, uint16_t Length)
{
	STATUS MemoryProgramStatus = PASSED;
	uint16_t i, off;
	uint16_t* p16 = NULL;
	uint32_t* p32 = NULL;
	uint8_t* p8 = NULL;
	
	i = 0;
	off = 0;
	p32 = (uint32_t*)pBuffer;
	while((i*4 < Length-3) && (MemoryProgramStatus != FAILED))
  {
		if((*(__IO uint32_t*) Address) != p32[i++])
    {
      MemoryProgramStatus = FAILED;
    }
    Address += 4;
  }
	
	off = i*4;
	p16 = (uint16_t*)pBuffer;
	if((off+1 < Length) && (MemoryProgramStatus != FAILED))
	{
		if((*(__IO uint32_t*) Address) != p16[i*2])
    {
      MemoryProgramStatus = FAILED;
    }
    Address += 2;
		off += 2;
	}
	
	p8 = (uint8_t*)pBuffer;
	if((off < Length) && (MemoryProgramStatus != FAILED))
	{
		if((*(__IO uint32_t*) Address) != p8[off])
    {
      MemoryProgramStatus = FAILED;
    }
	}
	
	return MemoryProgramStatus;
}

void Flash_EndOperation(void)
{
	FLASH_LockBank1();
}

推薦將要寫入的數據分割成數段,當一段寫入成功後再寫入下一段,如果失敗可反覆寫這一段直到成功。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章