hi:
I wrote a flash driver like this:
In FlashDrv.c
#pragma CONST_SEG __GPAGE_SEG SYS_InfoFlash
volatile const uint16 FLASHDrv_dataTestUB; //定义在这里,用于占位
#pragma CONST_SEG DEFAULT
void FLASHDrv_Init(void)
{
if(FCLKDIV_FDIVLD == 0)
{
FCLKDIV = 39;
}
}
uint8 FLASHDrv_ProgramOneWord(uint16 * __far addrFLASHPUW , uint16 dataProgramUW)
{
if(FSTAT_ACCERR == 1)
{
FSTAT = 0x10;
}
if(FSTAT_PVIOL == 1)
{
FSTAT = 0x20;
}
while (!FSTAT_CBEIF)
FSTAT = 0x30;
*addrFLASHPUW = dataProgramUW;
FCMD = 0x20;
FSTAT = FSTAT | 0x80;
while (!FSTAT_CCIF)
{
if ((FSTAT_ACCERR == 1) || (FSTAT_PVIOL == 1))
{
return 0;
}
}
return 1;
}
uint8 FLASHDrv_SectorErase(uint16 * __far addrFLASHPUW)
{
if (FSTAT_ACCERR == 1)
{
FSTAT = 0x10;
}
if (FSTAT_PVIOL == 1)
{
FSTAT = 0x20;
}
while (!FSTAT_CBEIF)
FSTAT = 0x30;
*addrFLASHPUW = 0xffff;
FCMD = 0x40;
FSTAT = FSTAT | 0x80;
while (!FSTAT_CCIF)
{
if ((FSTAT_ACCERR == 1) || (FSTAT_PVIOL == 1))
{
return 0;
}
}
return 1;
}
uint8 FLASHDrv_MassWrite(uint16 * __far addrFLASHPUW, uint16 numByteUW, uint16 * __far addrDataPUW)
{
uint16 numCycleCntUW;
uint16 *__far addrFlashArrayPUW = addrFLASHPUW;
uint16 *__far addrDataArrayPUW = addrDataPUW;
uint16 numDataUW = *addrDataArrayPUW;
uint8 numReturn = 1;
if((((uint32)addrFLASHPUW%1024)==0)&&(numByteUW>0))
{
if(FLASHDrv_SectorErase(addrFLASHPUW))
{
if(numByteUW <= 2)
{
if(FLASHDrv_ProgramOneWord(addrFlashArrayPUW , numDataUW))
numReturn = 1;
else
numReturn = 0;
}
else
{
for(numCycleCntUW=2;numCycleCntUW<=numByteUW
{
numCycleCntUW += 2;
if(FLASHDrv_ProgramOneWord(addrFlashArrayPUW , numDataUW))
{
addrFlashArrayPUW++;
addrDataArrayPUW++;
numDataUW = *addrDataArrayPUW;
}
else
{
numReturn = 0;
break;
}
}
}
}
else
{
numReturn = 0;
}
}
return numReturn;
}
In prm file
SYS_InfoFlash INTO PAGE_FC;
In main.c
typedef struct
{
uint16 a;
uint8 b;
sint16 c;
uint16 d;
uint16 e;
uint8 f;
uint8 g;
uint32 h;
}flashteststruct;
flashteststruct flashtest;
flashteststruct flashtest2;
void main(void)
{
FLASHDrv_Init();
flashtest.a = 1;
flashtest.b = 3;
flashtest.c = 0xfa03;
flashtest.d = 0xc005;
flashtest.e = 0xe043;
flashtest.f = 0xbb;
flashtest.g = 0xdc;
flashtest.h = 0x1fa45;
FLASHDrv_MassWrite((uint16 *__far)&FLASHDrv_dataTestUB,sizeof(flashteststruct), (uint16 *__far)&flashtest);
FLASHDrv_MassRead((uint8 *__far)&FLASHDrv_dataTestUB,sizeof(flashteststruct), (uint8 *__far)&flashtest2);
}
my problem is when i run this program , the program can not run into for(; loop , the program is error, but when i allocate
SYS_InfoFlash INTO PAGE_E2; in prm file, the program run ok. i debuged this program in step mode, i found function FLASHDrv_MassWrite((uint16 *__far)&FLASHDrv_dataTestUB,sizeof(flashteststruct), (uint16 *__far)&flashtest) can't run correctly when i allocate SYS_InfoFlash INTO PAGE_FC. the program error is in function if(FLASHDrv_SectorErase(addrFLASHPUW)) .
another problem is when i changeed function uint8 FLASHDrv_SectorErase(uint16 * __far addrFLASHPUW) into
uint8 FLASHDrv_SectorErase(uint8 * __far addrFLASHPUW), no matter i allocate SYS_InfoFlash INTO PAGE_FC or
allocate SYS_InfoFlash INTO PAGE_E2, in two cases , the program all run correctly.
can anyone help me about this program,
thanks!
First of all this is wrong:
FSTAT = FSTAT | 0x80;
^^ this is attempt to clear not only CBEIF flag, but also all other FSTAT flags, which are set at the time CPU reads FSTAT.
You flash routines, or atlest part of them from the moment you clear CBEIF until CCIF is set, should execute from always available memory like RAM. Flash array is not readable while it is being erased or programmed. XDT256 has more then one flash bank and this explains why your routines work from one page and don't work from another. Why wrong attempt to use 8-bit writes to flash array didn't hand or reset MCU is also clear (uint8 FLASHDrv_SectorErase(uint8 * __far addrFLASHPUW). Doing so is banned by flash memory controller. You should see some error flags set.
So either program/erase flash from different flash array or EEPROM, or run you routines or above mentioned part of them from RAM. Don't forget to disable interrupts if vectors or interrupt handlers are placed in array that you are going to program/erase.
This thread explains how you could put your routine to RAM: