参考:http://blog.csdn.net/IT_114
在自己2.6.33 内核中,分区是:
- 1. static struct mtd_partition smdk_default_nand_part[] = {
- 2. #if defined (CONFIG_256MB_NAND)
- 3. [0] = {
- 4. .name = "ywx-uboot",
- 5. .size = 0x00040000, ##256KB
- 6. .offset = 0x0,
- 7. },
- 8. [1] = {
- 9. .name = "ywx-kernel",
- 10. .offset = 0x00200000,
- 11. .size = 0x00200000, ##2MB
- 12. },
- 13. [2] = {
- 14. .name = "ywx-yaffs2",
- 15. .offset = 0x00400000,
- 16. .size = 0x0fb80000, ##251.5MB
- 17. }
- 18. #endif
- 19. };
在 uboot 中分区如下:
0~0x40000 u-boot (256K)
0x200000~0x400000 kernel (2M)
0x400000~~ (剩余的)
1、通常一个Nnad Flash存储设备由若干块组成,1个块由若干页组成。一般128MB以下容量的Nand Flash芯片,一页大小为528B,被依次分为2个256B的主数据区和16B的额外空间。128MB以上容量的Nand Flash芯片,一页大小通常为2KB。由于Nand Flash出现位反转的概率较大,一般在读写时需要使用ECC进行错误检验和恢复。TQ2440上的Nandflash型号是K9F2G08,页面大小为page = 2K + 64Byte。
Yaffs/yaffs2文件系统的设计充分考虑到Nand Flash以页为存取单位等的特点,将文件组织成固定大小的段(Chunk)。以528B的页为例,Yaffs/yaffs2文件系统使用前512B存储数据和16B的额外空间存放数据的ECC和文件系统的组织信息等(称为OOB数据)。通过OOB数据,不但能实现错误检测和坏块处理,同时还可以避免加载时对整个存储介质的扫描,加快了文件系统的加载速度。以下是Yaffs/yaffs2文件系统页的结构说明
Yaffs页结构说明 |
好了,在了解Nand Flash组成和Yaffs/yaffs2文件系统结构后,我们再回到u-boot中。目前,在u-boot中已经有对Cramfs、Jffs2等文件系统的读写支持,但与带有数据校验等功能的OOB区的Yaffs/Yaffs2文件系统相比,他们是将所有文件数据简单的以线性表形式组织的。所以,我们只要在此基础上通过修改u-boot的Nand Flash读写命令,增加处理00B区域数据的功能,即可以实现对Yaffs/Yaffs2文件系统的读写支持。
- //定义一个管理对Yaffs2支持的宏
- #define CONFIG_MTD_NAND_YAFFS2 1
- //开启Nand Flash默认分区,注意此处的分区要和你的内核中的分区保持一致
- #define MTDIDS_DEFAULT "nand0=nandflash0"
- #define MTDPARTS_DEFAULT "mtdparts=nandflash0:256k(bootloader)," \
- "2m(kernel)," \
- "-(root)"
- U_BOOT_CMD(nand, CONFIG_SYS_MAXARGS, 1, do_nand,
- "NAND sub-system",
- "info - show available NAND devices\n"
- "nand device [dev] - show or set current device\n"
- "nand read - addr off|partition size\n"
- "nand write - addr off|partition size\n"
- " read/write 'size' bytes starting at offset 'off'\n"
- " to/from memory address 'addr', skipping bad blocks.\n"
- /*注意:这里只添加了yaffs2的写命令,因为我们只用u-boot下载(即写)功能,所以我们没有添加yaffs2读的命令*/
- #if defined(CONFIG_MTD_NAND_YAFFS2)
- "nand write[.yaffs2] - addr off|partition size - write `size' byte yaffs image\n"
- " starting at offset off' from memory address addr' (.yaffs2 for 512+16 NAND)\n"
- #endif
- "nand erase [clean] [off size] - erase 'size' bytes from\n"
- " offset 'off' (entire device if not specified)\n"
- "nand bad - show bad blocks\n"
- "nand dump[.oob] off - dump page\n"
- "nand scrub - really clean NAND erasing bad blocks (UNSAFE)\n"
- "nand markbad off [...] - mark bad block(s) at offset (UNSAFE)\n"
- "nand biterr off - make a bit error at offset (UNSAFE)"
- #ifdef CONFIG_CMD_NAND_LOCK_UNLOCK
- "\n"
- "nand lock [tight] [status]\n"
- " bring nand to lock state or display locked pages\n"
- "nand unlock [offset] [size] - unlock section"
- #endif
- );
接着,在该文件中对nand操作的do_nand函数中添加yaffs2对nand的操作,如下:
- if (strncmp(cmd, "read", 4) == 0 || strncmp(cmd, "write", 5) == 0) {
- int read;
- if (argc < 4)
- goto usage;
- addr = (ulong)simple_strtoul(argv[2], NULL, 16);
- read = strncmp(cmd, "read", 4) == 0; /* 1 = read, 0 = write */
- printf("\nNAND %s: ", read ? "read" : "write");
- if (arg_off_size(argc - 3, argv + 3, nand, &off, &size) != 0)
- return 1;
- s = strchr(cmd, '.');
- if (!s || !strcmp(s, ".jffs2") ||
- !strcmp(s, ".e") || !strcmp(s, ".i")) {
- if (read)
- ret = nand_read_skip_bad(nand, off, &size,
- (u_char *)addr);
- else
- ret = nand_write_skip_bad(nand, off, &size,
- (u_char *)addr);
- }
- /*添加yaffs2相关操作,注意该处又关联到nand_write_skip_bad函数*/
- #if defined(CONFIG_MTD_NAND_YAFFS2)
- else if (s != NULL && (!strcmp(s, ".yaffs2")))
- {
- nand->rw_oob = 1;
- nand->skipfirstblk = 1;
- ret = nand_write_skip_bad(nand,off,&size,(u_char *)addr);
- nand->skipfirstblk = 0;
- nand->rw_oob = 0;
- }
- #endif
- /*添加结束*/
- else if (!strcmp(s, ".oob")) {
- /* out-of-band data */
- mtd_oob_ops_t ops = {
- .oobbuf = (u8 *)addr,
- .ooblen = size,
- .mode = MTD_OOB_RAW
- };
- if (read)
- ret = nand->read_oob(nand, off, &ops);
- else
- ret = nand->write_oob(nand, off, &ops);
- } else {
- printf("Unknown nand command suffix '%s'.\n", s);
- return 1;
- }
- printf(" %zu bytes %s: %s\n", size,
- read ? "read" : "written", ret ? "ERROR" : "OK");
- return ret == 0 ? 0 : 1;
- }
在include/linux/mtd/mtd.h头文件的mtd_info结构体中添加上面用到rw_oob和skipfirstblk数据成员,如下:
#vi include/linux/mtd/mtd.h //在mtd_info结构体中添加
- #if defined(CONFIG_MTD_NAND_YAFFS2)
- u_char rw_oob;
- u_char skipfirstblk;
- #endif
在第二步关联的nand_write_skip_bad函数中添加对Nand OOB的相关操作,如下:
#vi drivers/mtd/nand/nand_util.c //在nand_write_skip_bad函数中添加
上传 nand_util.c 附件
![](/blog/image/attachicons/rar.gif)
- int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
- u_char *buffer)
- {
- int rval;
- size_t left_to_write = *length;
- size_t len_incl_bad;
- u_char *p_buffer = buffer;
- #if defined(CONFIG_MTD_NAND_YAFFS2) /*add yaffs2 file system support*/
- if(nand->rw_oob==1)
- {
- size_t oobsize = nand->oobsize;
- size_t datasize = nand->writesize;
- int datapages = 0;
- if (((*length)%(nand->oobsize+nand->writesize)) != 0)
- {
- printf ("Attempt to write error length data!\n");
- return -EINVAL;
- }
- datapages = *length/(datasize+oobsize);
- *length = datapages*datasize;
- left_to_write = *length;
- }
- #endif
- /* Reject writes, which are not page aligned */
- if ((offset & (nand->writesize - 1)) != 0 ||
- (*length & (nand->writesize - 1)) != 0) {
- printf ("Attempt to write non page aligned data\n");
- return -EINVAL;
- }
- len_incl_bad = get_len_incl_bad (nand, offset, *length);
- if ((offset + len_incl_bad) > nand->size) {
- printf ("Attempt to write outside the flash area\n");
- return -EINVAL;
- }
- /*修改 开始*/
- #if !defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support
- if (len_incl_bad == *length) {
- rval = nand_write (nand, offset, length, buffer);
- if (rval != 0)
- printf ("NAND write to offset %llx failed %d\n",offset, rval);
-
- return rval;
- }
- #endif
- /*修改 结束*/
- while (left_to_write > 0) {
- size_t block_offset = offset & (nand->erasesize - 1);
- size_t write_size;
- WATCHDOG_RESET ();
- if (nand_block_isbad (nand, offset & ~(nand->erasesize - 1))) {
- printf ("Skip bad block 0x%08llx\n",
- offset & ~(nand->erasesize - 1));
- offset += nand->erasesize - block_offset;
- continue;
- }
- /*添加 开始*/
- #if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support
- if(nand->skipfirstblk==1)
- {
- nand->skipfirstblk=0;
- printf ("Skip the first good block %llx\n", offset & ~(nand->erasesize - 1));
- offset += nand->erasesize - block_offset;
- continue;
- }
- #endif
- /*添加 结束*/
- if (left_to_write < (nand->erasesize - block_offset))
- write_size = left_to_write;
- else
- write_size = nand->erasesize - block_offset;
- /*添加 开始*/
- printf("\rWriting at 0x%llx -- ",offset); //add yaffs2 file system support
- /*添加 结束*/
- rval = nand_write (nand, offset, &write_size, p_buffer);
- if (rval != 0) {
- printf ("NAND write to offset %llx failed %d\n",
- offset, rval);
- *length -= left_to_write;
- return rval;
- }
- left_to_write -= write_size;
- offset += write_size;
-
- /*添加 开始*/
- #if defined(CONFIG_MTD_NAND_YAFFS2) //add yaffs2 file system support
- if(nand->rw_oob==1)
- {
- p_buffer += write_size+(write_size/nand->writesize*nand->oobsize);
- }
- else
- {
- p_buffer += write_size;
- }
- #else
- p_buffer += write_size;
- #endif
- /*添加 结束*/
- }
- return 0;
- }
OK,对yaffs2支持的代码已修改完毕,重新编译u-boot并下载到nand中,启动开发板,在u-boot的命令行输入:nand help查看nand的命令,可以看到多了一个nand write[.yaffs2]的命令,这个就是用来下载yaffs2文件系统到nand中的命令了。
make smdk2440_config && make all
然后设置,DNW的地址为 0x0, 把根目录下的u-boot.bin 下载到Nandflash的地址0处
1.选择 nor flash启动模式
2.进入 nor flash 下载模式界面
3.选择 “1”
[1] Download u-boot or STEPLDR.nb1 or other bootloader to Nand Flash
4.下载成功后,关机。
5.拨到从 nand flash 启动模式
6.打开电源,开机
- U-Boot 2010.06-rc1 ( 4鏈?17 2011 - 10:15:21)
- DRAM: 64 MiB
- Flash: 2 MiB
- NAND: 256 MiB
- In: serial
- Out: serial
- Err: serial
- Net: dm9000
- [SMDK2440]# nand help
- nand - NAND sub-system
- Usage:
- nand info - show available NAND devices
- nand device [dev] - show or set current device
- nand read - addr off|partition size
- nand write - addr off|partition size
- read/write 'size' bytes starting at offset 'off'
- to/from memory address 'addr', skipping bad blocks.
- nand write[.yaffs2] - addr off|partition size - write `size' byte yaffs image
- starting at offset off' from memory address addr' (.yaffs2 for 512+16 NAND)
- nand erase [clean] [off size] - erase 'size' bytes from
- offset 'off' (entire device if not specified)
- nand bad - show bad blocks
- nand dump[.oob] off - dump page
- nand scrub - really clean NAND erasing bad blocks (UNSAFE)
- nand markbad off [...] - mark bad block(s) at offset (UNSAFE)
- nand biterr off - make a bit error at offset (UNSAFE)
- [SMDK2440]#
- A sample .exrc file for vi e...
- IBM System p5 服务器 HACMP ...
- 游标的特征
- busybox的httpd使用CGI脚本(Bu...
- Solaris PowerTOP 1.0 发布