您好,欢迎来到61ic! | [登录] [注册] 忘记密码 | 设为首页 帮助
 . 网站首页 . 业界新闻 . 设计中心 . 移动技术 . TI专栏 . ADI专栏 . FPGA专栏 . 代码工厂 . 官方商城 . 
 . 活动专区 . 新品快递 . 解决方案 . 前沿科技 . TI资源 . ADI资源 . FPGA资源 . 下载中心 . 产品展示 . 
加入收藏
付款方式
联系我们
您现在的位置: 61IC电子在线 >> TI专栏 >> TI DaVinci >> TMS320DM3x SOC >> 正文
  移植ubifs到DM368成功           ★★★ 【字体:
移植ubifs到DM368成功
作者:LIDEHUA1…    文章来源:LIDEHUA1975    点击数:    更新时间:2013-7-12    

我在用TI的dm368开发板,kernel是2.6.32.17,默认的flash文件系统是jffs2,但是jffs2在大分区下,mount速度很慢,而且占用ram较多,因此,我想使用ubifs看看性能是否会更好些。

ubifs的原理和配置过程,很多网页都有介绍的,我给一个链接,大家可以看看,我就不转载了,我重点说我移植过程中遇到并解决的问题。

http://bbs.chinaunix.net/thread-1954881-1-1.html

 

kerne的配置很简单,2.6.32里面都有,选上并重新编译就好了。

ubiattach、ubimkvol等工具,TI的dvsdk里面自带了,能用,我就偷了个懒,没有重新编译。

 

很轻松的照着网页说明操作了下,mount 分区也成功了,复制文件也成功了,很高兴:)

ubiattach /dev/ubi_ctrl -m 3

ubimkvol  /dev/ubi0 -N rootfs -s 480MiB

mount -t ubifs  ubi0_0 /mnt/nand/ -o sync

但很快就遇到麻烦了,开发板关机重新启动,我再mout ubi文件系统就出错了,提示了一堆错误,而且分区是空的,之前复制的文件不见了。

问题如下:

ubiattach /dev/ubi_ctrl -m 3

UBI error: ubi_io_read: error -74while reading 64 bytes from PEB 1662:0, read 64 bytes

UBI error: ubi_io_read: error -74while reading 64 bytes from PEB 1663:0, read 64 bytes

 

为了分析问题,我把mtd和ubifs的debug log都打开了,看到了一些信息;

#define   EBADMSG           74   /* Not a data message */

              /*Nand returns -EBADMSG on ecc errors, but it returns

               * the data. For our userspace tools it isimportant

               * to dump areas with ecc errors !

               * For kernel internal usage it also mightreturn -EUCLEAN

               * to signal the caller that a bitflip hasoccured and has

               * been corrected by the ECC algorithm.

               * Userspace software which accesses NAND thisway

               * must be aware of the fact that it deals withNAND

               */

nand_do_read_ops

       stats= mtd->ecc_stats;

       if(mtd->ecc_stats.failed - stats.failed)

              return-EBADMSG;

  

nand_read_page_hwecc

              stat= chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);

              if(stat < 0)

                     mtd->ecc_stats.failed++;

              else

                     mtd->ecc_stats.corrected+= stat;

看样子,应该是ECC出错了,可是我用的是硬件ECC校验,怎么可能几乎全部的page都出现ecc校验错误了呢?

 

root@dm368-evm:~#flash_eraseall  /dev/mtd3

root@dm368-evm:~# ubiattach/dev/ubi_ctrl -m 3

UBI: attaching mtd3 to ubi0

UBI: physical eraseblock size:   131072 bytes (128 KiB)

UBI: logical eraseblock size:    129024 bytes

UBI: smallest flash I/O unit:    2048

UBI: sub-page size:              512

UBI: VID header offset:          512 (aligned 512)

UBI: data offset:                2048

 

分析下UBI写数据的过程,

UBI DBG (pid 1484): ubi_io_write:write 512 bytes to PEB 57:0

int ubi_io_write(struct ubi_device*ubi, const void *buf, int pnum, int offset,

               int len)

       addr= (loff_t)pnum * ubi->peb_size + offset;

       err= ubi->mtd->write(ubi->mtd, addr, len, &written, buf);

在io_init函数中可以看到几个变量的赋值;

       ubi->peb_size   = ubi->mtd->erasesize;

       ubi->peb_count  = mtd_div_by_eb(ubi->mtd->size,ubi->mtd);

       ubi->flash_size= ubi->mtd->size;

从debug log来看,这里一次写了512字节,从某个block的起始page开始,offset是0;

那么到了nand mtd底层驱动,行为就是;

nand_write->nand_do_write_ops:

       subpage= column || (writelen & (mtd->writesize - 1));

