让YAFFS支持MLC

    潜水多年,第一次发文,错误之处,欢迎指正。(zengzhaoxiu@163.com)

    以下是两年前的一个项目里的部分,现讲述出来,希望对大家有所帮助。本文为原创,转贴请注明出处。

 

    YAFFS的BLOCK的管理方式是和MLC兼容的,但是TAG ECC还是早期的HAMMING ECC,只支持1-Bit纠错。下面以4-Bits ECC MLC为例简单介绍让YAFFS支持MLC的方法,本例需要使用kernel里面的ReedSolomon Lib。

 

    第一步:在Config.in里加多两个配置选项,如下:

 

config YAFFS_TAGS_ECC_RS

  bool "Use Reed Solomon ECC algorithm for tags"

  depends on YAFFS_FS2

  default y

 

config YAFFS_TAGS_ECC_CORRECTABLE

  int "Maximum number of errors can be corrected (4 or 8)"

  depends on YAFFS_TAGS_ECC_RS

  default "4"

 

 

    第二步:修改yaffs_ecc.h

......

 

#include "yportenv.h"

 

typedef struct {

#if !defined(CONFIG_YAFFS_TAGS_ECC_RS)

  unsigned char colParity;

  unsigned lineParity;

  unsigned lineParityPrime;

#else

 unsigned char parity[CONFIG_YAFFS_TAGS_ECC_CORRECTABLE*2];

#endif

} yaffs_ECCOther;

......

 

    第三步:修改yaffs_ecc.c

在yaffs_ECCCalculateOther函数体之前添加

#if !defined(CONFIG_YAFFS_TAGS_ECC_RS)

 

在yaffs_ECCCorrectOther函数体之后添加

 

#include <linux/rslib.h>

 

extern struct rs_control* yaffs_ECCOther_RS;

 

static const u8 RS_CODE_FIX[CONFIG_YAFFS_TAGS_ECC_CORRECTABLE*2] =

{

#if CONFIG_YAFFS_TAGS_ECC_CORRECTABLE == 4

    ~210, ~158, ~253, ~241, ~98, ~165, ~203, ~28,

#elif CONFIG_YAFFS_TAGS_ECC_CORRECTABLE == 8

    ~44, ~47, ~153, ~112, ~7, ~40, ~91, ~101, ~115, ~207, ~59, ~61, ~210, ~138, ~180, ~202,

#else

#error "Only 4 or 8 is valid!"

#endif

};

 

void yaffs_ECCCalculateOther(const unsigned char *input, unsigned nBytes,

                             yaffs_ECCOther * eccOther)

{

    uint16_t par[CONFIG_YAFFS_TAGS_ECC_CORRECTABLE*2];

    int i;

 

    /* Initialize the parity buffer */

    memset(par, 0, CONFIG_YAFFS_TAGS_ECC_CORRECTABLE*2*sizeof(uint16_t));

 

    encode_rs8(yaffs_ECCOther_RS, input, nBytes, par, 0);

 

    for (i = 0; i < CONFIG_YAFFS_TAGS_ECC_CORRECTABLE*2; i++)

        eccOther->parity[i] = par[i] ^ RS_CODE_FIX[i];

}

 

int yaffs_ECCCorrectOther(unsigned char *input, unsigned nBytes,

                          yaffs_ECCOther * read_ecc, const yaffs_ECCOther * unused)

{

    uint16_t par[CONFIG_YAFFS_TAGS_ECC_CORRECTABLE*2];

    int i, numerr;

 

    for (i = 0; i < CONFIG_YAFFS_TAGS_ECC_CORRECTABLE*2; i++)

        par[i] = read_ecc->parity[i] ^ RS_CODE_FIX[i];

 

    numerr = decode_rs8(yaffs_ECCOther_RS, input, par, nBytes, NULL, 0, NULL, 0, NULL);

    return (numerr > 0) - (numerr < 0);

}

 

#endif

关于RS_CODE_FIX数组的说明:数组内容是sizeof(yaffs_PackedTags2TagsPart)个0xFF生成的RS Code,用这个数组的目的是保证空的OOB不会被认为是错误的TAG。

 

    第四步:修改yaffs_packedtags2.c,因为RS ECC在做Correct时是不需要再计算数据ECC的

在yaffs_UnpackTags2函数里,在yaffs_ECCCalculateOther调用前后分别加上

#if !defined(CONFIG_YAFFS_TAGS_ECC_RS)

......

#endif

 

    第五步:在yaffs_fs.c里,加上RSlib的部分

在文件开头部分的适当位置加上

#if defined(CONFIG_YAFFS_TAGS_ECC_RS)

#include <linux/rslib.h>

struct rs_control* yaffs_ECCOther_RS;

#endif

 

在init_yaffs_fs函数的结尾部分加上

#if defined(CONFIG_YAFFS_TAGS_ECC_RS)

  /* 1+x^2+x^3+x^4+x^8 */

  yaffs_ECCOther_RS = init_rs(8, 0x11D, 1, 1, CONFIG_YAFFS_TAGS_ECC_CORRECTABLE*2);

#endif

 

在exit_yaffs_fs函数的结尾部分加上

#if defined(CONFIG_YAFFS_TAGS_ECC_RS)

 free_rs(yaffs_ECCOther_RS);

#endif

 

至此,支持MLC的yaffs已经OK了。关于mkyaffsimage部分的修改,在此略过。

对于硬件ECC单元的支持,参照上例改动也是很简单的。用于RTOS的修改也是很Easy的。

 

下次再讲述对kernel ReedSolomon Lib的优化。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值