2012-03-14 22:27 U-BOOT支持烧写yaffs2文件系统

U-BOOT 支持yaffs2文件系统的烧写。
其实移植这步烧写很简单,只是将打包的文件系统一次写入NAND即可,以页为单位,一次写入2K+64B。
包含main和spare区,其中spare的ECC数据等在yaffs2文件系统制作时就已经写好了。是通过软件ECC
每256B产生3B的规则进行的。所以必须保证mkyaffs2image工具能正确制作YAFFS2文件系统。否则系统是
启动不了。

具体移植步骤:
1.在include/configs/xxxxx.h增加宏
#define CONFIG_MTD_NAND_YAFFS2
2.添加write.yaffs2烧写命令,U-BOOT只需要写命令即可
 vim common/cmd_nand.c中

 501 #if defined(CONFIG_MTD_NAND_YAFFS2)
 502            "nand read.yaffs2 - addr off|partition size\n"
 503            "nand write.yaffs2 - addr off|partiton size\n"
 504 #endif

添加以上帮助说明信息

增加解析yaffs2命令的函数

 344 #if defined(CONFIG_MTD_NAND_YAFFS2)
 345                  else if(s != NULL && !strcmp(s, ".yaffs2") ) {
 346                         if (read) {
 347 /*                              nand->rw_oob = 1;
 348                                 nand->skipfirstblk = 1;
 349                                 ret = nand_read_skip_bad(nand,off,&size,(u_     chat *)addr);
 350                                 nand->skipfirstblk = 0;
 351                                 nand->rw_oob = 0;
 352 */
 353                         }
 354                         else {/* 主要关心写命令 */
 355                                 nand->rw_oob = 1;
 356                                 nand->skipfirstblk = 1;
 357                                 ret = nand_write_skip_bad(nand, off, &size,      (u_char *)addr);
 358                                 nand->skipfirstblk = 0;
 359                                 nand->rw_oob = 0;
 360                         }
 361                 }
 362 #endif
nand->rw_oob  和 nand->skipfirstblk 一个作为烧写YAFFS的标志,文件系统跳过的块,因为YAFFS2文件系统烧写时需要跳过
第一块。这是由于其特性决定的,第一块用于构建BBT(bad block table)

这两个新成员需要添加在include/linux/mtd/mtd.h的mtd_info结构体中
128 #if defined(CONFIG_MTD_NAND_YAFFS2)
129         u_char rw_oob;
130         u_char skipfirstblk;
131 #endif

3.由于写操作会调用nand_write_skip_bad()函数,这里也需要修改,位于nand_util.c

474 #if defined(CONFIG_MTD_NAND_YAFFS2)
475         if (nand->rw_oob == 1) {/* 烧写的YAFFS2文件 */
476
477                 size_t oobsize = nand->oobsize;
478                 size_t datasize = nand->writesize;
479                 int datapages = 0;
480                 datapages = (*length)/(datasize+oobsize);/* 注意这里是整个长度 */
481                 *length = datapages*datasize; /* 实际main区大小 */
482                 left_to_write = *length; /* 在具体烧写时会以left_to_write做参数 */
483         }
484 #endif
传入这个函数的size 是nand命令参数给的,对于YAFFS2为实际大小,即2112的倍数,off也是经由命令行传递来的
而addr是对应内存BUF的地址
466 int nand_write_skip_bad(nand_info_t *nand, ulong offset, size_t *length,
467                         u_char *buffer)
这是函数原型
所以以上添加代码的意思是,如注释,也就是从yaffs2文件大小中提取main区的数据大小
在以下代码添加如是宏,避免影响其他烧写
498 #if !defined (CONFIG_MTD_NAND_YAFFS2)
499         if (len_incl_bad == *length) {
500                 rval = nand_write (nand, offset, length, buffer);
501                 if (rval != 0)
502                         printf ("NAND write to offset %x failed %d\n",
503                                 offset, rval);
504
505                 return rval;
506         }
507 #endif

518 #if defined(CONFIG_MTD_NAND_YAFFS2)
519                 if (nand->skipfirstblk == 1) {/* 需要跳过第一块 */
520                         nand->skipfirstblk = 0;
521                         printf("Skip the first good block 0x%08x\n",offset &   
522                                 ~(nand->erasesize - 1));
523                         offset += nand->erasesize - block_offset;/* 故偏移地址 + 1block */
524                         continue;
525                 }
526 #endif
527          

542 #if defined(CONFIG_MTD_NAND_YAFFS2)
543                 if (nand->rw_oob == 1)
544                         p_buffer += write_size+(write_size/nand->writesize*nand->oobsize);
  /* 注意因为是一次烧写main和spare 故指向镜像的指针编译量要加上OOB区的大小,一次写入一块,不足一块以页写入*/
545                 else
546                         p_buffer += write_size;
547 #else
548
549                 p_buffer      += write_size;
550 #endif
551         }
552
553         return 0;
554 }

4.下面看nand_write()的实现
536                 rval = nand_write (nand, offset, &write_size, p_buffer);
这是传递的参数,函数位于nand_base.c中

2011 #if defined(CONFIG_MTD_NAND_YAFFS2)
2012         int oldopsmode = 0;
2013         if (mtd->rw_oob != 1)
2014                 chip->ops.oobbuf = NULL;
2015         else {
2016                 chip->ops.oobbuf = (uint8_t *)(buf+mtd->writesize);/* oob数据起始地址 */
2017                 chip->ops.ooblen = mtd->oobsize; /* 64B */
2018                 chip->ops.ooboffs = 0;
2019                 oldopsmode = chip->ops.mode;
2020                 chip->ops.mode =MTD_OOB_RAW; /* 原始模式,不进行ECC计算 */
2021         }
2022 #else
2023         chip->ops.oobbuf = NULL;
2024 #endif

其实这个函数只是填充nand_chip这个结构体然后调用
2053         ret = nand_do_write_ops(mtd, to, &chip->ops);

函数原型如下
1887 /**
1888  * nand_do_write_ops - [Internal] NAND write with ECC
1889  * @mtd:        MTD device structure
1890  * @to:         offset to write to
1891  * @ops:        oob operations description structure
1892  *
1893  * NAND write with ECC
1894  */
1895 static int nand_do_write_ops(struct mtd_info *mtd, loff_t to,
1896                              struct mtd_oob_ops *ops)

这个函数功能,选择具体的一片NAND,当然大多情况只有一片,然后会处理OOB区数据
根据chip->ops.mode,这里为原始模式,即不进行处理,则将OOB区数据复制到对应的ops


这是里面添加的内容
然后会调用具体的write_page写一页数据

1972 #if defined(CONFIG_MTD_NAND_YAFFS2)
1973                 if (mtd->rw_oob == 1) {
1974                 oob = oob + bytes;
1975                 buf = buf + ops->ooblen;
1976                 }
1977 #endif
每写一次oob和databuf都移动2112B。

1962                 ret = chip->write_page(mtd, chip, wbuf, page, cached,
1963      

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值