📄 km29ux.c
字号:
#include <string.h>
#include "..\inc\44b.h"
#include "..\inc\44blib.h"
#include "..\inc\def.h"
#include "..\inc\km29ux.h"
//KM29U128T
/****************** CAUTION ***********************
1) PA7,4,2 has to be configured as an output port
2) PA3 has to be configured as an input port
3) GCS3 has to be configured as 8-bit,
tcos=1,tacc=4 @ 60Mhz, tcos has to exist!!!
4) caching has to be disabled on nGCS3
5) write buffer has to be turned off.
**************************************************/
//The code is made for bi-endian mode
/*
1999.5 Wireless Div. Circuit for KS32C41000
H/W connection.
F_nSE= L
F_nRE= nGCS3 | nOE
F_nWE= nGCS3 | nWE
F_CLE= PA4
F_ALE= PA7
F_RB = PA3
F_nCE = PA2
*/
// blk0:page0 : reserved
// blk0:page1,2,3,4: Block Information Table :
// good block:used block:logical block number
// unused block:FFFF
// bad block: F0F0
#define WRITEVERIFY (1) //verifing is enable at writing.
#define PAGE2BLOCKID(page32) (page32>>5)
#define ALE (0x80)
#define CLE (0x10)
#define CE (0x04)
#define RB (0x08)
#define FC_CMD {rPDATA|=CLE;rPDATA&=~(ALE|CE);}
#define FC_ADDR {rPDATA|=ALE;rPDATA&=~(CLE|CE);}
#define FC_DATA {rPDATA&=~(ALE|CLE|CE);}
#define FC_INACTIVE {rPDATA|=CE;rPDATA&=~(ALE|CLE);}
#define WAITRB while(!(rPDATA&RB))
//wait tWB and check R/B pin.
#define rKM29UXDATA (*(volatile U8 *)0x6000000)
static U16 blockLookupTable[1024+8]; //logical blockId # ->physical block #
//8 is spare area for loading 528bytes.
static unsigned lastPage=0;
static unsigned isOpen=0;
// 1block=528bytes x 32pages
// 1024block
// A[23:14][13:9]
// block page
int Nf_Format(int page32)
//returns the allocated good block excluding BIT.
{
int i;
int error=0,retry=0;
int blockCnt;
int blockId;
U8 buffer[528];
unsigned int bp0,bp1;
U8 *phyStTbl=(U8 *)blockLookupTable;
if((page32%32)!=0)return 0;
blockCnt=page32/32;
//check if the flash had been formatted.
if(_CheckId()!=0xec73) //check KM29U128T
{
Uart_Printf("ID Error!!!\n");
return 0;
}
_RdPage(0,0,buffer);
if(buffer[0]=='N')return 0;
blockId=0;
phyStTbl[0]=0xf5; //For BIT
phyStTbl[1]=0xf5;
for(i=1;i<1024;i++)
{
_RdPage(i,0,buffer);bp0=buffer[0];
_RdPage(i,0,buffer);bp1=buffer[0];
if(bp0==0xff && bp1==0xff)
{ //good block
if(blockId < blockCnt)
{
//good block have blcokId
phyStTbl[2*i]=blockId &0xff;
phyStTbl[2*i+1]=(blockId>>8) &0xff;
blockId++;
}
else
{
phyStTbl[2*i]=0xff; //unused good block have 0xffff instead of blcokId
phyStTbl[2*i+1]=0xff;
}
}
else
{ //bad block
//bad block have 0xffff instead of blcokId
phyStTbl[2*i]=0xf0;
phyStTbl[2*i+1]=0xf0;
Uart_Printf("BAD BLOCK #=%d\n",i);
}
}
while(1)
{
for(i=0;i<528;i++)buffer[i]=0;
memcpy(buffer,"NAND 128M MODE2",16);
if(!_WrPage(0,0,buffer))error++;
memcpy(buffer,phyStTbl+0x0,512);
if(!_WrPage(0,1,buffer))error++;
memcpy(buffer,phyStTbl+0x200,512);
if(!_WrPage(0,2,buffer))error++;
memcpy(buffer,phyStTbl+0x400,512);
if(!_WrPage(0,3,buffer))error++;
memcpy(buffer,phyStTbl+0x600,512);
if(!_WrPage(0,4,buffer))error++;
if(error==0)break;
error=0;
if(++retry==3)return 0; //retry error!!! unusable NAND flash
_EraseBlock(0); //erase physical block #0 for retry
}
return blockId; //returns the allocated good block excluding BIT.
}
int Nf_Open(void)
//returns the last page #
{
int i,j;
U8 buffer[2048+16];
int lBlock=0;
if(_CheckId()!=0xec73) //check KM29U128T
{
Uart_Printf("ID Error!!!\n");
return 0;
}
_RdPage(0,0,buffer+0); //check if the flash is formatted.
if(buffer[0]!='N')return 0;
_RdPage(0,1,buffer+0);
_RdPage(0,2,buffer+0x200);
_RdPage(0,3,buffer+0x400);
_RdPage(0,4,buffer+0x600);
for(i=0;i<1024;i++)blockLookupTable[i]=0xffff;
for(i=1;i<1024;i++)
{
j=(U8)buffer[i*2]+((U8)buffer[i*2+1])*0x100;
if(j!=0xf0f0 && j!=0xffff){blockLookupTable[j]=i;lBlock++;}
}
lastPage=(lBlock)*32-1; //total page count.
//check the Block Information Table Integrity.
for(i=0;i<lBlock;i++)
{
if(blockLookupTable[i]==0xffff)return 0; //error!!!
}
isOpen=1;
return lastPage;
}
int Nf_EraseBlock(unsigned int page32)
{
if((page32%32)!=0)return 0; //page32[4:0] has to be 00000.
return _EraseBlock( blockLookupTable[PAGE2BLOCKID(page32)] );
}
int Nf_ReadPage(unsigned int startPage, unsigned int pageCount, U8 *buffer)
{
int i;
int page=startPage;
U8 *pPage=buffer;
for(i=0;i<pageCount;i++)
{
_RdPage(blockLookupTable[PAGE2BLOCKID(page)],(page&0x1f),pPage);
pPage+=528;
page++;
}
return 1;
}
int Nf_WritePage(unsigned int startPage, unsigned int pageCount, U8 *buffer)
{
int i;
int page=startPage;
U8 *pPage=buffer;
for(i=0;i<pageCount;i++)
{
if(!_WrPage(blockLookupTable[PAGE2BLOCKID(page)],(page&0x1f),pPage))
return 0;
pPage+=528;
page++;
}
return 1;
}
int Nf_Add1Block(void)
{
if(_RepAdd1Block(0)==0)return 0;
return Nf_Open();
}
int Nf_Replace1Block(int page32)
{
if(_RepAdd1Block(PAGE2BLOCKID(page32))==0)return 0;
return Nf_Open();
}
int _RepAdd1Block(int badBlockId)
//if badBlockId==0, replacement doesn't occur.
//blockId is blockLookupTable entry. 0=BIT table, 1=page0-31, 2=page32-63
{
int i;
int error=0,retry=0;
U8 buffer[528];
U8 reserved[528];
unsigned int phyBadBlock=0,phyNewBlock,newBlockId;
U8 *phyStTbl=(U8 *)blockLookupTable;
if(isOpen==0)return 0;
if(badBlockId!=0) //must remove the bad block.
{
newBlockId=badBlockId;
phyBadBlock=blockLookupTable[badBlockId];
_RdPage(0,0,reserved);
_RdPage(0,1,phyStTbl+0x0);
_RdPage(0,2,phyStTbl+0x200);
_RdPage(0,3,phyStTbl+0x400);
_RdPage(0,4,phyStTbl+0x600);
*((U16 *)phyStTbl+phyBadBlock)=0xf0f0; //mark bad block
}
else
{
newBlockId=(lastPage+1)/32;
_RdPage(0,0,reserved);
_RdPage(0,1,phyStTbl+0x0);
_RdPage(0,2,phyStTbl+0x200);
_RdPage(0,3,phyStTbl+0x400);
_RdPage(0,4,phyStTbl+0x600);
}
for(i=1;i<1024;i++)
{
if(*((U16 *)phyStTbl+i)==0xffff)break;
}
if(i==1024)return 0; //no more available empty good block.
phyNewBlock=i;
*((U8 *)((U16 *)phyStTbl+phyNewBlock))=0xff & newBlockId; //replace mark bad block
*((U8 *)((U16 *)phyStTbl+phyNewBlock)+1)=0xff & (newBlockId>>8);
Uart_Printf("Bad Block ID:%d(phy. %d) ->New block ID:%d(phy. %d)\n"
,badBlockId,phyBadBlock,newBlockId,phyNewBlock);
while(1)
{
_EraseBlock(0); //erase physical block #0
//buffer[528] has the ROM writer maker's information.
if(!_WrPage(0,0,reserved))error++;
for(i=0;i<528;i++)buffer[i]=0;
memcpy(buffer,phyStTbl+0x0,512);
if(!_WrPage(0,1,buffer))error++;
memcpy(buffer,phyStTbl+0x200,512);
if(!_WrPage(0,2,buffer))error++;
memcpy(buffer,phyStTbl+0x400,512);
if(!_WrPage(0,3,buffer))error++;
memcpy(buffer,phyStTbl+0x600,512);
if(!_WrPage(0,4,buffer))error++;
if(error==0)break;
error=0;
if(++retry==3)return 0; //retry error!!! unusable NAND flash
}
return 1;
}
int _EraseBlock(unsigned int block)
{
unsigned int blockPage=(block<<5);
int i;
FC_CMD;
rKM29UXDATA=0x60;
FC_ADDR;
rKM29UXDATA=blockPage&0xff;
rKM29UXDATA=(blockPage>>8)&0xff;
for(i=0;i<2;i++);//tWC 50ns
FC_CMD;
rKM29UXDATA=0xd0;
for(i=0;i<3;i++);
FC_DATA;
WAITRB; //wait max 3ms
FC_CMD;
rKM29UXDATA=0x70;
FC_DATA;
if (rKM29UXDATA&0x1) //erase error
{
FC_INACTIVE;
Uart_Printf("[ERASE_ERROR:PB=%d]",block);
return 0;
}
else
{
FC_INACTIVE;
return 1;
}
}
int _VerifyPage(U32 block,U32 page,U8 *buffer)
{
U8 buf[528];
_RdPage(block,page,buf);
if(strncmp((char *)buf,(char *)buffer,528)==0)return 1;
else return 0;
}
int _WrPage(unsigned int block,unsigned int page,U8 *pPage)
{
unsigned int blockPage=(block<<5)+page;
int i;
FC_CMD;
rKM29UXDATA=0x80;
FC_ADDR;
rKM29UXDATA=0;
rKM29UXDATA=blockPage&0xff;
rKM29UXDATA=(blockPage>>8)&0xff;
FC_DATA;
//for(i=0;i<528;i++){rKM29UXDATA=*pPage++;}
__WrPage528(pPage);
FC_CMD;
rKM29UXDATA=0x10;
for(i=0;i<10;i++); //twb=100ns. why is it 10? spec is false?
//No. It's because of LED of PE1.
WAITRB; //wait max 500us;
rKM29UXDATA=0x70;
FC_DATA;
for(i=0;i<3;i++); //twhr=60ns
if((rKM29UXDATA&0x1))
{
FC_INACTIVE;
rSYSCFG=SYSCFG_8KB;
Uart_Printf("[WRITE_ERROR:PB=%d]",block);
return 0;
}
else
{
FC_INACTIVE;
rSYSCFG=SYSCFG_8KB;
#if (WRITEVERIFY==1)
return _VerifyPage(block,page,pPage);
#else
return 1;
#endif
}
}
void _RdPage(unsigned int block,unsigned int page,U8 *pPage)
{
int i;
unsigned int blockPage=(block<<5)+page;
FC_CMD;
rKM29UXDATA=0x00;
FC_ADDR;
rKM29UXDATA=0;
rKM29UXDATA=blockPage&0xff;
rKM29UXDATA=(blockPage>>8)&0xff;
for(i=0;i<3;i++);
FC_DATA;
WAITRB; //wait max. 10us
//for(i=0;i<528;i++){*pPage++=rKM29UXDATA;}
__RdPage528(pPage);
FC_INACTIVE;
}
int _CheckId(void)
{
int i;
int id;
FC_CMD;
rKM29UXDATA=0x90;
FC_ADDR;
rKM29UXDATA=0;
FC_DATA;
for(i=0;i<5;i++); //wait 100ns
id=rKM29UXDATA<<8;
id+=rKM29UXDATA;
FC_INACTIVE;
return id;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -