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

全部博文(100)

文章存档

2017年(1)

2016年(16)

2015年(83)

我的朋友

分类: 嵌入式

2015-09-19 18:17:28


点击(此处)折叠或打开

  1. static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
  2.                 uint8_t *buf, int oob_required, int page)
  3. {
  4.     int i, eccsize = chip->ecc.size;
  5.     int eccbytes = chip->ecc.bytes;
  6.     int eccsteps = chip->ecc.steps;
  7.     uint8_t *p = buf;
  8.     uint8_t *ecc_calc = chip->buffers->ecccalc;
  9.     uint8_t *ecc_code = chip->buffers->ecccode;
  10.     uint32_t *eccpos = chip->ecc.layout->eccpos;

  11.     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  12.         chip->ecc.hwctl(mtd, NAND_ECC_READ);
  13.         chip->read_buf(mtd, p, eccsize);
  14.         chip->ecc.calculate(mtd, p, &ecc_calc[i]);//每512字节,读出硬件ecc字节,存放到ecc_calc,例如8bitecc,每次读取13字节,i+=13,循环4次
  15.     }
  16.     chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);

  17.     for (i = 0; i < chip->ecc.total; i++)
  18.         ecc_code[i] = chip->oob_poi[eccpos[i]];//读出OOB区域的ecc数据,存放到ecc_code,例如8bitecc,读取13*4=52字节

  19.     eccsteps = chip->ecc.steps;
  20.     p = buf;

  21.     for (i = 0 ; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  22.         int stat;

  23.         stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);//8bitecc是通过硬件完成的,所以校验函数应该放这里,而是每次写512字节时就进行校验
  24.         if (stat < 0)
  25.             mtd->ecc_stats.failed++;
  26.         else
  27.             mtd->ecc_stats.corrected += stat;
  28.     }
  29.     return 0;
  30. }

  31. /**
  32.  * nand_write_page_hwecc - [REPLACEABLE] hardware ECC based page write function
  33.  * @mtd: mtd info structure
  34.  * @chip: nand chip info structure
  35.  * @buf: data buffer
  36.  * @oob_required: must write chip->oob_poi to OOB
  37.  */
  38. static int nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
  39.                  const uint8_t *buf, int oob_required)
  40. {
  41.     int i, eccsize = chip->ecc.size;
  42.     int eccbytes = chip->ecc.bytes;
  43.     int eccsteps = chip->ecc.steps;
  44.     uint8_t *ecc_calc = chip->buffers->ecccalc;
  45.     const uint8_t *p = buf;
  46.     uint32_t *eccpos = chip->ecc.layout->eccpos;

  47.     for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
  48.         chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
  49.         chip->write_buf(mtd, p, eccsize);
  50.         chip->ecc.calculate(mtd, p, &ecc_calc[i]);
  51.     }

  52.     for (i = 0; i < chip->ecc.total; i++)
  53.         chip->oob_poi[eccpos[i]] = ecc_calc[i];

  54.     chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);

  55.     return 0;
  56. }

  57. /**
  58.  * nand_bch_correct_data - [NAND Interface] Detect and correct bit error(s)
  59.  * @mtd:    MTD block structure
  60.  * @buf:    raw data read from the chip
  61.  * @read_ecc:    ECC from the chip
  62.  * @calc_ecc:    the ECC calculated from raw data
  63.  *
  64.  * Detect and correct bit errors for a data byte block
  65.  */
  66. int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
  67.              unsigned char *read_ecc, unsigned char *calc_ecc)
  68. {
  69.     const struct nand_chip *chip = mtd->priv;
  70.     struct nand_bch_control *nbc = chip->ecc.priv;
  71.     unsigned int *errloc = nbc->errloc;
  72.     int i, count;

  73.     count = decode_bch(nbc->bch, NULL, chip->ecc.size, read_ecc, calc_ecc,
  74.              NULL, errloc);
  75.     if (count > 0) {
  76.         for (i = 0; i < count; i++) {
  77.             if (errloc[i] < (chip->ecc.size*8))
  78.                 /* error is located in data, correct it */
  79.                 buf[errloc[i] >> 3] ^= (1 << (errloc[i] & 7));
  80.             /* else error in ecc, no action needed */

  81.             MTDDEBUG(MTD_DEBUG_LEVEL0, "%s: corrected bitflip %u\n",
  82.              __func__, errloc[i]);
  83.         }
  84.     } else if (count < 0) {
  85.         printk(KERN_ERR "ecc unrecoverable error\n");
  86.         count = -1;
  87.     }
  88.     return count;
  89. }

  90. /**
  91.  * nand_correct_data - [NAND Interface] Detect and correct bit error(s)
  92.  * @mtd:    MTD block structure
  93.  * @dat:    raw data read from the chip
  94.  * @read_ecc:    ECC from the chip
  95.  * @calc_ecc:    the ECC calculated from raw data
  96.  *
  97.  * Detect and correct a 1 bit error for 256 byte block
  98.  */
  99. int nand_correct_data(struct mtd_info *mtd, u_char *dat,
  100.          u_char *read_ecc, u_char *calc_ecc)
  101. {
  102.     uint8_t s0, s1, s2;

  103. #ifdef CONFIG_MTD_NAND_ECC_SMC
  104.     s0 = calc_ecc[0] ^ read_ecc[0];
  105.     s1 = calc_ecc[1] ^ read_ecc[1];
  106.     s2 = calc_ecc[2] ^ read_ecc[2];
  107. #else
  108.     s1 = calc_ecc[0] ^ read_ecc[0];
  109.     s0 = calc_ecc[1] ^ read_ecc[1];
  110.     s2 = calc_ecc[2] ^ read_ecc[2];
  111. #endif
  112.     if ((s0 | s1 | s2) == 0)
  113.         return 0;

  114.     /* Check for a single bit error */
  115.     if( ((s0 ^ (s0 >> 1)) & 0x55) == 0x55 &&
  116.      ((s1 ^ (s1 >> 1)) & 0x55) == 0x55 &&
  117.      ((s2 ^ (s2 >> 1)) & 0x54) == 0x54) {

  118.         uint32_t byteoffs, bitnum;

  119.         byteoffs = (s1 << 0) & 0x80;
  120.         byteoffs |= (s1 << 1) & 0x40;
  121.         byteoffs |= (s1 << 2) & 0x20;
  122.         byteoffs |= (s1 << 3) & 0x10;

  123.         byteoffs |= (s0 >> 4) & 0x08;
  124.         byteoffs |= (s0 >> 3) & 0x04;
  125.         byteoffs |= (s0 >> 2) & 0x02;
  126.         byteoffs |= (s0 >> 1) & 0x01;

  127.         bitnum = (s2 >> 5) & 0x04;
  128.         bitnum |= (s2 >> 4) & 0x02;
  129.         bitnum |= (s2 >> 3) & 0x01;

  130.         dat[byteoffs] ^= (1 << bitnum);

  131.         return 1;
  132.     }

  133.     if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1)
  134.         return 1;

  135.     return -EBADMSG;
  136. }

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