潜水多年,第一次发文,错误之处,欢迎指正。(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的优化。