📄 nandflash.c
字号:
#include "def.h"
#include "2410addr.h"
#include "2410lib.h"
#define EnNandFlash() (rNFCONF |= 0x8000) //bit15=1 enable NAND flash controller
#define DsNandFlash() (rNFCONF &= ~0x8000) //bit15=1 disable NAND flash controller
#define InitEcc() (rNFCONF |= 0x1000) //bit12=1 initialize ECC
#define NoEcc() (rNFCONF &= ~0x1000) //bit12=0 initialize ECC
#define NFChipEn() (rNFCONF &= ~0x800) //bit11=0 NAND flash nFCE = L (active)
#define NFChipDs() (rNFCONF |= 0x800) //bit11=1 NAND flash nFCE = H (inactive)
#define WrNFCmd(cmd) (rNFCMD = (cmd)) //write commond to nand flash
#define WrNFAddr(addr) (rNFADDR = (addr)) //write address to nand flash
#define WrNFDat(dat) (rNFDATA = (dat)) //write data to nand flash
#define RdNFDat() (rNFDATA) //read data from nand flash
#define RdNFStat() (rNFSTAT) //read status from nand flash
#define NFIsBusy() (!(rNFSTAT&1))//whether nand flash is busy?
#define NFIsReady() (rNFSTAT&1) //whether nand flash is ready?
#define READCMD0 0
#define READCMD1 1
#define READCMD2 0x50
#define ERASECMD0 0x60
#define ERASECMD1 0xd0
#define PROGCMD0 0x80
#define PROGCMD1 0x10
#define QUERYCMD 0x70
#define RdIDCMD 0x90
static U16 NandAddr;
/**** 初始化 K9F1208U0M nand flash ****/
static void InitNandCfg(void)
{
//enable nand flash control, initilize ecc, chip disable,
rNFCONF = (1<<15)|(1<<12)|(1<<11)|(7<<8)|(7<<4)|(7);
}
#ifdef WIAT_BUSY_HARD
#define WaitNFBusy() while(NFIsBusy())
#else
static U32 WaitNFBusy(void) // R/B 未接好?
{
U8 stat;
WrNFCmd(QUERYCMD);
do {
stat = RdNFDat();
//printf("%x\n", stat);
}while(!(stat&0x40));
WrNFCmd(READCMD0);
return stat&1;
}
#endif
/**** K9F1208U0M nand flash 的ID ****/
static U32 ReadChipId(void)
{
U32 id;
NFChipEn();
WrNFCmd(RdIDCMD);
WrNFAddr(0);
while(NFIsBusy());
id = RdNFDat()<<8;
id |= RdNFDat();
NFChipDs();
return id;
}
/**** K9F1208U0M nand flash 的状态 ****/
static U16 ReadStatus(void)
{
U16 stat;
NFChipEn();
WrNFCmd(QUERYCMD);
stat = RdNFDat();
NFChipDs();
return stat;
}
/**** K9F1208U0M nand flash 的块擦除操作 ****/
static U32 EraseBlock(U32 addr)
{
U8 stat;
addr &= ~0x1f;
NFChipEn();
WrNFCmd(ERASECMD0);
WrNFAddr(addr);
WrNFAddr(addr>>8);
if(NandAddr)
WrNFAddr(addr>>16);
WrNFCmd(ERASECMD1);
stat = WaitNFBusy();
NFChipDs();
#ifdef ER_BAD_BLK_TEST
if(!((addr+0xe0)&0xff)) stat = 1; //just for test bad block
#endif
printf("Erase block 0x%x %s\n", addr, stat?"fail":"ok");
return stat;
}
/**** K9F1208U0M nand flash 的页数据读 ****/
static void ReadPage(U32 addr, U8 *buf)//addr = page address
{
U16 i;
NFChipEn();
WrNFCmd(READCMD0);
WrNFAddr(0);
WrNFAddr(addr);
WrNFAddr(addr>>8);
if(NandAddr)
WrNFAddr(addr>>16);
InitEcc();
WaitNFBusy();
for(i=0; i<512; i++)
buf[i] = RdNFDat();
NFChipDs();
}
/**** K9F1208U0M nand flash 的页数据读 ****/
static U32 WritePage(U32 addr, U8 *buf)
{
U16 i;
U8 stat, tmp[3];
NFChipEn();
WrNFCmd(PROGCMD0);
WrNFAddr(0);
WrNFAddr(addr);
WrNFAddr(addr>>8);
if(NandAddr)
WrNFAddr(addr>>16);
InitEcc();
for(i=0; i<512; i++)
WrNFDat(buf[i]);
tmp[0] = rNFECC0;
tmp[1] = rNFECC1;
tmp[2] = rNFECC2;
WrNFDat(tmp[0]);
WrNFDat(tmp[1]);
WrNFDat(tmp[2]);
WrNFCmd(PROGCMD1);
stat = WaitNFBusy();
NFChipDs();
#ifdef WR_BAD_BLK_TEST
if((addr&0xff)==0x17) stat = 1; //just for test bad block
#endif
if(stat)
printf("Write nand flash 0x%x fail\n", addr);
else {
U8 RdDat[512];
ReadPage(addr, RdDat);
for(i=0; i<512; i++)
if(RdDat[i]!=buf[i]) {
printf("Check data at page 0x%x, offset 0x%x fail\n", addr, i);
stat = 1;
break;
}
}
return stat;
}
/**** 屏蔽 K9F1208U0M nand flash 的坏块 ****/
static void MarkBadBlk(U32 addr)
{
addr &= ~0x1f;
NFChipEn();
WrNFCmd(READCMD2); //point to area c
WrNFCmd(PROGCMD0);
WrNFAddr(4); //mark offset 4,5,6,7
WrNFAddr(addr);
WrNFAddr(addr>>8);
if(NandAddr)
WrNFAddr(addr>>16);
WrNFDat(0); //mark with 0
WrNFDat(0);
WrNFDat(0); //mark with 0
WrNFDat(0);
WrNFCmd(PROGCMD1);
WaitNFBusy(); //needn't check return status
WrNFCmd(READCMD0); //point to area a
NFChipDs();
}
/**** 检查 K9F1208U0M nand flash 的坏块 ****/
static int CheckBadBlk(U32 addr)
{
U8 dat;
addr &= ~0x1f;
NFChipEn();
WrNFCmd(READCMD2); //point to area c
WrNFAddr(5); //mark offset 4,5,6,7
WrNFAddr(addr);
WrNFAddr(addr>>8);
if(NandAddr)
WrNFAddr(addr>>16);
WaitNFBusy();
dat = RdNFDat();
WrNFCmd(READCMD0); //point to area a
NFChipDs();
return (dat!=0xff);
}
static U32 StartPage, BlockCnt;
/************************************************************/
struct Partition{
U32 offset;
U32 size;
char *name;
};
static struct Partition NandPart[] = {
{0, 0x00030000, "boot"}, //256K
{0x00030000, 0x001d0000, "kernel"},
{0x00200000, 0x00600000, "rootfs"}, //6M
{0x00800000, 0x00800000, "ext-fs1"}, //8M
{0x01000000, 0x01000000, "ext-fs2"}, //16M
{0x02000000, 0x02000000, "ext-fs3"}, //32M
{0, 0 , 0}
};
/**** K9F1208U0M nand flash 的分区 ****/
static int NandSelPart(char *info)
{
U16 i, max_sel;
struct Partition *ptr = NandPart;
printf("Please select which region to %s : Esc to abort\n", info);
for(i=0; ptr->size!=0; i++, ptr++)
printf("%d : offset 0x%-8x, size 0x%-8x [%s]\n", i, ptr->offset, ptr->size, ptr->name);
max_sel = i;
while(1) {
i = getch();
if(i==0x1b)
return -1;
if((i>='0')&&(i<(max_sel+'0'))) {
i -= '0';
StartPage = NandPart[i].offset>>9;
BlockCnt = NandPart[i].size>>14;
return i;
}
}
}
/**** K9F1208U0M nand flash 的初始化 ****/
static int support=0;
static void InitNandFlash(void)
{
U32 i;
InitNandCfg();
i = ReadChipId();
printf("Read chip id = %x\n", i);
if((i==0x9873)||(i==0xec75))
NandAddr = 0;
else if(i==0xec76)
{
support=1; //by chang
NandAddr = 1;
}
else {
puts("Chip id error!!!\n");
return;
}
printf("Nand flash status = %x\n", ReadStatus());
}
/**** K9F1208U0M nand flash 的整片擦除 ****/
void NandErase(void)
{
int i, err = 0;
InitNandFlash();
i = NandSelPart("erase");
if(i<0)
return;
printf("Are you sure to erase nand flash from page 0x%x, block count 0x%x ? [y/n]\n", StartPage, BlockCnt);
while(1) {
char c;
c = getch();
if((c=='y')||(c=='Y'))
break;
if((c=='n')||(c=='N'))
return;
}
for(i=0; BlockCnt; BlockCnt--, i+=32) {
if(EraseBlock(i+StartPage)) {
err ++;
puts("Press any key to continue...\n");
getch();
}
}
DsNandFlash(); //disable nand flash interface
puts("Erase Nand partition completed ");
if(err)
printf("with %d bad block(s)\n", err);
else
puts("success\n");
}
/**** K9F1208U0M nand flash 的整片写 ****/
void NandWrite(void)
{
InitNandFlash();
//WrFileToNF();
DsNandFlash(); //disable nand flash interface
}
void memcpy(void *s1, const void *s2, int n)
{
int i;
for (i = 0; i < n; i++)
((char *)(s1))[i] = ((const char *)(s2))[i];
}
int strncmp(const char *s1, const char *s2, int maxlen)
{
int i;
for(i = 0; i < maxlen; i++) {
if(s1[i] != s2[i])
return ((int) s1[i]) - ((int) s2[i]);
if(s1[i] == 0)
return 0;
}
return 0;
}
/*** nand flash 测试程序***/
void Main(void)
{
U32 i;
U8 buf[512];
U32 id;
id=ReadChipId();
Uart_Printf("nand flash`s ID is:%x,ID\n");
if(EraseBlock(0x180))
for(i=0; i<512; i++)
buf[i] = i;
WritePage(0x180, buf);
for(i=0; i<512; i++)
buf[i] = 0;
ReadPage(0x180, buf);
for(i=0; i<512; i++)
printf("%4x", buf[i]);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -