SPI ハードウェア CRC 回路の MMC/SD カードへの応用 (3)
前回述べたように、実際の STM32 の SPI モジュールのハードウェア CRC 計算回路で求まるのは、8 ビットの「0」を追加した入力メッセージに対する剰余ですが、それについては後に回し、まず、定義通りの場合について考えます。
40 ビットの入力メッセージに 7 ビットの「0」を追加し、47 ビットとした入力メッセージ多項式を 8 次の生成多項式で割った余りの多項式を「r8_47(x)」として、下の式で定義します。
r8_47(x) = (x7・M(x)) mod (x8 + x7 + x4 + x3 + x + 1)
これは、47 ビットの入力メッセージを下図の原理的な回路で計算したものに相当します。
「r8_47(x)」から、求める CRC-7 の値「r7_47(x)」を求めるのは簡単で、単に「r8_47(x)」を CRC-7 の生成多項式 (x7 + x3 + 1) で割って余りの多項式を求めれば良いのです。
式で表現すれば、
r8_47(x) = q(x)・(x7 + x3 + 1) + r7_47(x)
となります。
ここで、商 q(x) の値は「0」か「1」です。
r8_47(x) は 8 次の多項式で割った余りなので、その次数は 7 以下となります。 したがって、7 次の多項式 (x7 + x3 + 1) で割れるかどうかは、r8_47(x) の 7 次の項の係数を見れば判定できます。
7 次の項の係数が「1」なら割れて、「0」なら割れません。
係数が「0」で、割れない場合には商 q(x) はゼロですから、
r8_47(x) = r7_47(x)
となり、8 次の多項式で割った余り r8_47(x) そのものが目的の CRC-7 の値となっています。
7 次の項の係数が「1」で、割れる場合には商 q(x) は 1 ですから、
r7_47(x) = r8_47(x) - (x7 + x3 + 1)
となります。
ここで、この演算は GF(2)、つまり、元が「0」と「1」しかない有限体上に係数を持つ多項式の演算ですから、「加算」と「減算」は同じ演算となり、具体的には「エクスクルーシブ OR」で実現されます。
以上の「補正」手続きを C 言語風に表現すると、8 次の多項式でメッセージ多項式を割った余りを保持している変数を「crc_value」として、
// CRC-7: g(x) = x**7 + x**3 + 1 // = {7, 3, 0} // = 0x89 // = 0b10001001 #define GX_CRC7 (0x89) if (0x80 & crc_value) { crc_value ^= GX_CRC7; }
のようになります。
このプログラムと、10 月 9 日付けの記事のプログラムとでは、「1」かどうかを検査するビット位置が b7 か b0 かという違いがあります。
それは、入力メッセージに追加する「0」の数が 7 個か 8 個かの違いに起因するのですが、その話は次回に回します。