表3 冗余字节定义
字节序号 | 内容 | 字节序号
| 内容
| 512 | 用户定义数据 | 520 | 后256BECC校验和 | 513 | 521 | 514 | 522 | 515 | 523 | 块逻辑地址 | 516 | 数据状态 | 524 | 517 | 块状态 | 525 | 前256BECC校验和 | 518 | 块逻辑地址1 | 526 | 519 | 527 |
表4给出了块逻辑地址的存放格式,LA表示逻辑地址,P代表偶校验位。逻辑地址只有10bit,代表只有1024bit的寻址空间。而SSFDC规范将NAND设备分成了多个zone,每个zone 内有1024块,但这物理上的1024块映射到逻辑空间只有1000块,其他的24块就作为备份使用,当有坏块存在时,就可以以备份块将其替换。
表4
逻辑地址格式 D7
| D6
| D5
| D4
| D3
| D2
| D1
| D0
|
| 0
| 0
| 0
| 1
| 0
| LA9
| LA8
| LA7
| 第518
523字节
| LA6
| LA5
| LA4
| LA3
| LA2
| LA1
| LA0
| P
| 第519
524字节
|
有了以上的软件规范,就可以对NAND设备写出较标准的ECC校验,并可以编写检测坏块、标记坏块、建立物理地址和逻辑地址的映射表的程序了。
static int NF_IsBadBlock(U32 block)
//检测坏块
{
int i;
unsigned int blockPage;
U8 data;
blockPage=(block<<5);
// For 2'nd cycle I/O[7:5]
NF_nFCE_L();
NF_CMD(0x50);
// Spare array read command
[url=]NF_ADDR(517&0xf);
// Read the mark of bad block in spare array(M addr="5") [/url][q6]
NF_ADDR(blockPage&0xff);
// The mark of bad block is in 0 page
NF_ADDR((blockPage>>8)&0xff);
// For block number A[24:17]
NF_ADDR((blockPage>>16)&0xff);
// For block number A[25]
for(i=0;i<10;i++);
// wait tWB(100ns) //?????
NF_WAITRB();
// Wait tR(max 12us)
data=NF_RDDATA();
NF_nFCE_H();
if(data!=0xff)
{
Uart_Printf("[block %d has been marked as a bad block(%x)]\n",block,data);
return 1;
}
else
{
return 0;
}
}
static int NF_MarkBadBlock(U32 block)
//标记坏块
{
int i;
U32 blockPage=(block<<5);
seBuf[0]=0xff;
seBuf[1]=0xff;
seBuf[2]=0xff;
[url=]
seBuf[5]=0x44;
// Bad blcok mark="0"[/url][q7]
NF_nFCE_L();
NF_CMD(0x50);
//????
NF_CMD(0x80);
// Write 1st command
NF_ADDR(0x0);
// The mark of bad block is
NF_ADDR(blockPage&0xff);
// marked 5th spare array
NF_ADDR((blockPage>>8)&0xff);
// in the 1st page.
NF_ADDR((blockPage>>16)&0xff);
for(i=0;i<16;i++)
{
NF_WRDATA(seBuf);
// Write spare array
}
NF_CMD(0x10);
// Write 2nd command
for(i=0;i<10;i++);
//tWB = 100ns. ///???????
NF_WAITRB();
// Wait tPROG(200~500us)
NF_CMD(0x70);
for(i=0;i<3;i++);
//twhr=60ns////??????
if (NF_RDDATA()&0x1)
// Spare arrray write error
{
NF_nFCE_H();
Uart_Printf("[Program error is occurred but ignored]\n");
}
else
{
NF_nFCE_H();
}
Uart_Printf("[block #%d is marked as a bad block]\n",block);
return 1;
} |