stm32内部Flash擦写流程,对于FLash必须按页擦写,不同型号的flash页大小不同,需要根据实际修改
#define FLASH_PAGE_SIZE 2048 //定义Flash页大小,RCT6页大小为2K(2048),c8t6为1k(1024)
/*
*对STM32内部FLASH写进行编程操作,需要遵循以下流程:
*1.FLASH解锁
*2.清除相关标志位
*3.擦除FLASH(先擦除后写入的原因是为了工业上制作方便,即物理实现方便)
*4.写入FLASH
*5.锁定FLASH
*/
//计算需要擦除的页数
static uint32_t FLASH_PagesMask(uint32_t len)
{
uint32_t pagenumber = 0;
if ((len % FLASH_PAGE_SIZE) != 0)
{
pagenumber = (len / FLASH_PAGE_SIZE) + 1;
}
else
{
pagenumber = len / FLASH_PAGE_SIZE;
}
return pagenumber;
}
//向startAddr地址写入p_data数据,长度为len个字节,Earse_flag为1表示需要擦除Flash,返回0表示写入成功
uint8_t flash_write(uint32_t startAddr,uint8_t *p_data,uint32_t len,uint8_t Earse_flag)
{
volatile FLASH_Status FLASHStatus; //FLASH状态
uint32_t EndAddr = startAddr + len; //末地址
uint32_t NbrOfPage = 0;
uint32_t EraseCounter = 0x0, Address = 0x0;
uint16_t MemoryProgramStatus = 0,i;
uint32_t writeData;
FLASH_Unlock(); //FLASH解锁
//清除所有已有标志
FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
if(Earse_flag)
{
//擦除
NbrOfPage = FLASH_PagesMask(len); //有多少个页被擦除
FLASHStatus = FLASH_COMPLETE;
for(EraseCounter = 0;(EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
{
FLASHStatus = FLASH_ErasePage(startAddr+(FLASH_PAGE_SIZE*EraseCounter));
}
if(FLASHStatus!=FLASH_COMPLETE)
{
return 1;
}
}
else
{
FLASHStatus = FLASH_COMPLETE;
}
Address = startAddr;
for(i = 0; (Address < EndAddr) && (FLASHStatus==FLASH_COMPLETE); Address += 4) //+=2
{
writeData = p_data[i]|(p_data[i+1]<<8)|(p_data[i+2]<<16)|(p_data[i+3]<<24);
FLASHStatus=FLASH_ProgramWord(Address,writeData);
i += 4;
}
if(FLASHStatus!=FLASH_COMPLETE)
{
return 1;
}
FLASH_Lock();
Address = startAddr;
for(i = 0 ;(Address < EndAddr) && (MemoryProgramStatus != 1);Address += 1)
{
if((*(vu8*)Address != p_data[i++]))
{
MemoryProgramStatus = 1;
return 1;
}
}
return 0;
}
void flash_read(uint32_t startAddr,uint8_t *p_data,uint16_t len)
{
uint32_t address = startAddr;
uint16_t i;
for(i=0; i < len; i++)
{
p_data[i] = (*(vu8*)address);
address++;
}
}