又是一个让人费解的问题,今天我那尝试把这个问题说清楚。关于nand flash的列地址A11。
先给出一个地址的公式: nand地址=块大小×块号+页大小×页号+页内地址
按手册上描述的The K9F2G08X0A is a 2,112Mbit(2,214,592,512 bit) memory organized as 131,072 rows(pages) by 2,112x8 columns.
公式就可以写成: nand地址=(rows:A28-A12)(columns:A11-A0).比如第0x12345页的0x677偏移处的地址就是0x12345667。
既然一个页大小为2K那么columns应该A0-A10就够,但是怎么会多出来一个A11?看手册上是这么写的:
Spare 64x8 columns are located from column address of 2,048~2,111
也就是说每个页还要一块spare area,64字节大小,存放ECC校验信息,而要寻址那64字节就需要用到A11位,这就是A11存在的意义
如果是spare area地址则A11=1,否则A11=0。
手册上有这样一个表:
1stCycle A0 A1 A2 A3 A4 A5 A6 A7 Column Address
2ndCycle A8 A9 A10 A11 *L *L *L *L Column Address
3rdCycle A12 A13 A14 A15 A16 A17 A18 A19 Row Address
4thCycle A20 A21 A22 A23 A24 A25 A26 A27 Row Address
5thCycle A28 *L *L *L *L *L *L *L Row Address
可是我们写程序发送地址的时候是这样写的:
..........
unsigned int col_add = addr & 0x7ff;
unsigned int raw_add = (addr >> 11)&0x1ffff;
NFADDR = col_add & 0xff;
NFADDR = (col_add >> 8) & 0x7; //a11为0
NFADDR = raw_add & 0xff;
NFADDR = (raw_add >> 8) & 0xff;
NFADDR = (raw_add >> 16) & 0x1;
.....
..
.
在这里有些人感觉很奇怪,表格里rows明明是从A12开始的可是程序里raw_add= (addr >> 11)&0x1ffff,只向由移11位,不是应该addr >> 12吗?
最关键的地方到了,你别忘了,我们在存放数据的时候,数据里面不包括ECC信息,也就是说在我们自己看来nandflash页大小就是2K。比如说我往nand的0x0地址存了0x800(2KB)大小数据,接下来,如果我们再存数据就继续从0x800的地址开始存,在这里你跳过前一页的ECC部分了吗?很明显没有,理论上前一页占了0x1000(4KB)大小,我们应该从0x1000开始存接下的数据,可是,我们实际上不会这么干,我们忽略ECC占的空间,我们认为一页大小就是2KB。
所以在我们看来nandflash地址就是这样的:
nand地址=(rows:A27-A11)(columns:A10-A0)
接受到地址后,在发送地址时,我们是这么干的,把A0-A10取出来,再添上一位A11=0,,然后把A11-A27取出来,对应A12-A28发过去,这样就实现了在发送地址时跳过每一页的ECC部分,但在用户看来每一页大小还是2KB,这里有些绕,但是好好想一想还是能想清楚的。
有些人说A0-A11这是手册写错了,我不这么认为,手册是对的,nandflash内部的实际地址就如手册上写的那样,只是在我们看来是A0-A10。
by xiezhendong
阅读(4351) | 评论(0) | 转发(0) |