Chinaunix首页 | 论坛 | 博客
  • 博客访问: 480035
  • 博文数量: 100
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 955
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-21 09:30
文章分类

全部博文(100)

文章存档

2017年(1)

2016年(16)

2015年(83)

我的朋友

分类: 嵌入式

2015-06-27 11:04:40


点击(此处)折叠或打开

  1. /**
  2.  * nand_write_skip_bad:
  3.  *
  4.  * Write image to NAND flash.
  5.  * Blocks that are marked bad are skipped and the is written to the next
  6.  * block instead as long as the image is short enough to fit even after
  7.  * skipping the bad blocks. Due to bad blocks we may not be able to
  8.  * perform the requested write. In the case where the write would
  9.  * extend beyond the end of the NAND device, both length and actual (if
  10.  * not NULL) are set to 0. In the case where the write would extend
  11.  * beyond the limit we are passed, length is set to 0 and actual is set
  12.  * to the required length.
  13.  *
  14.  * @param nand     NAND device
  15.  * @param offset    offset in flash
  16.  * @param length    buffer length
  17.  * @param actual    set to size required to write length worth of
  18.  *            buffer or 0 on error, if not NULL
  19.  * @param lim        maximum size that actual may be in order to not
  20.  *            exceed the buffer
  21.  * @param buffer buffer to read from
  22.  * @param flags        flags modifying the behaviour of the write to NAND
  23.  * @return        0 in case of success
  24.  */

  25. int nand_write_skip_bad(nand_info_t *nand, loff_t offset, size_t *length,
  26.         size_t *actual, loff_t lim, u_char *buffer, int flags)
  27. {
  28.     int rval = 0, blocksize;
  29.     size_t left_to_write = *length;
  30.     size_t used_for_write = 0;
  31.     u_char *p_buffer = buffer;
  32.     int need_skip;

  33.     if (actual)
  34.         *actual = 0;

  35. #ifdef CONFIG_CMD_NAND_YAFFS
  36.     if (flags & WITH_YAFFS_OOB) {
  37.         if (flags & ~WITH_YAFFS_OOB)//if yaffs,disable other flag
  38.             return -EINVAL;

  39.         int pages;
  40.         pages = nand->erasesize / nand->writesize;
  41.         blocksize = (pages * nand->oobsize) + nand->erasesize;//块长度 = oob + erasesize
  42.         if (*length % (nand->writesize + nand->oobsize)) {    //长度非块长度整数倍,提示将写入不完全的页
  43.             printf("Attempt to write incomplete page"
  44.                 " in yaffs mode\n");
  45.             return -EINVAL;
  46.         }
  47.     }
  48. #endif


  49.     /*
  50.      * nand_write() handles unaligned, partial page writes.
  51.      *
  52.      * We allow length to be unaligned, for convenience in
  53.      * using the $filesize variable.
  54.      *
  55.      * However, starting at an unaligned offset makes the
  56.      * semantics of bad block skipping ambiguous (really,
  57.      * you should only start a block skipping access at a
  58.      * partition boundary). So don't try to handle that.
  59.      */
  60.     if ((offset & (nand->writesize - 1)) != 0) {
  61.         printf("Attempt to write non page-aligned data\n");//页不对齐,出错误返回
  62.         *length = 0;
  63.         return -EINVAL;
  64.     }

  65.     need_skip = check_skip_len(nand, offset, *length, &used_for_write);//计算含坏块后的写总长度,用used_for_write返回

  66.     if (actual)
  67.         *actual = used_for_write;

  68.     if (need_skip < 0) {//超出边界
  69.         printf("Attempt to write outside the flash area\n");
  70.         *length = 0;
  71.         return -EINVAL;
  72.     }

  73.     if (used_for_write > lim) {//超出写入限制
  74.         puts("Size of write exceeds partition or device limit\n");
  75.         *length = 0;
  76.         return -EFBIG;
  77.     }

  78.     if (!need_skip && !(flags & WITH_DROP_FFS)) {//没有坏块并且flag不是WITH_DROP_FFS参数,直接按length长度写入。此处有bug,还需排除WITH_YAFFS_OOB
  79.         rval = nand_write(nand, offset, length, buffer);
  80.         if (rval == 0)
  81.             return 0;

  82.         *length = 0;
  83.         printf("NAND write to offset %llx failed %d\n",
  84.             offset, rval);
  85.         return rval;
  86.     }

  87.     while (left_to_write > 0) {
  88.         size_t block_offset = offset & (nand->erasesize - 1);//获取块内偏移
  89.         size_t write_size, truncated_write_size;

  90.         WATCHDOG_RESET();

  91.         if (nand_block_isbad(nand, offset & ~(nand->erasesize - 1))) {//跳过一个坏块
  92.             printf("Skip bad block 0x%08llx\n",
  93.                 offset & ~(nand->erasesize - 1));
  94.             offset += nand->erasesize - block_offset;//如果offset是块对齐的bock_offset = 0,跳过一个坏块
  95.             continue;
  96.         }

  97.         if (left_to_write < (blocksize - block_offset))//写入长度不足一个块,
  98.             write_size = left_to_write;
  99.         else
  100.             write_size = blocksize - block_offset;//写入长度=块长度-块偏移,当第二次写数据时就能块对齐了

  101. #ifdef CONFIG_CMD_NAND_YAFFS
  102.         if (flags & WITH_YAFFS_OOB) {
  103.             int page, pages;
  104.             size_t pagesize = nand->writesize;
  105.             size_t pagesize_oob = pagesize + nand->oobsize;
  106.             struct mtd_oob_ops ops;

  107.             ops.len = pagesize;
  108.             ops.ooblen = nand->oobsize;
  109.             ops.mode = MTD_OPS_AUTO_OOB;
  110.             ops.ooboffs = 0;

  111.             pages = write_size / pagesize_oob;
  112.             for (page = 0; page < pages; page++) {
  113.                 WATCHDOG_RESET();

  114.                 ops.datbuf = p_buffer;
  115.                 ops.oobbuf = ops.datbuf + pagesize;

  116.                 rval = mtd_write_oob(nand, offset, &ops);
  117.                 if (rval != 0)
  118.                     break;

  119.                 offset += pagesize;
  120.                 p_buffer += pagesize_oob;
  121.             }
  122.         }
  123.         else
  124. #endif
  125.         {//不是YAFFS格式,执行以下代码
  126.             truncated_write_size = write_size;
  127. #ifdef CONFIG_CMD_NAND_TRIMFFS
  128.             if (flags & WITH_DROP_FFS)
  129.                 truncated_write_size = drop_ffs(nand, p_buffer,
  130.                         &write_size);
  131. #endif

  132.             rval = nand_write(nand, offset, &truncated_write_size,
  133.                     p_buffer);
  134.             offset += write_size;
  135.             p_buffer += write_size;
  136.         }
  137.         if (rval != 0) {
  138.             printf("NAND write to offset %llx failed %d\n",
  139.                 offset, rval);
  140.             *length -= left_to_write;
  141.             return rval;
  142.         }

  143.         left_to_write -= write_size;
  144.     }

  145.     return 0;
  146. }


阅读(3338) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~