这里,subpage就是writelen,512;

也可以得知一点,ubifs没有使用oob,这跟jffs2和yaffs2是不同的;

              /*Partial page write ? */

              if(unlikely(column || writelen < (mtd->writesize - 1))) {

                     cached= 0;

                     bytes= min_t(int, bytes - column, (int) writelen);

                     chip->pagebuf= -1;

                     memset(chip->buffers->databuf,0xff, mtd->writesize);

                     memcpy(&chip->buffers->databuf[column],buf, bytes);

                     wbuf= chip->buffers->databuf;

              }

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

                                   (ops->mode == MTD_OOB_RAW));

下面是write_page函数的代码;

static int nand_write_page(structmtd_info *mtd, struct nand_chip *chip,

                        const uint8_t *buf, int page, int cached,int raw)

{

       intstatus;

 

       chip->cmdfunc(mtd,NAND_CMD_SEQIN, 0x00, page);

 

       if(unlikely(raw))

              chip->ecc.write_page_raw(mtd,chip, buf);

       else

              chip->ecc.write_page(mtd,chip, buf);

 

       /*

        * Cached progamming disabled for now, Not sureif its worth the

        * trouble. The speed gain is not veryimpressive. (2.3->2.6Mib/s)

        */

       cached= 0;

这里需要注意的就是raw,如果是MTD_OOB_RAW,那么不会做ECC校验,也不会把ECC码写入OOB;

如果是这样,在read的时候也必须指定是MTD_OOB_RAW,不需要ECC校验;否则,就会出现我们最开始看到的错误;

       if(mtd->ecc_stats.failed - stats.failed)

              return-EBADMSG;

 

那么,从这里的情况来看,我们可能已经找到出错的原因了;ubi使用了subpage write,而底层nand flash驱动实际上是不支持subpage write的,尽管ubi一次只写了512字节,但这个page的其他部分已经不能再次写入新的数据了。

 

从Nand_base.c(drivers\mtd\nand)来看,large page的nand flash,对subpage write的支持是不完善的,限制条件比较多,比如,不能是MLC的nand flash,不能用硬件ECC;

更严重的问题是代码存在缺陷,在写入部分data的时候,将其他部分的数据填充为0xff了,然后write整个page,并写入全部ecc码到oob,也许这就是前面ecc校验出错的原因吧。

nand_do_write_ops()

              /*Partial page write ? */

memset(chip->buffers->databuf, 0xff, mtd->writesize);

                     memcpy(&chip->buffers->databuf[column],buf, bytes);

因此,我想到的解决办法就是在nand驱动中禁止subpage write。

第一步,在chip options中增加NAND_NO_SUBPAGE_WRITE;

static struct davinci_nand_pdatadavinci_nand_data = {

       .options         = NAND_USE_FLASH_BBT|NAND_NO_SUBPAGE_WRITE,

然后重新编译下载kernel,但问题依旧;

root@dm368-evm:~# ubiattach/dev/ubi_ctrl -m 3

UBI: attaching mtd3 to ubi0

UBI: physical eraseblock size:   131072 bytes (128 KiB)

UBI: logical eraseblock size:    129024 bytes

UBI: smallest flash I/O unit:    2048

UBI: sub-page size:              512

UBI: VID header offset:          512 (aligned 512)

心想很奇怪,为什么 sub-page size还是512?

回头查看代码,想看看sub page size是怎样计算出来的,

 if (!(chip->options & NAND_NO_SUBPAGE_WRITE) &&
     !(chip->cellinfo & NAND_CI_CELLTYPE_MSK)) {
  switch(chip->ecc.steps) {
  case 2:
   mtd->subpage_sft = 1;
   break;
  case 4:
  case 8:
  case 16:
   mtd->subpage_sft = 2;
   break;
  }
 }
 chip->subpagesize = mtd->writesize >> mtd->subpage_sft;

可是我已经给options增加了NAND_NO_SUBPAGE_WRITE啊?有些怀疑,我就在此处加了打印log,果然是这里出了问题,

chip->options = 0x10101.

mtd->subpage_sft = 0.

chip->subpagesize = 512.

 

#define NAND_NO_SUBPAGE_WRITE    0x00000200

可是,这里的options 明明是不对的!那我设置的NAND_NO_SUBPAGE_WRITE在哪里丢掉了?

 

在下面的函数中有对chip->options赋值改变;

nand_get_flash_type()

              printk(KERN_INFO"nand_get_flash_type 1, chip->options = 0x%x.\n",chip->options);

 

       /*Get chip options, preserve non chip based options */

       chip->options &= ~NAND_CHIPOPTIONS_MSK;

       printk(KERN_INFO"nand_get_flash_type 2, chip->options = 0x%x.\n",chip->options);   

       chip->options|= type->options & NAND_CHIPOPTIONS_MSK;

       printk(KERN_INFO"nand_get_flash_type 3, chip->options = 0x%x.\n",chip->options);

 

       /*

        * Set chip as a default. Board drivers canoverride it, if necessary

        */

       chip->options|= NAND_NO_AUTOINCR;

 

       /*Check if chip is a not a samsung device. Do not clear the

        * options for chips which are not having anextended id.

        */

       if(*maf_id != NAND_MFR_SAMSUNG && !type->pagesize)

              chip->options&= ~NAND_SAMSUNG_LP_OPTIONS;

       printk(KERN_INFO"nand_get_flash_type 4, chip->options = 0x%x.\n",chip->options);

 

nand_get_flash_type 1,chip->options = 0x10200.

nand_get_flash_type 2,chip->options = 0x10000.

nand_get_flash_type 3,chip->options = 0x1011c.

nand_get_flash_type 4,chip->options = 0x10101.

 

问题出在这里,红色的代码!

/* Mask to zero out thechip options, which come from the id table */

#defineNAND_CHIPOPTIONS_MSK (0x0000ffff &~NAND_NO_AUTOINCR)

/* Chip can not autoincrement pages */

#define NAND_NO_AUTOINCR  0x00000001

 

找到问题了,解决办法就有了,注释掉红色的那行代码,就是他把NAND_NO_SUBPAGE_WRITE给丢掉了。

//chip->options &=~NAND_CHIPOPTIONS_MSK;

再重新编译下载kernel,问题搞定了!

再次启动开发板,加载ubi,一切正常了。

root@dm368-evm:/# ubiattach/dev/ubi_ctrl -m 3

UBI: attaching mtd3 to ubi0

UBI: physical eraseblock size:   131072 bytes (128 KiB)

UBI: logical eraseblock size:    126976 bytes

UBI: smallest flash I/O unit:    2048

UBI: VID header offset:          2048 (aligned 2048)

UBI: data offset:                4096

UBI: attached mtd3 to ubi0

UBI: MTD device name:            "filesystem1"

UBI: MTD device size:            512 MiB

UBI: number of good PEBs:        4096

UBI: number of bad PEBs:         0

UBI: max. allowed volumes:       128

UBI: wear-leveling threshold:    4096

UBI: number of internal volumes: 1

UBI: number of user volumes:     1

UBI: available PEBs:             3639

UBI: total number of reserved PEBs:457

UBI: number of PEBs reserved for badPEB handling: 40

UBI: max/mean erase counter: 2/1

UBI: image sequence number: 0

UBI: background thread"ubi_bgt0d" started, PID 1483

UBI device number 0, total 4096 LEBs(520093696 bytes, 496.0 MiB), available 3639 LEBs (462065664 bytes, 440.7 MiB),LEB size 126976 bytes (124.0 KiB)

 

root@dm368-evm:/# mount -tubifs  ubi0_0 /mnt/nand/ -o sync

UBIFS: mounted UBI device 0, volume0, name "rootfs"

UBIFS: file system size:   51171328 bytes (49972 KiB, 48 MiB, 403 LEBs)

UBIFS: journal size:       2539520 bytes (2480 KiB, 2 MiB, 20 LEBs)

UBIFS: media format:       w4/r0 (latest is w4/r0)

UBIFS: default compressor: lzo

UBIFS: reserved for root:  2416947 bytes (2360 KiB)

root@dm368-evm:/# df

Filesystem           1K-blocks      Used Available Use% Mounted on

/dev/root             39544232  16239820 21295632  43% /

none                      1024        24     1000   2% /dev

tmpfs                    16384        20    16364   0% /var/volatile

tmpfs                    21760         0    21760   0% /dev/shm

tmpfs                    16384         0    16384   0% /media/ram

ubi0_0                   45528      1528    41640   4% /mnt/nand

 

最后,总结下,就是要禁止nand flash驱动里面的subpage write,让 chip->subpagesize == mtd->writesize 就好了。

这是我的解决办法。如果有人要使用subpage write,那么一定要保证你的读写逻辑是正确的,要么不用ecc,要么各个subpage的ecc都应是正确的。

文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章: 没有了
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
    DM368移植tcpdump
    TI xDAIS的深入理解 推荐阅读
    appro dm368ipnc nandwriter…
    移植Open SSH到DM368 IPNC中…
    静态库是不安全的 appro aew…
    移植gdb到DM368 IPNC中 linu…
    DM368 ipnc 重写架构中的swo…
    关于APPRO DM368 IPNC使用XD…
    uboot change based on DM36…
    MII/MDIO接口详解
      网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    站长:61 湘ICP备13001086号-2