里德-所罗门库编程接口¶
- 作者:
Thomas Gleixner
简介¶
通用里德-所罗门库提供编码、解码和纠错功能。
里德-所罗门码在通信和存储应用中用于确保数据完整性。
本文档提供给想要使用该库提供的功能的开发人员。
已知错误和假设¶
无。
用法¶
本章提供了如何使用该库的示例。
初始化¶
init 函数 init_rs 返回指向 rs 解码器结构的指针,该结构保存使用给定多项式进行编码、解码和纠错的必要信息。它要么使用现有的匹配解码器,要么创建一个新的解码器。在创建时,会创建用于快速编码/解码的所有查找表。该函数可能需要一段时间,因此请确保不要在关键代码路径中调用它。
/* the Reed Solomon control structure */
static struct rs_control *rs_decoder;
/* Symbolsize is 10 (bits)
* Primitive polynomial is x^10+x^3+1
* first consecutive root is 0
* primitive element to generate roots = 1
* generator polynomial degree (number of roots) = 6
*/
rs_decoder = init_rs (10, 0x409, 0, 1, 6);
编码¶
编码器计算给定数据长度的里德-所罗门码,并将结果存储在奇偶校验缓冲区中。请注意,必须在调用编码器之前初始化奇偶校验缓冲区。
通过提供非零反转掩码,可以动态反转扩展数据。扩展数据与掩码进行异或。这例如用于 FLASH ECC,其中所有 0xFF 反转为所有 0x00。所有 0x00 的里德-所罗门码是所有 0x00。该代码在存储到 FLASH 之前会被反转,使其也为 0xFF。这可以防止从已擦除的 FLASH 中读取导致 ECC 错误。
数据字节会动态扩展到给定的符号大小。目前不支持使用 != 8 的符号大小对连续比特流进行编码。如果有必要,实现此类功能应该不是什么大问题。
/* Parity buffer. Size = number of roots */
uint16_t par[6];
/* Initialize the parity buffer */
memset(par, 0, sizeof(par));
/* Encode 512 byte in data8. Store parity in buffer par */
encode_rs8 (rs_decoder, data8, 512, par, 0);
解码¶
解码器计算给定数据长度和接收到的奇偶校验符号上的伴随式,并纠正数据中的错误。
如果硬件解码器提供了伴随式,则会跳过伴随式计算。
可以通过向解码器提供校正模式缓冲区和错误位置缓冲区来抑制数据缓冲区的校正。解码器会将计算出的错误位置和校正位掩码存储在给定的缓冲区中。这对于使用奇怪的位排序方案的硬件解码器很有用。
数据字节会动态扩展到给定的符号大小。目前不支持使用 != 8 的符号大小对连续比特流进行解码。如果有必要,实现此类功能应该不是什么大问题。
使用伴随式计算进行解码,直接数据校正¶
/* Parity buffer. Size = number of roots */
uint16_t par[6];
uint8_t data[512];
int numerr;
/* Receive data */
.....
/* Receive parity */
.....
/* Decode 512 byte in data8.*/
numerr = decode_rs8 (rs_decoder, data8, par, 512, NULL, 0, NULL, 0, NULL);
使用硬件解码器给出的伴随式进行解码,直接数据校正¶
/* Parity buffer. Size = number of roots */
uint16_t par[6], syn[6];
uint8_t data[512];
int numerr;
/* Receive data */
.....
/* Receive parity */
.....
/* Get syndrome from hardware decoder */
.....
/* Decode 512 byte in data8.*/
numerr = decode_rs8 (rs_decoder, data8, par, 512, syn, 0, NULL, 0, NULL);
使用硬件解码器给出的伴随式进行解码,不进行直接数据校正。¶
注意:不需要将数据和接收到的奇偶校验数据提供给解码器。
/* Parity buffer. Size = number of roots */
uint16_t par[6], syn[6], corr[8];
uint8_t data[512];
int numerr, errpos[8];
/* Receive data */
.....
/* Receive parity */
.....
/* Get syndrome from hardware decoder */
.....
/* Decode 512 byte in data8.*/
numerr = decode_rs8 (rs_decoder, NULL, NULL, 512, syn, 0, errpos, 0, corr);
for (i = 0; i < numerr; i++) {
do_error_correction_in_your_buffer(errpos[i], corr[i]);
}
清理¶
如果调用方是解码器的最后一个用户,则函数 free_rs 会释放已分配的资源。
/* Release resources */
free_rs(rs_decoder);
结构¶
本章包含里德-所罗门库中使用且与开发人员相关的结构的自动生成文档。
-
struct rs_codec¶
rs 编解码器数据
定义:
struct rs_codec {
int mm;
int nn;
uint16_t *alpha_to;
uint16_t *index_of;
uint16_t *genpoly;
int nroots;
int fcr;
int prim;
int iprim;
int gfpoly;
int (*gffunc)(int);
int users;
struct list_head list;
};
成员
mm
每个符号的位数
nn
每个块的符号数 (= (1<<mm)-1)
alpha_to
对数查找表
index_of
反对数查找表
genpoly
生成器多项式
nroots
生成器根的数量 = 奇偶校验符号的数量
fcr
第一个连续根,索引形式
prim
本原元素,索引形式
iprim
1 的第 prim 个根,索引形式
gfpoly
本原生成器多项式
gffunc
生成字段的函数(如果是非规范表示)
users
此结构的用户
list
rs 编解码器列表的列表条目
-
struct rs_control¶
每个实例的 rs 控制结构
定义:
struct rs_control {
struct rs_codec *codec;
uint16_t buffers[];
};
成员
codec
此实例使用的编解码器
buffers
在调用 decode_rs() 时使用的内部临时缓冲区
-
struct rs_control *init_rs(int symsize, int gfpoly, int fcr, int prim, int nroots)¶
创建 RS 控制结构并初始化它
参数
int symsize
符号大小(位数)
int gfpoly
扩展的伽罗瓦域生成器多项式系数,其中第 0 个系数位于低位。该多项式必须是本原的;
int fcr
rs 代码生成器多项式的第一个连续根,以索引形式
int prim
用于生成多项式根的本原元素
int nroots
RS 代码生成器多项式的阶数(根的数量)
描述
分配使用 GFP_KERNEL。
提供的公共函数¶
本章包含导出的里德-所罗门函数的自动生成文档。
-
void free_rs(struct rs_control *rs)¶
释放 rs 控制结构
参数
struct rs_control *rs
调用方不再使用的控制结构
描述
释放控制结构。如果 rs 是关联编解码器的最后一个用户,也会释放该编解码器。
-
struct rs_control *init_rs_gfp(int symsize, int gfpoly, int fcr, int prim, int nroots, gfp_t gfp)¶
创建 RS 控制结构并初始化它
参数
int symsize
符号大小(位数)
int gfpoly
扩展的伽罗瓦域生成器多项式系数,其中第 0 个系数位于低位。该多项式必须是本原的;
int fcr
rs 代码生成器多项式的第一个连续根,以索引形式
int prim
用于生成多项式根的本原元素
int nroots
RS 代码生成器多项式的阶数(根的数量)
gfp_t gfp
内存分配标志。
-
struct rs_control *init_rs_non_canonical(int symsize, int (*gffunc)(int), int fcr, int prim, int nroots)¶
为具有非规范表示的字段分配 rs 控制结构
参数
int symsize
符号大小(位数)
int (*gffunc)(int)
指向生成下一个字段元素的函数的指针,如果给定 0,则为乘法单位元素。如果 gfpoly 为 0,则使用而不是 gfpoly
int fcr
rs 代码生成器多项式的第一个连续根,以索引形式
int prim
用于生成多项式根的本原元素
int nroots
RS 代码生成器多项式的阶数(根的数量)
-
int encode_rs8(struct rs_control *rsc, uint8_t *data, int len, uint16_t *par, uint16_t invmsk)¶
计算数据值的奇偶校验(8 位数据宽度)
参数
struct rs_control *rsc
rs 控制结构
uint8_t *data
给定类型的数据字段
int len
数据长度
uint16_t *par
奇偶校验数据,必须由调用方初始化(通常全部为 0)
uint16_t invmsk
反转数据掩码(将与数据进行异或运算)
奇偶校验使用 uint16_t 数据类型以支持大于 8 的符号大小。调用代码必须自行处理存储的校正子结果的编码。
-
int decode_rs8(struct rs_control *rsc, uint8_t *data, uint16_t *par, int len, uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, uint16_t *corr)¶
解码码字(8 位数据宽度)
参数
struct rs_control *rsc
rs 控制结构
uint8_t *data
给定类型的数据字段
uint16_t *par
接收到的奇偶校验数据字段
int len
数据长度
uint16_t *s
校正子数据字段,必须是索引形式(如果为 NULL,则计算校正子)
int no_eras
擦除的数量
int *eras_pos
擦除的位置,可以为 NULL
uint16_t invmsk
反转数据掩码(将与数据进行异或运算,而不是与奇偶校验!)
uint16_t *corr
用于存储 eras_pos 上校正位掩码的缓冲区
校正子和奇偶校验使用 uint16_t 数据类型以支持大于 8 的符号大小。调用代码必须在调用此代码之前处理校正子结果的解码和接收到的奇偶校验。
注意
- rs_control 结构体 rsc 包含用于
解码的缓冲区,因此调用者必须确保解码器调用是串行化的。
返回已更正的符号数,或者对于无法纠正的错误返回 -EBADMSG。计数包括奇偶校验中的错误。
-
int encode_rs16(struct rs_control *rsc, uint16_t *data, int len, uint16_t *par, uint16_t invmsk)¶
计算数据值(16 位数据宽度)的奇偶校验
参数
struct rs_control *rsc
rs 控制结构
uint16_t *data
给定类型的数据字段
int len
数据长度
uint16_t *par
奇偶校验数据,必须由调用方初始化(通常全部为 0)
uint16_t invmsk
反转数据掩码(将与数据进行异或运算,而不是与奇偶校验!)
数据数组中的每个字段都包含最多符号大小的有效数据位。
-
int decode_rs16(struct rs_control *rsc, uint16_t *data, uint16_t *par, int len, uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, uint16_t *corr)¶
解码码字(16 位数据宽度)
参数
struct rs_control *rsc
rs 控制结构
uint16_t *data
给定类型的数据字段
uint16_t *par
接收到的奇偶校验数据字段
int len
数据长度
uint16_t *s
校正子数据字段,必须是索引形式(如果为 NULL,则计算校正子)
int no_eras
擦除的数量
int *eras_pos
擦除的位置,可以为 NULL
uint16_t invmsk
反转数据掩码(将与数据进行异或运算,而不是与奇偶校验!)
uint16_t *corr
用于存储 eras_pos 上校正位掩码的缓冲区
数据数组中的每个字段都包含最多符号大小的有效数据位。
注意
- rc_control 结构体 rsc 包含用于
解码的缓冲区,因此调用者必须确保解码器调用是串行化的。
返回已更正的符号数,或者对于无法纠正的错误返回 -EBADMSG。计数包括奇偶校验中的错误。
鸣谢¶
用于编码和解码的库代码由 Phil Karn 编写。
Copyright 2002, Phil Karn, KA9Q
May be used under the terms of the GNU General Public License (GPL)
包装函数和接口由 Thomas Gleixner 编写。
许多用户提供了错误修复、改进和测试方面的帮助。 非常感谢。
以下人员为本文档做出了贡献
Thomas Gleixnertglx@linutronix.de