vivi中对nandflash的操作还是比较多的,比如vivi启动时,首先要将自身的代码从nandflash里复制到sdram里,这一步就需要对nandflash的读取。此时可以通过nandflash控制器来操作,所以实现起来会简单一些。
到了vivi后面的阶段会引入mtd,用以增强对nandflash的操作(读、写、ecc较验等)。mtd封闭了一些对nandflash操作的细节,对上层操作提供统一的接口,如读、写等等。
最后,vivi引导内核时还需要正确的分区,比如bon分区和mtd分区,如果分区上出了一点错误,最终将导致内核不能正常的引导启动。而这些都与nandflash是密切相关的。可见nandflash的重要性。
单独拿nandflash出来讲,还是有点偏大。于是我决定从几个层次来认识与nandflash有关的操作。
这里我的芯片是三星的K9F1208,很通用的一款芯。
容量为:64M(67,108,864)x8bit。nandflash)(注意宽度为8位)
另外还有 2,048K(2,097,152)x8bit 即2M的额外空间。这个在下面会分析到。
大体上了解了这么多的参数就够了。
先来画一个nandflash的草图吧。下面是nandflash的一个block。
--> obb(out of bank)
/
|
|----> 256B <-----|-----> 256B <----|-> 16B <-|
+-----------------+-----------------+---------+
/ / / /|
/ / / / |
/ / / / |
/ / / / |
/ / / / +
/ / / / /|
/ / / / / +
/ / / / / /|
/ / / / / / |
/ / / / / / |
------ +-----------------+-----------------+---------+ / / |
| | | | | / / |
| | 1st half page | 2st half page | | / / |
| | =256Bytes | =256Bytes | | / / |
| +-----------------+-----------------+---------+ / +
/|/ 1page->| | | | / / -> bit0
+-----------------+-----------------+---------+ / -> bit1
32pages | | | | / -> bit2
=1Block | | | | / -> bit3
/|/ | | | | / -> bit4
| | | | | / -> bit5
| | | | | / -> bit6
| | | | | / -> bit7
------ +-----------------+-----------------+---------+ |__ 1 Bytes = bit[7:0]
|-----------> 512 Bytes <---------|
这里我们需要了解到:
这款芯片是8位的,即通过8个io口来与cpu通信(包括地址、数据、命令的传送)。
如上图所示,8个bit组成1个Byte。
有多个Byte组成Page。1Page = 528 Bytes = 512 Bytes + 16 Bytes。注意这里每一页由两部分组成。前一部分512B是我们存储数据用的,后16B是用来存储ECC校验码等额外数据的。所以我们能使用到的就只有前512B。
1Block = 32Pages 。所以1Block = 32 * (512 + 12) Bytes = 2^5 * (2^9 + 2^4) = 2^14 +2^9 Bytes
我们这款芯片总共有4096个Block。所以总容量为:
4096 * (2^14 + 2^9) = 2^12 * (2^14 + 2^9) = 2^26 + 2^11 = 64MB + 2MB
在nandflash里寻址时,我们要定位到某一Byte,必须有三个地址需要确定:
1. 确定是在哪一个Block中。即Block Address
2. 在Block中的哪一页。 即Page Address
3. 一页中,具体是哪一个Byte。看上图Byte如同一列一列的排布,所以称为 Column Address。
定位64M中某一Byte,需要26位地址。再画个图比较直观一些:
26 14 13 9 8 7 0
+-----------------+-----------------+---+-----------------+
| Block Address | Page Address | Column Address |
+-----------------+-----------------+---+-----------------+
注意到bit8了吧。由于bit[7:0]只能表示256个数,而一页的数据区有512个,所以在这块芯片里将一页分为了两个半页。当bit8=0时为第一半页,bit8=1时为第二半页。bit8是由硬件来控制的,当读完一个半页之后,bit8会自动置位。
如此一来,当我们要取nandflash的某一Byte的数据时,就需要分4步来传递地址,然后才能读取到那一字节的数据。
1. 传递bit[7:0] 。相当于传递了Column Address
2. 传递bit[16:9] 。
3. 传递bit[24:17] 。
4. 传递bit[25] 。
可以看到这四个步就是为了传递整个26位地址(bit8特殊)。这就是我们通常所说的“四步寻址”。
由于s3c2410已经集成了nandflash控制器,所以对于nandflash的操作,地址、命令、数据的传递都是通过写nandflash控制器的寄存器来完成的。对于nandflash控制器的详细说明可以看2410的数据手册。
数据手册里有以下几句话,是关于nandflash控制器的配置的。在从nandflash里读出数据时,我们也是按照这个顺序来的。
NAND FLASH MODE CONFIGURATION
1. Set NAND flash configuration by NFCONF register.
2. Write NAND flash command onto NFCMD register.
3. Write NAND flash address onto NFADDR register.
4. Read/Write data while checking NAND flash status by NFSTAT register. R/nB signal should be checked
before read operation or after program operation.
vivi最开始使用nandflash是要把vivi自身从nandflash复制到sdram里。来看一下它是怎么完成的。
|
上面这段程序很清楚。但需要注意一个地方,一次读取要读512(NAND_SECTOR_SIZE)个字节。读取的时候默认是从第一个半页开始读取的。如果要从第二个半页开始读取,我们则要先写入一个命令,来使bit8置位。读完1st half page后,bit8自动置1,读完2st half page后,bit8也会自动清0 。
同样,读取时,我们也可以不从一页的开始读取。比如,可以从一页的中间读取,这种情况我还没有分析太清楚,但上面的程序显然是必须从某一页的开始读起的。因为在for循环里会连续向buf写512个数据。推荐从页始开始读比较好。
nandflash好些个command。写入不同的command时,也就可以对其进行不同的操作。
----------------------------+--------------+----------+-----------
Function | 1st. Cycle |2nd. Cycle| 3rd. Cycle
----------------------------+--------------+----------+-----------
Read 1 | 00h/01h(1) | - | - 00:读1st half page 01:读2st half page
----------------------------+--------------+----------+-----------
Read 2 | 50h | - | -
----------------------------+--------------+----------+-----------
Read ID | 90h | - | -
----------------------------+--------------+----------+-----------
Reset | FFh | - | -
----------------------------+--------------+----------+-----------
Page Program (True) | 80h | 10h | -
----------------------------+--------------+----------+-----------
Page Program (Dummy) | 80h | 11h | -
----------------------------+--------------+----------+-----------
Copy-Back Program(True) | 00h | 8Ah | 10h
----------------------------+--------------+----------+-----------
Copy-Back Program(Dummy) | 03h | 8Ah | 11h
----------------------------+--------------+----------+-----------
Block Erase | 60h | D0h | -
----------------------------+--------------+----------+-----------
Multi-Plane Block Erase | 60h----60h | D0h | -
----------------------------+--------------+----------+-----------
Read Status | 70h | - | -
----------------------------+--------------+----------+-----------
Read Multi-Plane Status | 71h | - | -
----------------------------+--------------+----------+-----------