📄 nandflash.c
字号:
else {
//Uart_Printf("FMD_WriteSector::::::4 \r\n");
for(i=0;i<512;i++) {
NF_WRDATA8(*pSectorBuff++); // Write one page to NFM from buffer
}
//WritePage512(pSectorBuff,(PULONG)rNFDATA);
}
// Read out the ECC value generated by HW
NF_MECC_Lock();
dwECCVal = NF_ECC();///将NFMECC0/存器里产生的ECC数据放在SPARE AREA里去。
// Write the SectorInfo data to the media
// NOTE: This hardware is odd: only a byte can be written at a time and it must reside in the
// upper byte of a USHORT.
if(pSectorInfoBuff)
{
//Uart_Printf("FMD_WriteSector::::::5 \r\n");
// Write the first reserved field (DWORD)
NF_DATA_W4(pSectorInfoBuff->dwReserved1);
// Write OEM reserved flag
NF_DATA_W( (pSectorInfoBuff->bOEMReserved) );
// Write the bad block flag
NF_DATA_W( (pSectorInfoBuff->bBadBlock) );
// Write the second reserved field
NF_DATA_W( (pSectorInfoBuff->wReserved2 >> 8) & 0xff );
NF_DATA_W( (pSectorInfoBuff->wReserved2) & 0xff );
}else///如果不要INFOBUFF信息FOR CE里查询,则写sizeof(SectorInfo)个字节为0XFF。
{
// Make sure we advance the Flash's write pointer (even though we aren't writing the SectorInfo data)
for(i=0; i<sizeof(SectorInfo); i++)
{
NF_DATA_W(0xff);
}
}
//Uart_Printf("FMD_WriteSector::::::6 \r\n");
// ECC stuff should be here
eccBuf[0] = (BYTE) ((dwECCVal) & 0xff);
eccBuf[1] = (BYTE) ((dwECCVal >> 8) & 0xff);
eccBuf[2] = (BYTE) ((dwECCVal >> 16) & 0xff);
// Write the ECC value to the flash
for(i=0; i<3; i++) {//将ECC generator发生器产生的ECC 码写到SPARE 区域里去。
NF_DATA_W(eccBuf[i]);
}
for(i=0; i<5; i++) { /////??
NF_DATA_W(0xff);
}
NF_CLEAR_RB();
// Finish up the write operation
NF_CMD(CMD_WRITE2);
// Wait for RB
NF_DETECT_RB(); // Wait tR(max 12us)
// Check the status
NF_CMD(CMD_STATUS);
if(NF_DATA_R() & STATUS_ERROR) {
//#ifdef BOOT_LOADER
Uart_Printf("FMD_WriteSector() ######## Error Programming page %d!\r\n", startSectorAddr);
//#else
// RETAILMSG(1, (TEXT("FMD_WriteSector() ######## Error Programming page %d!\n"), startSectorAddr));
//#endif
bRet = FALSE;
}
// Disable the chip
NF_CE_H();
//RELEASEMUTEX();
return bRet;
}
#define TACLS 0
#define TWRPH0 6
#define TWRPH1 2
static U16 NF8_CheckId(void)
{
int i;
U16 id, id4th;
NF_nFCE_L();
NF_CMD(0x90);
NF_ADDR(0x0);
for (i=0; i<10; i++);
//Uart_Printf("NFSTAT: 0x%x\n", rNFSTAT);
id=NF_RDDATA8()<<8; // Maker code 0xec
id|=NF_RDDATA8(); // Devide code(K9S1208V:0x76), (K9K2G16U0M:0xca)
NF_nFCE_H();
return id;
}
//***********************************************************************
void NF_ReadID(void)
{
U16 id;
U8 maker, device;
// NF8_Init();
id = NF8_CheckId();
device = (U8)id;
maker = (U8)(id>>8);
if(device!=0x76)
Uart_Printf("Read Nand Flash ID FAIL!!!\n");
Uart_Printf("Nand Flash ID(0xec76):0x%x%x\n", maker, device);
//v1.2
/* Uart_SendString("Nand Mfg: ");
Uart_SendDWORD((DWORD)wData1, TRUE);
Uart_SendString("Nand Dev: ");
Uart_SendDWORD((DWORD)wData2, TRUE);
*/
}
//************************************************************************
PVOID FMD_Init(void)
{
// RETAILMSG(1, (TEXT("FMD::FMD_Init\r\n")));
// 0. Create the Mutex for shared access between the kernel and MSFLASH
//rNFReg = (PUSHORT) (0x4E000000);///
//v_s2440CLKPWR = (CLKPWRreg *) ( CLKPWR_BASE | 0x20000000 );
// Enable the clock to NAND controller
rCLKCON |= (1<<4);
//Uart_Printf("FlashDrv!FMD!FMD_Init: rNFReg = %x \r\n", (USHORT)rNFCONF);
/*rNFCONF = rNFReg;
rNFCONT = (PUSHORT) ((PBYTE) rNFReg + 0x04);
rNFCMD = (PUSHORT) ((PBYTE) rNFReg + 0x08);
rNFADDR = (PUSHORT) ((PBYTE) rNFReg + 0x0C);
rNFDATA = (PULONG) ((PBYTE) rNFReg + 0x10);
rNFSTAT = (PUSHORT) ((PBYTE) rNFReg + 0x20);
rNFECC = (PULONG) ((PBYTE) rNFReg + 0x2C);*/
// Now we need enable the NAND Flash controller
//GRABMUTEX();
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(1<<1)|(1<<0);
rNFSTAT = 0;
/* WRITE_REGISTER_USHORT(rNFCONF, (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0));
WRITE_REGISTER_USHORT(rNFCONT, (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(0<<6)|(0<<5)|(1<<4)|(1<<1)|(1<<0));
WRITE_REGISTER_USHORT(rNFSTAT, 0);*/
//RELEASEMUTEX();
// NF_Reset();
//RETAILMSG(1, (TEXT("FMD::FMD_Init Done\r\n")));
NF_ReadID();
return (PVOID)rNFCONF;
ErrExit:
//FMD_Deinit((PVOID)rNFCONF);
return 0;
}
//***********************************************************************
void K9S1208_Program(U32 DownBlock)
{
// unsigned long interrupt_reservoir;
int i;
int programError=0;
U8 *srcPt,*saveSrcPt;
U32 blockIndex,blockLimit;
SectorInfo si;
FMD_Init();
//downloadAddress=0x30100000;
// downloadAddress=0x30200000;
Uart_Printf("\n[ NAND Flash writing program]\n");
// NF_Init();
NF_Reset();
// rINTMSK = BIT_ALLMSK;
targetSize=downloadFileSize;
//Uart_Printf("target Size=0x%x\n",targetSize);
//if(targetSize==0)
//{
srcAddress=0x30100000;
// srcAddress=0x30200000;
//Uart_Printf("the data must be downloaded using ICE from %xh\n",srcAddress);
//}
// else
//srcAddress=downloadAddress+4; //to discard the data head for the size
//InputTargetBlock();
targetBlock=DownBlock;
targetSize=downloadFileSize;
Uart_Printf("\nsource base address(0x3010000x)=0x%x\n",srcAddress);
Uart_Printf("target start block number =%d\n",targetBlock);
Uart_Printf("target size (0x4000*n) =0x%x\n",targetSize);
srcPt=(U8 *)srcAddress;
blockIndex=targetBlock;
si.bOEMReserved = 0xff;//OEM_BLOCK_RESERVED | OEM_BLOCK_READONLY;
si.bBadBlock = 0xff;//BADBLOCKMARK;
si.dwReserved1 = 0xffff;//0;
si.wReserved2 = 0xff;//0;
//Uart_Printf("----------1 \r\n");
blockLimit = targetSize / (16*1024);
// Uart_Printf("\nblockLimit:%d\n",blockLimit);
while(1)
{
saveSrcPt=srcPt;
#if BAD_CHECK
if(IsBlockBad(blockIndex)) // 1:bad 0:good
{
blockIndex++; // for next block
//Uart_Printf("----------2 \r\n");
continue;
}
#endif
if(!FMD_EraseBlock(blockIndex))
{
//Uart_Printf("----------4 \r\n");
blockIndex++; // for next block//不能加一,因为如果是0块,如果他都不能用,
Uart_Printf("\nFMD_EraseBlock continue\n");
continue;
}
for(i=(blockIndex<<5);i<(blockIndex<<5)+32;i++)
{
if (!FMD_WriteSector(i, srcPt,&si, 1))
// if(!NF_WritePage(blockIndex,i,srcPt))// block num, page num, buffer
{
Uart_Printf("NBOOT_Write ERROR: Unable to save NBOOT Flag \r\n");
programError=1;
break;
}
//#if ECC_CHECK
if(!NF_ReadPage(blockIndex,i,srcPt))
{
Uart_Printf("ECC Error(block=%d,page=%d!!!\n",blockIndex,i);
}
//#endif
srcPt+=512; // Increase buffer addr one pase size
if((U32)srcPt>=(srcAddress+targetSize)) // Check end of buffer
break; // Exit for loop
}
Uart_Printf(".");
if(programError==1)
{
blockIndex++;
srcPt=saveSrcPt;
programError=0;
continue;
}
if((U32)srcPt>=(srcAddress+targetSize))
break; // Exit while loop
blockIndex++;
}
//Uart_Printf("----------6 \r\n");
Uart_Printf("\nDownload Success!!!\r\n");
}
//*************************************************************
//*************************************************************
//*************************************************************
BOOL MarkBlockBad(BLOCK_ID blockID)
{
DWORD dwStartPage = blockID << 5;
BOOL bRet = TRUE;
int i;
Uart_Printf("MarkBlockBad::::Block Num = %d !!!\r\n",blockID);
// Enable chip
NF_CE_L();
NF_CLEAR_RB();
// Issue command
// We are dealing with spare area
NF_CMD(CMD_READ2);
NF_CMD(CMD_WRITE);
// Set up address
NF_ADDR(VALIDADDR);
NF_ADDR((dwStartPage) & 0xff);
NF_ADDR((dwStartPage >> 8) & 0xff);
if (NEED_EXT_ADDR) {
NF_ADDR((dwStartPage >> 16) & 0xff);
}
NF_DATA_W(BADBLOCKMARK);
// Copmlete the write
NF_CMD(CMD_WRITE2);
for(i=0;i<10;i++); //延时
// Wait for RB
NF_DETECT_RB(); // Wait tR(max 12us)
// Get the status
NF_CMD(CMD_STATUS);
for(i=0;i<3;i++);///延时
if(NF_DATA_R() & STATUS_ERROR) {
Uart_Printf("######## Failed to mark the block bad!\n");
bRet = FALSE;
}
// Disable chip select
NF_CE_H();
return bRet;
}
//************************************************************************
BOOL FMD_SetBlockStatus(BLOCK_ID blockID, DWORD dwStatus)
{
SECTOR_ADDR sectorAddr = blockID << 5;
BYTE bStatus = 0;
if(!MarkBlockBad (blockID))
{
Uart_Printf("FMD::MarkBlockBad--Failed\r\n");
return FALSE;
}
// RETAILMSG(1, (TEXT("MarkBlockBad-Success\r\n")));
// We don't currently support setting a block to read-only, so fail if request is
// for read-only and block is not currently read-only.
return TRUE;
}
//*************************************************************************
void EraseFlash()
{
U8 key;
int i;
Uart_Printf("Are You Sure Erase Blocks ? [Y/N]\n");
key=Uart_Getch();
if (( key=='y') || ( key=='Y'))
{
Uart_Printf("Start Erase Blocks.... please waite....\n");
for (i=0;i < NUM_BLOCKS;i++)
{
if (!(FMD_EraseBlock(i))) //擦除整个芯片
FMD_SetBlockStatus(i, BLOCK_STATUS_BAD);
}
Uart_Printf("Over Erase Blocks\n");
}
else Uart_Printf("No Block Erase!\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -