📄 nandflash.c
字号:
/*************************************************************************/
/* */
/* FILE NAME VERSION */
/* */
/* source\flash.c 1.0 */
/* */
/* DESCRIPTION : 2440 MPU Nand Flash */
/* */
/* */
/* DATA STRUCTURES */
/* */
/* FUNCTIONS : s3c2440 Nand Flash Program Code */
/* */
/* CPU DEPENDENCES */
/* */
/* Made by Song Seun Keun */
/* */
/* Copyrigth (C) 2001 AIJISYSTEM CO.,LTD */
/*************************************************************************/
#include <stdio.h>
#include <string.h>
#include "common.h"
#define SAMSUNG
//#define TOSHIBA
#define CACHE
#define PAGE_CNT 32
#define PAGE_SIZE 512
#define BLOCK_COUNT 8192 //4096
#define BLOCK_SIZE 0x4000
/* Hardware dependent functions */
#ifdef SAMSUNG
#define NF_RDDATA() (rNFDATA)
#define NF_nFCE_L() {rNFCONT&=~(1<<1);}
#define NF_nFCE_H() {rNFCONT|=(1<<1);}
#define NF_WRDATA(data) {rNFDATA=data;}
#define NF_CMD(cmd) {rNFCMD=cmd;}
#define NF_ADDR(addr) {rNFADDR=addr;}
#define NF_CLEAR_RB() {rNFSTAT |= (1<<2);}
#define NF_DETECT_RB() {while(!(rNFSTAT&(1<<2)));}
#endif
// Host program苞 data & command甫 林绊罐扁 困茄 structure
extern FLASH_INFO Flash_Info;
uchar TempBuf[BLOCK_SIZE];
uchar FillBuf[PAGE_SIZE];
ulong Current_Block_No = 0;
ulong Current_Page_No = 0;
ulong image_size = 0;
ulong debugadd = 0;
volatile int READMEM = 1000;
int WRITE = 1;
void Main(void)
{
switch(Flash_Info.Command)
{
case FPROGRAM: Program();
break;
case FERASEALL:
Flash_Info.Result = 1;
//EraseAll();
break;
case FERASESEC:
Flash_Info.Result = 1;
//EraseSector();
break;
case FREADID: ReadChipID();
break;
case FREADMEM: ReadMem();
break;
case FWRITE_BIB:
break;
case FINIT: InitFlash();
break;
default :
Flash_Info.Result = 0;
}
}
// Flash program function
void Program(void)
{
ulong len, flen, i, wSize;
volatile ulong status;
uchar *srcP, *bsrcP;
Flash_Info.Result = 0;
srcP = (uchar *)Flash_Info.Buf;
len = Flash_Info.Length;
/* Calculate the Block Address */
if(WRITE)
{
ulong sBlock;
debugadd = Flash_Info.TargetAddr;
sBlock = Flash_Info.TargetAddr >> 14;
Current_Block_No = sBlock;
Current_Page_No = Current_Block_No*PAGE_CNT;
WRITE-=WRITE;
}
while(len && (Current_Block_No < BLOCK_COUNT))
{
if(!(Current_Page_No%PAGE_CNT)) {
if(Flash_Info.BadBlockTable[Current_Block_No]){
Current_Block_No++;
Current_Page_No = Current_Block_No*PAGE_CNT;
}
if(Current_Block_No >= BLOCK_COUNT)
return;
if(!PrepareBlock())
return;
}
if(len > PAGE_SIZE)
flen = PAGE_SIZE;
else {
flen = len;
bsrcP = srcP+len;
for(i=len; i<PAGE_SIZE;i++)
*bsrcP++ = 0xff;
}
status = WriteChar(srcP, Current_Page_No);
for(i=0;i<30;i++);
if(!status) // error
return;
ReadChar(TempBuf, Current_Page_No, PAGE_SIZE);
if(!Verification((ulong *)TempBuf, PAGE_SIZE, (ulong *)srcP))
return;
Current_Page_No++;
wSize +=PAGE_SIZE;
image_size +=PAGE_SIZE;
len -= flen;
srcP += PAGE_SIZE;
}
// LastAddr = Flash_Info.TargetAddr+wSize;
Flash_Info.Result = 1;
}
// Chip erase function
void EraseAll(void)
{
int i;
Flash_Info.Result = 1; // 8Mbyte
for(i=0;i<100;i++) OneBlockErase(i);
}
// Sector erase function
void EraseSector(void)
{
Flash_Info.Result = 1;
}
// 窍唱狼 Sector 父 Erase
int OneBlockErase(ulong block)
{
int i, Delay=5000;
ulong nand_cntlr_block_addr;
nand_cntlr_block_addr = block<<5;
NF_nFCE_L();
NF_CLEAR_RB();
// Erase one block 1st command
rNFCMD = ERASE_CMD_FIRST;
// For block number A[17:0]
rNFADDR = (nand_cntlr_block_addr&0xff);
// For block number A[24:17]
rNFADDR = ((nand_cntlr_block_addr>>8)&0xff);
// For block number A[25]
rNFADDR = ((nand_cntlr_block_addr>>16)&0xff);
// Erase one block 2nd command
rNFCMD = ERASE_CMD_SECOND;
NF_DETECT_RB();
while(Delay--);
rNFCMD = READ_STATUS; // Read status command
for(i=0;i<10;i++);
if(NF_RDDATA()&0x1){
Flash_Info.BadBlockTable[Current_Block_No]=1;
NF_nFCE_H();
return 0;
}
else{
NF_nFCE_H();
return 1;
}
}
// Read Manufacturer & Device ID
void ReadChipID(void)
{
ulong manId,devId;
int i;
NF_nFCE_L();
rNFCMD = ID_CMD;
rNFADDR = 0x0;
for(i=0;i<10;i++); /* Wait for done */
NF_nFCE_H();
manId = NF_RDDATA();
devId = (manId >> 15) & 0xff;
manId = (manId >> 23) & 0xff;
Flash_Info.Result = (devId << 8) + manId;
}
ulong PrepareBlock(void)
{
if(Flash_Info.BadBlockTable[Current_Block_No])
return 0;
if(!OneBlockErase(Current_Block_No++))
return 0;
return 1;
}
int BlankCheck(ulong *targetP,ulong targetSize)
{
ulong i;
for(i=0; i<targetSize; i+=4)
if(*targetP++ != 0xffffffff)
return 0;
return 1;
}
int Verification(ulong *targetP, ulong limit, ulong *srcAddr)
{
ulong i;
for(i=0; i<limit; i+=4, targetP++, srcAddr++)
if(*targetP != *srcAddr) {
return 0;
}
return 1;
}
int ReadChar(uchar *data, ulong targetAddr, ulong size)
{
ulong i, j, len, flen;
len = size;
for(i=0;i<size;i+=PAGE_SIZE){
if(len > PAGE_SIZE)
flen = PAGE_SIZE;
else
flen = len;
NF_nFCE_L();
NF_CLEAR_RB()
rNFCMD = READ;
rNFADDR = 0;
/* For block number A[17:0] */
rNFADDR = (targetAddr&0xff);
/* For block number A[24:17] */
rNFADDR = ((targetAddr>>8)&0xff);
/* For block number A[25] */
rNFADDR = ((targetAddr>>16)&0xff);
for(j=0;j<10;j++);
NF_DETECT_RB();
//memcpy((void *)data, (void *)data_reg, flen);
for(j=0;j<512;j++) *data++ = NF_RDDATA();
len -= PAGE_SIZE;
if(Flash_Info.Command == FREADMEM) targetAddr ++;
}
return 1;
}
int WriteChar(uchar *data, ulong page_addr)
{
int i;
NF_nFCE_L();
NF_CLEAR_RB();
/* Write Reset */
rNFCMD = WRITE_RESET;
/* Write Command */
rNFCMD = PROGRAM_FIRST;
rNFADDR = 0x0;
/* For block number A[17:0] */
rNFADDR = (page_addr&0xff);
/* For block number A[24:17] */
rNFADDR = ((page_addr>>8)&0xff);
/* For block number A[25] */
rNFADDR = ((page_addr>>16)&0xff);
//memcpy((void *)data_reg, (void *)data, PAGE_SIZE);
for(i=0;i<512;i++) NF_WRDATA(*data++);
//for(i=0;i<100;i++); // for the timing issue
/* Write second command */
rNFCMD = PROGRAM_SECOND;
for(i=0;i<100;i++); //for the timing issue
NF_DETECT_RB();
/* Read command */
rNFCMD = READ_STATUS;
for(i=0;i<30;i++); // for the timing issue
if(NF_RDDATA()&0x1){
Flash_Info.BadBlockTable[Current_Block_No]=1;
NF_nFCE_H();
return 0;
}
else{
NF_nFCE_H();
return 1;
}
}
void ReadMem(void)
{
ulong TargetAdd;
uchar *srcP;
srcP = (uchar *)Flash_Info.Buf;
TargetAdd = Flash_Info.TargetAddr;
/* Calculate the Block Address */
if(READMEM)
{
ulong sBlock;
sBlock = Flash_Info.TargetAddr >> 14;
Current_Block_No = sBlock;
Current_Page_No = Current_Block_No*PAGE_CNT;
READMEM-=READMEM;
}
FlashConfig ();
ReadChar(srcP, Current_Page_No, Flash_Info.Length);
Current_Page_No+=8;
Flash_Info.Result = 1;
}
void InitFlash(void)
{
int i;
ulong TargetAdd;
image_size = 0;
TargetAdd = Flash_Info.TargetAddr;
FlashConfig();
MMU_Init();
for(i=0;i<4096;i++) Flash_Info.BadBlockTable[i]=0;
for(i=1;i<4096;i++)
{
if(!Bad_Block_Check(i)) Flash_Info.BadBlockTable[i]=1;
}
Current_Block_No = 0;
Current_Page_No = 0;
/* Calculate the Block Address */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -