此封装对上层应用接口友好,支持任意长度数据,可从操作失败的地方再次操作(不用重新开始),是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();
}
推荐将要写入的数据分割成数段,当一段写入成功后再写入下一段,如果失败可反复写这一段直到成功。