uboot nand 2gb fix

drivers/nand中的nand_init
对于s3c6410来说
#define CFG_NAND_BASE           (0x70200010)
之后是
nand_init_chip
nand->IO_ADDR_R = nand->IO_ADDR_W = (void  __iomem *base_addr;
取出地址,再下一步,
board_nand_init

 

4K是正确的,好像到了8G 这个值才需要改动, 256M也是4K。

K9G8G08(1块=128页=256K),在1G的MLC NAND上启动正常

Device 0: NAND 2GiB 3,3V 8-bit, sector size 512 KiB
NAND:    maf.id = 0xec
device.id = 0xd5

 

drivers/nand中的nand_init
对于s3c6410来说
#define CFG_NAND_BASE           (0x70200010)
之后是
nand_init_chip
nand->IO_ADDR_R = nand->IO_ADDR_W = (void  __iomem *base_addr;
取出地址,再下一步,
board_nand_init

 

uboot中打印信息:

NAND:    maf.id = 0xec
device.id = 0xd5
nand flash name is NAND 2GiB 3,3V 8-bit
nand type MLC
pagesize = 0x1000
oobsize = 0x80
blocksize = 0x80000
busw = 0x0
2048 MB

 

/写是一个page,擦是一个block
programe size 4224-byte page(=4096 + 128,所以oob也是128)
erase size 512K+16K byte block
512K-----80000
说明第一块就是坏块

Device 0 bad blocks:
  00000000
  00080000

 

K9GAG08U

G: MLC normal

AG: 16G

08: x8

U: 2.7~3.6

0: NORMAL

M: 1st Generation

P

C

B

0

 

16G是指bit
所以是AG

 

从uboot中nand bad命令入口,看uboot是如何分别坏块的。

验证了下面的nand flash的datasheet中的colomn address 4096 of last page in the block的话。

具体的流程如下:

Device 0 bad blocks:
[do_nand]: off =  00000000
[nand_block_isbad]: 1  00000000
[nand_block_isbad]: 2  00000000
[nand_block_isbad]: mtd->erasesize = 0x80000, mtd->writesize = 0x1000
[nand_block_isbad]: 3  00000000
[nand_block_checkbad]:  00000000
[nand_block_checkbad]: mtd->erasesize = 0x80000, mtd->writesize = 0x1000
[nand_block_bad]: 1 ofs = 0x00000000
[nand_block_bad]: 2 ofs = 0x7f000
mtd->erasesize = 0x80000, mtd->writesize = 0x1000, and chip->page_shift = 0xc
page = 0x7f, chipnr = 0x0
[nand_command_lp]: column = 0x1000
find a bad block, and result = 0x0
  00000000

其中打印

 printf("[nand_block_bad]: 1 ofs = 0x%08x /n", (ulong)ofs);
都要加上ulong。因为ofs是loff_t即long long型。

 

开始的想法是oob应该也算地址,但是实际上是这样

先按照erase_block(即块)递增,然后在这个基础上每次移动到当前块的最后一个page,之后算出这个page的number作为page号,然后再把column地址变成pagesize,顺序把read这个cmd,地址中的page,column传送给nand flash,然后从6410的nand flash数据地址寄存器中就可以读出这个地址的值了。

 

要注意看看硬件有没有错,地址线之类的

另外要注意,如果在movinand的uboot上使用nand read的指令,出现ecc uncorrectable的错误是正常的。因为这时候没有BBT。

 

后在uboot中使用nand scrub的命令,强制性的把坏块标志去除,后可以在第0块写入东西,重启后不丢失。

 

硬件地址线,包括从nand启动的配置是没有错的,因为从datasheet知道irom-nand的启动方式,在我们自己的板子上用这种方式,不行。在idea的板子上用这种方式,还是不行。

具体方法:在uboot中使能CONFIG_NAND_BL1_8BIT_ECC的宏,因为nand搬运和irom搬用的方式不一样,nand搬运是基于nand的第一块肯定是好的,搬运8kb的BL1肯定不会有问题,而irom搬运是用8bit的ECC来保证取到的东西是正确的(也许并不需要?)。

 

一般烧写前先用nand bad看下坏块的分布

 

/**
 * struct nand_flash_dev - NAND Flash Device ID Structure
 * @name: Identify the device type
 * @id:  device ID code
 * @pagesize: Pagesize in bytes. Either 256 or 512 or 0
 *  If the pagesize is 0, then the real pagesize
 *  and the eraseize are determined from the
 *  extended id bytes in the chip
 * @erasesize: Size of an erase block in the flash device.
 * @chipsize: Total chipsize in Mega Bytes
 * @options: Bitfield to store chip relevant options
 */
struct nand_flash_dev {
 char *name;
 int id;
 unsigned long pagesize;  //0 mean not fixed
 unsigned long chipsize;
 unsigned long erasesize;  //0 mean not fixed
 unsigned long options;
};

 

 

Bad Block Table (BBT)

Since the usual bad block marker in the OOB area does not allow us to distinguish between factory-bad and worn-out-bad blocks, we need to store this information elsewhere. This place is called bad-block table (BBT) and is stored as a bitmap in the last two good blocks at the end of NAND . To increase security, a backup of those two blocks is kept in the two preceding good blocks as well.

The BBT location itself is identified by special markers (BBT0/BBT1) in the OOB area of the first page of the respective erase blocks.

The BBT consists of two bits per block which distinguish the three conditions (factory-bad/worn-out/good).

Both u-boot and Linux implement the same BBT layout and thus interoperate quite well.

BBT creation

The BBT is created once a BBT-implementing u-boot is started for the first time. The BBT scanning code assumes that the NAND is completely erased , i.e. only contains 0xff as content. Any block that contains bytes != 0xff in the OOB is marked as "factory bad" block.

 

据说4KB的pagesize和8位的ecc是对应的。而且需要很大的nand_ecclayout(128?)。

 

既然NAND controller支持ECC_HW,是不是就应该打开ECC_HW?

 

Understanding Memory Technology Devices in Embedded Linux

from BOOK: Essential Linux Device Drivers

讲述了NAND的一些知识

NAND Chip Drivers

NAND technology users such as USB pen drives, DOMs, Compact Flash memory, and SD/MMC cards emulate standard storage interfaces such as SCSI or IDE over NAND flash, so you don't need to develop NAND drivers to communicate with them.5 On-board NAND flash chips need special drivers, however, and are the topic of this section.

As you learned previously in this chapter, NAND flash chips, unlike their NOR counterparts, are not connected to the CPU via data and address lines. They interface to the CPU through special electronics called a NAND flash controller that is part of many embedded processors. To read data from NAND flash, the CPU issues an appropriate read command to the NAND controller. The controller transfers data from the requested flash location to an internal RAM memory, also part of the controller. The data transfer is done in units of the flash chip's page size (for example, 2KB). In general, the denser the flash chip, the larger is its page size. Note that the page size is different from the flash chip's block size , which is the minimum erasable flash memory unit (for example, 16KB). After the transfer operation completes, the CPU reads the requested NAND contents from the internal RAM. Writes to NAND flash are done similarly, except that the controller transfers data from the internal RAM to flash. The connection diagram of NAND flash memory on an embedded device is shown in Figure 17.3 .

 

Figure 17.3 NAND flash connection.

Because of this unconventional mode of addressing, you need special drivers to work with NAND storage. MTD provides such drivers to manage NAND-resident data. If you are using a supported chip, you have to enable only the appropriate low-level MTD NAND driver. If you are writing a NAND flash driver, however, you need to explore two datasheets: the NAND flash controller and the NAND flash chip.

NAND flash chips do not support automatic configuration using protocols such as CFI. You have to manually inform MTD about the properties of your NAND chip by adding an entry to the nand_flash_ids[] table defined in drivers/mtd/nand/nand_ids.c . Each entry in the table consists of an identifier name, the device ID, page size, erase block size, chip size, and options such as the bus width.

There is another characteristic that goes hand in hand with NAND memory. NAND flash chips, unlike NOR chips, are not faultless. It's normal to have some problem bits and bad blocks scattered across NAND flash regions. To handle this, NAND devices associate a spare area with each flash page (for example, 64 bytes of spare area for each 2KB data page). The spare area contains out-of-band (OOB) information to help perform bad block management and error correction. The OOB area includes error correcting codes (ECCs) to implement error correction and detection. ECC algorithms correct single-bit errors and detect multibit errors. The nand_ecclayout structure defined in include/mtd/mtd-abi.h specifies the layout of the OOB spare area:

struct nand_ecclayout {
uint 32_t eccbytes;
uint32_t eccpos[64];
uint32_t oobavail;
struct nand_oobfree oobfree[MTD_MAX_OOBFREE_ENTRIES];
};

In this structure, eccbytes holds the number of OOB bytes that store ECC data, and eccpos is an array of offsets into the OOB area that contains the ECC data. oobfree records the unused bytes in the OOB area available to flash filesystems for storing flags such as clean markers that signal successful completion of erase operations.

Individual NAND drivers initialize their nand_ecclayout according to the chip's properties. Figure 17.4 illustrates the layout of a NAND flash chip having a page size of 2KB. The OOB semantics used by the figure is the default for 2KB page-sized chips as defined in the generic NAND driver, drivers/mtd/nand/nand_base.c .

 
 
                                 Figure 17.4
In The Pic: 2-39 for FILE SYSTEM, 40-63, OOB

Figure 17.4 Layout of a NAND flash chip.

Often, the NAND controller performs error correction and detection in hardware by operating on the ECC fields in the OOB area. If your NAND controller does not support error management, however, you will need to get MTD to do that for you in software. The MTD nand_ecc driver (drivers/mtd/nand/nand_ecc.c ) implements software ECC.

Figure 17.4 also shows OOB memory bytes that contain bad block markers. These markers are used to flag faulty flash blocks and are usually present in the OOB region belonging to the first page of each block . The position of the marker inside the OOB area depends on the properties of the chip. Bad block markers are either set at the     

    

(In 2G flash according to this to judge bad block)

factory during manufacture, or by software when it detects wear in a block. MTD implements bad block management in drivers/mtd/nand/nand_bbt.c .

 

The mtd_partition structure used in Listing 17.1 for the NOR flash in Figure 17.2 works for NAND memory, too. After you MTD-enable your NAND flash, you can access the constituent partitions using standard device nodes such as /dev/mtd/X and /dev/mtdblock/X . If you have a mix of NOR and NAND memories on your hardware, X can be either a NOR or a NAND partition. If you have a total of more than 32 flash partitions, accordingly change the value of MAX_MTD_DEVICES in include/linux/mtd/mtd.h .

To effectively make use of NAND storage, you need to use a filesystem tuned for NAND access, such as JFFS2 or YAFFS2, in tandem with the low-level NAND driver. We discuss these filesystems in the next section.

 

/* zhangq add this to support oob 128 */
struct nand_ecclayout nand_oob_128 = {
 .eccbytes = 48,
 .eccpos = {
     80, 81, 82, 83, 84, 85, 86, 87,
     88, 89, 90, 91, 92, 93, 94, 95,
     96, 97, 98, 99, 100, 101, 102, 103,
     104, 105, 106, 107, 108, 109, 110, 111,
     112, 113, 114, 115, 116, 117, 118, 119,
     120, 121, 122, 123, 124, 125, 126, 127},
 .oobfree = {
  {.offset = 2,
   .length = 78}}
};

 

   nand->ecc.size = 128;
//   nand->ecc.bytes = 8; /* really 7 bytes */
   nand->ecc.bytes = 48; /* really 7 bytes */

ecc.size = ecc.bytes + lenth + offset                                128 = 78 + 2 + 48

 

 

 

    nand->ecc.size = 512;
   nand->ecc.bytes = 8; /* really 7 bytes */

这里只是一行8个,然后这8个字节总共能校验的大小等于size

 chip->ecc.steps = mtd->writesize / chip->ecc.size;
step就是说要几次才能完成ecc校验

  chip->ecc.total = chip->ecc.steps * chip->ecc.bytes;

就是说要完成校验总共要多少ecc字节 

 

 

 

NAND_NCE   select the chip by setting nCE to low

NAND_CLE    select the command latch by setting CLE to high

NAND_ALE    select the address latch by setting ALE to high

 

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值