#ifndef FLASH_H
#define FLASH_H
#include "main.h"
#ifdef FLASH_C
#include "stm32f10x_flash.h"
void FLASH_Erase(uint Addr);
#endif
#define FLASH_BasePos 0x08000000
/*low-density devices*/
//#define FLASH_PAGE1024
//#define FLASH_EndPos 0x08004000 //x4
//#define FLASH_EndPos 0x08008000 //x6
//#define FLASH_SecSize 0x00000400
/*medium-density devices*/
//#define FLASH_PAGE1024
//#define FLASH_EndPos 0x08010000 //x8
//#define FLASH_EndPos 0x08020000 //xB
//#define FLASH_SecSize 0x00000400
/*high-density devices*/
#define FLASH_PAGE2048
#define FLASH_EndPos 0x08040000 //xC
//#define FLASH_EndPos 0x08060000 //xD
//#define FLASH_EndPos 0x08080000 //xE
#define FLASH_SecSize 0x00000800
typedef struct{
ushort Page;
ushort* Data;
ushort Length;
uint WriteAddr;
uchar Flag;
} FLASH_PageTypeDef;
ushort FLASH_Read(uint Addr);
void FLASH_WriteNoCheck(uint Addr, ushort Data);
void FLASH_WriteCheck (uint Addr, ushort* Data, ushort Length);
void FLASH_PageCopy (uint f_Addr, uint t_Addr);
void FLASH_PageWrite(FLASH_PageTypeDef* Page);
uchar FLASH_PageRead (FLASH_PageTypeDef* Page);
#endif
#define FLASH_C
#include "flash.h"
ushort SecBuf[FLASH_SecSize >> 1];
void FLASH_WriteNoCheck(uint Addr, ushort Data)
{
if(Addr < FLASH_BasePos || Addr >= FLASH_EndPos || Addr & 0x00000001)
{
return;
}
FLASH_Unlock();
FLASH_ProgramHalfWord(Addr, Data);
FLASH_Lock();
}
void FLASH_WriteCheck(uint Addr, ushort* Data, ushort Length)
{
if(Addr < FLASH_BasePos || Addr >= FLASH_EndPos || Addr & 0x00000001)
{
return;
}
uint SecNum = (Addr - FLASH_BasePos) / FLASH_SecSize;
uint SecPos = (Addr - FLASH_BasePos) % FLASH_SecSize;
uint SecHed = SecNum * FLASH_SecSize + FLASH_BasePos;
if(SecPos + (Length << 1) > FLASH_SecSize)
{
ushort ThisPage_Length = (FLASH_SecSize - SecPos) >> 1;
ushort NextPage_Length = Length - ThisPage_Length;
FLASH_WriteCheck(SecHed + FLASH_SecSize, Data + ThisPage_Length, NextPage_Length);
Length = ThisPage_Length;
}
for(ushort i = 0; i < SecPos; i += 2)
{
SecBuf[i >> 1] = FLASH_Read(SecHed + i);
}
ushort SecHalfPos = SecPos >> 1;
for(ushort i = 0; i < Length; i ++)
{
SecBuf[SecHalfPos + i] = Data[i];
}
for(ushort i = SecPos + (Length << 1); i < FLASH_SecSize; i += 2)
{
SecBuf[i >> 1] = FLASH_Read(SecHed + i);
}
FLASH_Unlock();
FLASH_ErasePage(SecHed);
ushort Write_Data;
for(ushort i = 0; i < FLASH_SecSize; i += 2)
{
Write_Data = SecBuf[i >> 1];
if(Write_Data == 0xFFFF) continue;
else FLASH_WriteNoCheck(SecHed + i, Write_Data);
}
FLASH_Lock();
}
void FLASH_PageCopy(uint f_Addr, uint t_Addr)
{
ushort SecHalfSize = FLASH_SecSize >> 1;
for(ushort i = 0; i < SecHalfSize; i ++)
{
SecBuf[i] = FLASH_Read(f_Addr + (i << 1));
}
FLASH_Unlock();
FLASH_ErasePage(t_Addr);
for(ushort i = 0; i < SecHalfSize; i ++)
{
if(SecBuf[i] == 0xFFFF) continue;
else FLASH_WriteNoCheck(t_Addr + (i << 1), SecBuf[i]);
}
FLASH_Lock();
}
void FLASH_Erase(uint Addr)
{
FLASH_Unlock();
FLASH_ErasePage(Addr);
FLASH_Lock();
}
void FLASH_PageWrite(FLASH_PageTypeDef* Page)
{
if(!Page->Flag) return;
for(ushort i = 0; i < Page->Length; i ++)
{
FLASH_WriteNoCheck(Page->WriteAddr + (i << 1), Page->Data[i]);
}
Page->Flag = 0;
}
uchar FLASH_PageRead(FLASH_PageTypeDef* Page)
{
uint HeadAddr = FLASH_BasePos + (Page->Page * FLASH_SecSize);
uint TailAddr = HeadAddr + FLASH_SecSize;
uint CurrAddr;
for(CurrAddr = HeadAddr; CurrAddr < TailAddr; CurrAddr += Page->Length)
{
uchar Flag = 1;
for(ushort i = 0; i < Page->Length && CurrAddr + (i << 1) < TailAddr; i ++)
{
if(FLASH_Read(CurrAddr + (i << 1)) != 0xFFFF)
{
Flag = 0;
break;
}
}
if(Flag)
{
break;
}
}
if(CurrAddr == HeadAddr)
{
Page->WriteAddr = HeadAddr;
Page->Flag = 1;
return 1;
}
for(ushort i = 0; i < Page->Length; i ++)
{
Page->Data[i] = FLASH_Read(CurrAddr - ((Page->Length - i) << 1));
}
if(CurrAddr + (Page->Length << 1) > TailAddr)
{
Page->WriteAddr = HeadAddr;
FLASH_Erase(HeadAddr);
}
else
{
Page->WriteAddr = CurrAddr;
}
Page->Flag = 1;
return 0;
}
ushort FLASH_Read(uint Addr)
{
return *(vu16*)Addr;
}