Reed-Solomon 庫程式設計介面¶
- 作者:
Thomas Gleixner
引言¶
通用 Reed-Solomon 庫提供編碼、解碼和糾錯功能。
Reed-Solomon 碼在通訊和儲存應用中用於確保資料完整性。
本文件旨在為希望利用該庫提供功能的開發者提供參考。
已知 Bug 和假設¶
無。
用法¶
本章提供瞭如何使用該庫的示例。
初始化¶
初始化函式 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);
編碼¶
編碼器根據給定的資料長度計算 Reed-Solomon 碼,並將結果儲存在奇偶校驗緩衝區中。請注意,在呼叫編碼器之前,必須初始化奇偶校驗緩衝區。
透過提供非零反轉掩碼,可以即時反轉擴充套件資料。擴充套件資料與掩碼進行異或操作。例如,這用於 FLASH ECC,其中全 0xFF 會反轉為全 0x00。全 0x00 的 Reed-Solomon 碼也是全 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);
結構體¶
本章包含 Reed-Solomon 庫中使用的與開發者相關的結構體的自動生成文件。
-
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原語元素,索引形式
iprim1 的第 prim 根,索引形式
gfpoly原語生成多項式
gffunc如果是非規範表示,用於生成欄位的函式
users此結構體的使用者
listRS 編解碼器列表的列表條目
-
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 fcrRS 碼生成多項式的第一個連續根,以索引形式表示
int prim生成多項式根的原語元素
int nrootsRS 碼生成多項式度數(根的數量)
描述
分配使用 GFP_KERNEL。
提供的公共函式¶
本章包含 Reed-Solomon 匯出函式的自動生成文件。
-
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 fcrRS 碼生成多項式的第一個連續根,以索引形式表示
int prim生成多項式根的原語元素
int nrootsRS 碼生成多項式度數(根的數量)
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 fcrRS 碼生成多項式的第一個連續根,以索引形式表示
int prim生成多項式根的原語元素
int nrootsRS 碼生成多項式度數(根的數量)
-
int encode_rs8(struct rs_control *rsc, uint8_t *data, int len, uint16_t *par, uint16_t invmsk)¶
計算資料值(8 位資料寬度)的奇偶校驗
引數
struct rs_control *rscRS 控制結構
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 *rscRS 控制結構
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 *rscRS 控制結構
uint16_t *data給定型別的資料欄位
int len資料長度
uint16_t *par奇偶校驗資料,必須由呼叫方初始化(通常全為 0)
uint16_t invmsk反轉資料掩碼(將與資料進行異或操作,而不是與奇偶校驗進行!)
資料陣列中的每個欄位最多包含符號大小的有效資料位。
-
int decode_rs16(struct rs_control *rsc, uint16_t *par, int len, uint16_t *s, int no_eras, int *eras_pos, uint16_t invmsk, uint16_t *corr)¶
解碼碼字(16 位資料寬度)
引數
struct rs_control *rscRS 控制結構
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 上儲存糾正位掩碼的緩衝區
資料陣列中的每個欄位最多包含符號大小的有效資料位。
注意
- rs_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