• 検索結果がありません。

dsPIC33/PIC24 Family Reference Manual, 32-Bit Programmable Cyclic Redundancy Check (CRC)

N/A
N/A
Protected

Academic year: 2021

シェア "dsPIC33/PIC24 Family Reference Manual, 32-Bit Programmable Cyclic Redundancy Check (CRC)"

Copied!
36
0
0

読み込み中.... (全文を見る)

全文

(1)

32 ビット プログラマブル巡回冗長検査 (CRC)

ハイライト

本セクションは以下の主要項目を記載しています。

1.0

はじめに ...2

2.0

モジュールの概要 ...

3

3.0

CRC レジスタ ...4

4.0

CRC エンジン ... 10

5.0

制御ロジック ...11

6.0

プログラマブル

CRC モジュールの利点 ... 20

7.0

CRC モジュールのアプリケーション ... 20

8.0

省電力モードの動作 ...

31

9.0

レジスタマップ ...

32

10.0 関連アプリケーション ノート ... 33

11.0 改訂履歴 ... 34

注意: この日本語版文書は参考資料としてご利用ください。最新情報は必ずオリジ ナルの英語版をご参照願います。

(2)

1.0

はじめに

dsPIC33/PIC24 の 32 ビット プログラマブル巡回冗長検査 (CRC) モジュールは、ソフトウェア

で構成できる

CRC チェックサム ジェネレータです。チェックサムとは、複数バイトを格納し

た個々のメッセージまたはデータブロックに関連付けられる固有の数値です。通信用のデータ

パケットにせよメモリに保存したデータブロックにせよ、チェックサム等の情報は、それらの

データを処理する前の検証に役立ちます。最も単純な方法として、メッセージ内のデータバイ

トを全て加算する事でチェックサムを求める事ができます。しかし、バイト単位で反転したり

並び順を入れ換えたりしてメッセージが改変された場合、このような方法では誤りを検出でき

ません。また、メッセージの

NULL バイトが追加された場合も検出できません。

CRC はこのような単純な方法に比べると複雑ですが、信頼性の高い誤り検出アルゴリズムです。

CRC アルゴリズムはメッセージをバイナリビット ストリームとして扱い、これを決められたバ

イナリ値で除算した時の 余りをチェックサムとみなします。通常の除算と同様に、CRC 計算も

反復処理です。ただし、これらの演算は

mod2 によるモジュロ演算で実行されるという点が異

なります。例えば、除算は

XOR 演算 ( すなわちキャリーなしの減算 ) に置き換えられます。CRC

アルゴリズムは、全ての計算に多項式の項を使います。除数、被除数、余りのバイナリ値の各

桁は、多項式の各項の係数に割り当てられます。例えば、値

25h (11001) を下式のように表現

します。

1-1:

CRC 計算では、まず適当な除数を選択します。この除数は生成多項式と呼ばれます。生成多項

式の選択によって

CRC の誤り検出能力が異なるため、アプリケーションに合わせて適切な長

さの生成多項式を選択する必要があります。多くのアプリケーションで広く一般的に用いられ

る生成多項式はいくつか存在しますが、本書ではそのような特定の多項式の誤り検出能力につ

いては取り上げません。

CRC 演算は反復処理であるため、ソフトウェアで実装するとかなりの CPU 帯域幅を使います。

dsPIC33/PIC24 が内蔵する CRC ハードウェア モジュールは、ソフトウェアによる構成が可能

であり、最小限のソフトウェア オーバーヘッドで高速な CRC チェックサム計算が可能です。

プログラマブル

CRC ジェネレータを使うと、各種の通信およびセキュリティ アプリケーショ

ン向けにチェックサムを高速に生成するハードウェア実装が可能です。この

CRC ジェネレー

タは下記の特長を備えます。

• プログラマブルな最大 32 ビットの CRC 多項式

• 選択可能なシフト方向 ( リトル エンディアン / ビッグ エンディアン )

• 独立したデータ長と多項式長

• 設定可能な割り込み出力

• データ FIFO

(1 * x

4

) + (1 * x

3

) + (0 * x

2

) + (0 * x

1

) + (1 * x

0

) または x

4

+ x

3

+ x

0

(3)

2.0

モジュールの概要

dsPIC33/PIC24 が内蔵するプログラマブル CRC ジェネレータ モジュールは、おおまかに 2 つ

の部分

( 制御ロジックと CRC エンジン ) に分けられます。制御ロジックはレジスタ インター

フェイス、FIFO、割り込みジェネレータ、CRC エンジン インターフェイスを備えます。CRC

エンジンは

CRC カリキュレータを備え、これは XOR 機能を備えたシリアルシフタを使って実

装されます。

2-1

に、概略ブロック図を示します。

2-1:

プログラマブル

CRC ジェネレータの概略ブロック図

Shift Buffer CRC Shift Engine CRCWDATH CRCWDATL LENDIAN 1 CRCISEL 1 0

FIFO Empty Event

Shift Complete Set CRCIF 2 * FCYShift Clock CRCWDATH CRCWDATL 0 Event Variable FIFO (4x32, 8x16 or 16x8)

(4)

3.0

CRC レジスタ

このセクションでは、

CRC モジュール関連のレジスタについて説明します。このモジュールで

8 つのレジスタを使います。これらは特殊機能レジスタ (SFR) として dsPIC33/PIC24 のデー

RAM 空間に割り当てられています。

• CRCCON1 (CRC 制御レジスタ 1)

• CRCCON2 (CRC 制御レジスタ 2)

• CRCXORL (CRC XOR LOW レジスタ )

• CRCXORH (CRC XOR HIGH レジスタ )

• CRCDATL (CRC データ LOW レジスタ )

• CRCDATH (CRC データ HIGH レジスタ )

• CRCWDATL (CRC シフト LOW レジスタ )

• CRCWDATH (CRC シフト HIGH レジスタ )

CRCCON1 (

レジスタ

3-1

) および CRCCON2 (

レジスタ

3-2

) レジスタは、モジュール動作の

制御と各種設定に使います。CRCXORL/H レジスタ (

レジスタ

3-3

レジスタ

3-4

) は、CRC

計算で使う多項式の項を選択します。

CRCDATL/H および CRCWDATL/H レジスタは、それぞ

2 ワード入力データ用および CRC 処理後の出力データ用バッファとして機能するレジスタ

ペアです。

(5)

レジスタ

3-1:

CRCCON1: CRC 制御レジスタ 1

R/W-0

U-0

R/W-0

R-0

R-0

R-0

R-0

R-0

CRCEN

-

CSIDL

VWORD4

VWORD3

VWORD2

VWORD1

VWORD0

bit 15

bit 8

R-0

R-1

R/W-0

R/W-0

R/W-0

U-0

U-0

U-0

CRCFUL

CRCMPT

CRCISEL

CRCGO

LENDIAN

-

-

-bit 7

bit 0

凡例

:

R = 読み出し可能ビット

W = 書き込み可能ビット

U = 未実装ビット、「0」として読み出し

-n = POR 時の値

「1」 = ビットはセット

「0」 = ビットはクリア

x = ビットは未知

bit 15

CRCEN: CRC イネーブルビット

1 = モジュールを有効にする

0 = モジュールを無効にする

bit 14

未実装

:「0」として読み出し

bit 13

CSIDL: CRC Stop-in-Idle モードビット

1 = デバイスがアイドルに移行するとモジュールの動作を停止する

0 = アイドル中もモジュールの動作を継続する

bit 12-8

VWORD<4:0>: カウンタ値ビット

FIFO 内の有効ワード数を示します。DWIDTH<4:0>  7 (8 ビット幅以下のデータワード ) の場合、最

大値は

16 です。DWIDTH<4:0> 15(9 ~ 16 ビット幅のデータワード ) の場合、最大値は 8 です。

DWIDTH<4:0> 31(17 ~ 32 ビット幅のデータワード ) の場合、最大値は 4 です。

bit 7

CRCFUL: CRC FIFO フルビット

1 = FIFO はフルである

0 = FIFO はフルではない

bit 6

CRCMPT: CRC FIFO エンプティビット

1 = FIFO はエンプティである

0 = FIFO はエンプティではない

bit 5

CRCISEL: CRC 割り込み選択ビット

1 = FIFO のエンプティ時 ( データの最終ワードが CRC でまだシフト中 ) に割り込みを生成する

0 = シフトの完了時に割り込みを生成する (FIFO はエンプティであり、かつシフトバッファからシフ

トされるデータはない

)

bit 4

CRCGO: CRC 開始ビット

1 = CRC シリアルシフタの動作を開始する ( このビットがクリアされるとシフトを中止する )

0 = CRC シリアルシフタを停止する

bit 3

LENDIAN: データワードのリトル エンディアン コンフィグレーション ビット

1 = LSb を先頭にデータワードを CRC へシフトする ( リトル エンディアン )。入力データの順序を

反転する

0 = MSb を先頭にデータワードを CRC へシフトする ( ビッグ エンディアン )。入力データの順序を

反転しない

bit 2-0

未実装

:「0」として読み出し

(6)

レジスタ

3-2:

CRCCON2: CRC 制御レジスタ 2

U-0

U-0

U-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

-

-

-

DWIDTH4

DWIDTH3

DWIDTH2

DWIDTH1

DWIDTH0

bit 15

bit 8

U-0

U-0

U-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

-

-

-

PLEN4

PLEN3

PLEN2

PLEN1

PLEN0

bit 7

bit 0

凡例

:

R = 読み出し可能ビット

W = 書き込み可能ビット

U = 未実装ビット、「0」として読み出し

-n = POR 時の値

「1」 = ビットはセット

「0」 = ビットはクリア

x = ビットは未知

bit 15-13

未実装

:「0」として読み出し

bit 12-8

DWIDTH<4:0>: データワード幅コンフィグレーション ビット

データワードの幅を設定します

(「データワード幅 - 1」の値を指定 )。

bit 7-5

未実装

:「0」として読み出し

bit 4-0

PLEN<4:0>: 多項式長コンフィグレーション ビット

多項式の長さを設定します

(「多項式の長さ - 1」の値を指定 )。

(7)

レジスタ

3-3:

CRCXORL: CRC XOR LOW レジスタ

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

X15

X14

X13

X12

X11

X10

X9

X8

bit 15

bit 8

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

U-0

X7

X6

X5

X4

X3

X2

X1

-bit 7

bit 0

凡例

:

R = 読み出し可能ビット

W = 書き込み可能ビット

U = 未実装ビット、「0」として読み出し

-n = POR 時の値

「1」 = ビットはセット

「0」 = ビットはクリア

x = ビットは未知

bit 15-1

X<15:1>: 多項式の項 x

n

XOR イネーブルビット

bit 0

未実装

:「0」として読み出し

レジスタ

3-4:

CRCXORH: CRC XOR HIGH レジスタ

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

X31

X30

X29

X28

X27

X26

X25

X24

bit 15

bit 8

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

X23

X22

X21

X20

X19

X18

X17

X16

bit 7

bit 0

凡例

:

R = 読み出し可能ビット

W = 書き込み可能ビット

U = 未実装ビット、「0」として読み出し

-n = POR 時の値

1」 = ビットはセット

0」 = ビットはクリア

x = ビットは未知

bit 15-0

X<31:16>: 多項式の項 x

n

XOR イネーブルビット

(8)

レジスタ

3-5:

CRCDATL: CRC データ LOW レジスタ

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

DATA15

DATA14

DATA13

DATA12

DATA11

DATA10

DATA9

DATA8

bit 15

bit 8

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

DATA7

DATA6

DATA5

DATA4

DATA3

DATA2

DATA1

DATA0

bit 7

bit 0

凡例

:

R = 読み出し可能ビット

W = 書き込み可能ビット

U = 未実装ビット、「0」として読み出し

-n = POR 時の値

1」 = ビットはセット

0」 = ビットはクリア

x = ビットは未知

bit 15-0

DATA<15:0>: CRC 入力データビット

このレジスタへの書き込みは

FIFO に格納されます。このレジスタを読み出すと「0」が返されます。

レジスタ

3-6:

CRCDATH: CRC データ HIGH レジスタ

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

DATA31

DATA30

DATA29

DATA28

DATA27

DATA26

DATA25

DATA24

bit 15

bit 8

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

DATA23

DATA22

DATA21

DATA20

DATA19

DATA18

DATA17

DATA16

bit 7

bit 0

凡例

:

R = 読み出し可能ビット

W = 書き込み可能ビット

U = 未実装ビット、「0」として読み出し

-n = POR 時の値

1」 = ビットはセット

0」 = ビットはクリア

x = ビットは未知

bit 15-0

DATA<31:16>: CRC 入力データビット

このレジスタへの書き込みは

FIFO に格納されます。このレジスタを読み出すと「0」が返されます。

(9)

レジスタ

3-7:

CRCWDATL: CRC シフト LOW レジスタ

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

SDATA15

SDATA14

SDATA13

SDATA12

SDATA11

SDATA10

SDATA9

SDATA8

bit 15

bit 8

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

SDATA7

SDATA6

SDATA5

SDATA4

SDATA3

SDATA2

SDATA1

SDATA0

bit 7

bit 0

凡例

:

R = 読み出し可能ビット

W = 書き込み可能ビット

U = 未実装ビット、「0」として読み出し

-n = POR 時の値

「1」 = ビットはセット

「0」 = ビットはクリア

x = ビットは未知

bit 15-0

SDATA<15:0>: CRC シフトレジスタ ビット

このレジスタへの書き込みは、CRC 書き込みバスを介して CRC シフトレジスタに書き込まれます。

このレジスタからの読み出しは、CRC 読み出しバスを読み出します。

レジスタ

3-8:

CRCWDATH: CRC シフト HIGH レジスタ

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

SDATA31

SDATA30

SDATA29

SDATA28

SDATA27

SDATA26

SDATA25

SDATA24

bit 15

bit 8

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

R/W-0

SDATA23

SDATA22

SDATA21

SDATA20

SDATA19

SDATA18

SDATA17

SDATA16

bit 7

bit 0

凡例

:

R = 読み出し可能ビット

W = 書き込み可能ビット

U = 未実装ビット、「0」として読み出し

-n = POR 時の値

「1」 = ビットはセット

「0」 = ビットはクリア

x = ビットは未知

bit 15-0

DATA<31:16>: CRC シフトレジスタ ビット

このレジスタへの書き込みは、CRC 書き込みバスを介して CRC シフトレジスタに書き込まれます。

このレジスタからの読み出しは、

CRC 読み出しバスを読み出します。

(10)

4.0

CRC エンジン

4.1

汎用

CRC エンジン

CRC エンジンは、シリアルシフト式 CRC カリキュレータで、マルチプレクサの設定により

フィードフォワードおよびフィードバックする位置を設定変更できます。

4-1

に、

CRC シフ

トエンジンの簡略図を示します。

CRC アルゴリズムは、バイナリ除算の代わりに XOR 演算を使って計算処理を単純にします。

生成多項式の係数は、CRCXORL<15:1> と CRCXORH<31:16> ビットで設定します。ある

ビット位置に「1」を書き込むと、多項式内の対応する項の XOR 演算が有効になります。多

項式の長さは、CRCCON2 レジスタ (CRCCON2<4:0>) の PLEN<4:0> ビットで設定します。

PLEN<4:0> の値が示す多項式の長さに基づいてマルチプレクサを切り換え、フィードバック

を始めるタップ位置を指定します。

CRC 計算の結果は、CRC 読み出しバスを介してホールドレジスタを読み出す事で取得できます。

CRC 書き込みバスを介する CRC シフトレジスタへの直接書き込み経路も使えます。CPU は

CRCWDATL および CRCWDATH レジスタを介してこの経路にアクセスします。

4-1:

CRC シフトエンジンの詳細

CRCWDATH CRCWDATL Bit 0 X(0)(1) X(1)(1) Read/Write Bus Shift Buffer Data X(2)(1) X(n)(1) Note 1: シフトエンジンの各XOR 段はプログラマブルです。詳細は本文を参照してください。 2: 多項式の長さn は (PLEN<4:0> + 1) です。

(11)

5.0

制御ロジック

5.1

多項式インターフェイス

CRC モジュールには、32 ビットを使って最大で 32 次の CRC 多項式をプログラミングできます。

多項式の長さは計算式の最大次数に一致し、

PLEN<4:0> ビット (CRCCON2<4:0>) で選択します。

CRCXORL および CRCXORH レジスタは、どの指数項を計算式に含めるのかを設定します。特

定のビットをセットすると、そのビットに対応する指数項が多項式に含められます。これによ

り、CRC エンジンは対応するビットで XOR 演算を実行します。ビットをクリアすると、その

項の

XOR 演算は無効になります。以下に、16 ビットと 32 ビットの CRC 多項式の例を示します。

5-1:

これらの多項式を

CRC ジェネレータにプログラミングするには、レジスタの各ビットを

5-1

のように設定します。

5-1:

CRC の構成例 : 16 ビットと 32 ビットの多項式

多項式で使う項に対応するビットを「1」にセットしている事に注目してください ( 例 : X26 と

X23)。多項式は bit 0 の XOR 演算を常に必要とします。従って、X0 はドントケアです。多項

式の最上位ビット

(MSb) は計算に影響を与えないため「0」に設定してかまいません。

5.2

データ

インターフェイス

CRC モジュールは、CRC 計算用にユーザが定義した入力データ幅を確保します。入力データ

幅は、DWIDTH<4:0> ビット (CRCCON2<12:8>) を使って 1 ~ 32 ビットに設定できます。

入力データはCRCDATLおよびCRCDATHレジスタに格納されます。CRCDATLおよびCRCDATH

レジスタの幅は、DWIDTH<4:0> ビットの設定に従って設定されます。

データ幅が

16 ビット以下の場合、CRCDATL レジスタだけを使うため、CRCDATH レジスタ

への書き込みは全て無視されます。

データ幅が

16 ビットより大きい場合、CRCDATL と CRCDATH の両方のレジスタを使います。

この場合、先に下位

16 ビット ( 下位ワード ) を CRCDATL レジスタに書き込み、後から上位の

ビットを

CRCDATH レジスタに書き込む必要があります。

CRC 制御ビット

ビット値

16 ビット多項式

32 ビット多項式

PLEN<4:0>

01111

11111

X<31:16>

0000 0000 0000 0000

0000 0100 1100 0001

X<15:1>

0001 0000 0010 000x

0001 1101 1011 011x

Note:

データ幅が

8 ビット以下の場合、バイト操作によって入力データを CRCDATL レ

ジスタに書き込む必要があります。

x

16

+ x

12

+ x

5

+ 1

x

32

+ x

26

+ x

23

+ x

22

+ x

16

+ x

12

+ x

11

+ x

10

+ x

8

+ x

7

+ x

5

+ x

4

+ x

2

+ x + 1

(12)

5.3

データのシフト方向

シフト方向の設定には

LENDIAN ビット (CRCCON1<3>) を使います。既定値 (LENDIAN = 0)

の場合、

CRC モジュールは MSb を先頭に CRC エンジンを通してデータをシフトします。

LENDIAN を「1」にセットすると、CRC モジュールは LSb を先頭にデータをシフトします。

この設定により、ソフトウェアでのビット順序の反転によるオーバーヘッドなしで、各種通信

方式に対応できます。この動作はデータをエンジンにシフトインする方向だけを変更する事に

注意してください。

CRC 計算の結果は通常のままであり、反転されません。

PIC24 と dsPIC33 はリトル エンディアンのデバイスです。CRC モジュールをビッグ エンディ

アンに設定する場合

(LENDIAN = 0)、入力データのバイトとワードをアプリケーション コード

内でスワップしてから

CRCDAT レジスタに書き込む必要があります。

5.4

FIFO

CRC モジュールは可変データ幅の FIFO を備えます。データ幅は、DWIDTH<4:0> ビット

(CRCCON2<12:8>) で定義します。1 ~ 32 ビットの間で設定できます。FIFO 関連のロジック

には、

VWORD と呼ばれる 5 ビットカウンタ (VWORD<4:0> または CRCCON1<12:8>) が含ま

れます。VWORD<4:0> ビットの値は FIFO 内の新しいデータエレメントの数を示します。

FIFO は下記のように設定できます。

• DWIDTH<4:0>

7 (8 ビット幅以下のデータワード ) の場合、16 ワード段

• DWIDTH<4:0>

15 (9 ~ 16 ビット幅のデータワード ) の場合、8 ワード段

• DWIDTH<4:0>

31 (17 ~ 32 ビット幅のデータワード ) の場合、4 ワード段

CRC 計算前に、CPU は CRC の計算に使うデータを CRCDAT レジスタ経由で FIFO に書き込

む必要があります。CRCDAT レジスタを読み出すと常に 0 が返されます。

FIFO に 8 ビット以下のデータを格納する場合 :

データワード幅を

8 ビット以下に設定した場合、CRCDATL レジスタの下位または上位バイトの

どちらかに書き込むたびに

FIFO がインクリメントします。FIFO 書き込みの最小データ単位は

1 バイトです。16 ビットワードを 1 つ CRCDATL レジスタに書き込む場合、まず下位バイトが

FIFO に書き込まれた後に上位バイトが書き込まれます。

例えば、DWIDTH<4:0> が 5 の場合、データサイズは DWIDTH<4:0> + 1 つまり 6 です。このデー

タは

1 バイト (8 ビット ) データとして書き込まれ、モジュールは未使用の上位 2 ビットを無視し

ます。

CRCDATL レジスタにデータバイトを書き込むと、VWORD<4:0> ビット (CRCCON1< 12:8>)

の値が

1 つインクリメントします。

FIFO に 9 ~ 16 ビット幅のデータを格納する場合 :

9 ~ 16 ビットのデータワード幅を設定した場合、CRCDATL レジスタへの書き込み時に FIFO に

読み込まれます。

CRCDATH レジスタへの書き込みは全て無視されます。CRCDATL レジスタに

書き込むたびに、

VWORD<4:0> ビットの値がインクリメントします。

FIFO に 17 ~ 31 ビット幅のデータを格納する場合 :

データ幅が

16 ビットよりも大きい場合、CRCDATH レジスタに書き込むたびに VWORD<4:0>

ビットが

1 つインクリメントします。CRCDATH レジスタに上位ワードを書き込む前に、

CRCDATL レジスタに下位ワードを書き込む必要があります。

MSb からシフトインするには (LENDIAN = 0)、FIFO への格納時にソフトウェアでバイトとワー

ドのスワップを実行する必要があります。

5-1

5-2

5-3

に、各種データ幅に対する

FIFO の図解を示します。

シフトが全て終了

(FIFO がエンプティになり、CRC シフトエンジンがアイドルに移行 ) すれ

ば、

データの損失または

CRC結果の破壊なしにFIFO幅(DWIDTH<4:0>ビット)を変更できます。

Note:

CRCFUL ビットがセットされている時に CRCDATL および CRCDATH レジスタ

に新しいデータを書き込んでも、それらのデータは無視される事に注意してくだ

さい。

(13)

5-1:

FIFO に 8 ビット幅以下のデータを格納する場合

5-2:

FIFO に 9 ~ 16 ビット幅のデータを格納する場合

5-3:

FIFO に 17 ~ 32 ビット幅のデータを格納する場合

MOV.W W1, CRCDATL ; low byte is written first, then high byte MOV.W W2, CRCDATL ; low byte is written first, then high byte MOV.B W3, CRCDATL ; low byte only

MOV.B W4, CRCDATL ; low byte only MOV.B W5, CRCDATL ; low byte only MOV.B W6, CRCDATL ; low byte only W1 = 0x0201 W2 = 0x0403 W3 = 0x0005 W4 = 0x0006 W5 = 0x0007 W6 = 0x0008 Resulting FIFO:

Initial Conditions: Code Executed to Fill the FIFO:

Write Location Value

W6L 7 0x08 W5L 6 0x07 W4L 5 0x06 W3L 4 0x05 W2H 3 0x04 W2L 2 0x03 W1H 1 0x02 W1L 0 0x01 W1 = 0x0A01 W2 = 0x0B02 W3 = 0x0C03 W4 = 0x0D04

MOV.W W1, CRCDATL ; word MOV.B W2, CRCDATL ; low byte MOV.W W3, CRCDATL ; word MOV.W W4, CRCDATL ; word Initial Conditions: Code Executed to Fill the FIFO:

Note 1: 値の「-」は、FIFO に元々格納されていたデータが変更されなかった事を意味します。

Resulting FIFO:

Write Location Value

W4 3 0x0D04 W3 2 0x0C03 W2L 1 0x-02(1) W1 0 0x0A01 W1 = 0x0A01 W2 = 0x0B02 W3 = 0x0C03 W4 = 0x0D04

MOV.W W1, CRCDATL ; low word

MOV.W W2, CRCDATH ; high word, write to FIFO occurs here MOV.W W3, CRCDATL ; low word

MOV.W W4, CRCDATH ; high word, write to FIFO occurs here Initial Conditions: Code Executed to Fill the FIFO:

Word Width > 16 Bits and 32 Bits:

Write Location Value

W4, W3 1 0x0D040C03

(14)

5.5

CRC エンジン インターフェイス

5.5.1

FIFO から CRC シフトエンジン

FIFOからCRCシフトバッファへのデータ移動を開始するには、CRCGOビット(CRCCON1<4>)

をセットする必要があります。シリアルシフタは、

CRCGO = 1 かつ VWORD<4:0> の値が 0

より大きい場合、シフトバッファから

CRC シフトエンジンへのデータシフトを開始します。

LENDIAN = 0 の場合は MSb を先頭に、LENDIAN = 1 の場合は LSb を先頭に転送します。シフ

ト開始前に

CRCFUL ビットがセットされていた場合、VWORDx ビットが 1 つデクリメントし

た時にクリアされます。

FIFO 内のデータがシフトバッファに移動されるたびに、VWORD<4:0>

ビットが

1 つデクリメントします。シリアルシフタは VWORD<4:0> ビットが 0 に達するまで

シフトを続行し、0 になった時点で CRCMPT ビットをセットして FIFO がエンプティである事

を示します。CRC 計算中にユーザが CRCGO ビットをリセットすると、CRC シフトエンジン

CRCGO ビットがセットされるまで計算を停止します。

アプリケーションは、シフト動作の実行中に

FIFO に書き込む事ができます。その際、CRCFUL

ビットを監視する必要があります。CRCFUL ビットがセットされていなければ、FIFO にもう

1 ワード書き込む事ができます。VWORD<4:0> の読み出し値が有効になるには、CRCDAT レ

ジスタに書き込んだ後、少なくとも

1 命令サイクルが経過する必要があります。

VWORD<4:0> ビットが DWIDTH<4:0> ビットで設定された値に対応する最大値に達すると、

CRCFUL ビットがセットされます。VWORDx ビットが 0 に達すると、CRCMPT ビットがセッ

トされます。

CRCEN を「0」にすると FIFO はエンプティになり、VWORD<4:0> ビットが

「00000」に設定されます。

CRC シフトクロック周波数は、CPU 命令クロックサイクル周波数の 2 倍です。従ってこのハー

ドウェア シフト処理はソフトウェア シフタよりも高速です。これは、各ワードの計算がデー

タ幅の

1/2 の命令サイクル数で完了する事を意味します。例えば、32 ビットデータの 1 ワード

CRC 計算は 16 命令サイクルで完了します。

5.5.2

データシフトの命令サイクル数

FIFO からのデータはシフトバッファに移動します。FIFO からシフトバッファにデータワード

の移動を開始するには

2 命令サイクル必要です。シフトバッファのデータは続いて CRC シフ

トエンジンに移動します。シフトバッファから

CRC シフトエンジンにデータを全て移動する

には、DWIDTH4:0 ビットの値に対して (DWIDTH4:0 + 1)/2 の命令サイクルが必要です。例え

DWIDTH<4:0> = 5 の場合、データ長は 6 ビット (DWIDTH<4:0> + 1) であるため、シフトに

3 サイクルが必要です。この場合、1 バイトのうち 6 ビットだけがシフトアウトされます。

各バイトの上位

2 ビットはドントケアビットです。同様に、12 ビット多項式を選択した場合、

各ワードの上位

4 ビットが無視されます。

5.5.3

CRC の初期値

CRC 書き込みバスを介して CRC シフトレジスタに直接書き込む経路があります。CPU は、

CRCWDATL および CRCWDATH レジスタを使って、この経路にアクセスします。これらのレ

ジスタには、計算の開始前に必要な

CRC 初期値を書き込む事ができます。この CRC 初期値は

非直接形式である必要があります。非直接形式とは、

CRC と対象の CRC 初期値 ( 直接初期値 )

が等しい値です。例えば、アプリケーションが

CRC-32 多項式 0x04C11DB7 を使い、CRC 直接

初期値

0xFFFFFFFF から計算を開始する必要がある場合、CRCWDATL と CRCWDATH レジス

タには非直接値の

0x46AF6449 を書き込む必要があります。この非直接値 0x46AF6449 の CRC

0xFFFFFFFF です。CRCWDAT レジスタによってシフトエンジンに非直接初期値を書き込む

と、(PLEN<4:0> + 1)/2 命令サイクル後に CRC モジュールがこれを直接初期値に変換します。

通常、

CRC 計算は毎回同じ初期値から開始します。その場合、非直接初期値の計算が必要なの

1 回のみで、アプリケーション コード内で定数として定義できます。

Note:

CRCWDAT レジスタへの書き込みはシフトバッファをクリア ( リセット ) します。

Note:

0 に対する CRC 非直接初期値は 0 です。

(15)

5-1

に、直接初期値から非直接初期値を得るソフトウェア

ルーチンの例を示します。

5-1:

非直接初期値を求めるソフトウェア

ルーチン

CRC モジュールを使って非直接初期値を得る事ができます。それには以下の手順を実行します。

1.

CRC モジュールを有効にして (CRCEN = 1)、シフトする (CRCGO = 1)

2.

多項式の値を右に

1 つシフトする

3.

シフトした多項式の値のビット順序を反転する

4.

その結果を

CRCXOR レジスタに書き込む

5.

データ幅と多項式の長さ

(DWIDTH<4:0> と PLEN<4:0> ビット ) を多項式の次数 ( 長さ ) に

設定する

6.

対象の直接初期値のビット順序を反転する

7.

反転した初期値を

CRCWDAT レジスタに書き込む

8.

CRCDAT レジスタにダミーデータを書き込み、2 命令サイクル待って FIFO からシフトバッ

ファにデータを移動し、(PLEN<4:0> + 1)/2 命令サイクル待って結果をシフトアウトする

または

CRC 割り込み選択ビットをクリアして (CRCISEL = 0)、シフトバッファからのシフト完了

時に割り込みを受信し、

CRC 割り込みフラグをクリアし、CRCDAT レジスタにダミーデー

タを書き込み、

CRC 割り込みフラグがセットされるのを待つ

9.

CRCWDAT レジスタから値を読み出す

10. 読み出し結果のビット順序を反転すると最終的な非直接初期値が得られる

unsigned long CalculateNonDirectSeed(

unsigned long seed, // direct CRC initial value

unsigned long polynomial, // polynomial

unsigned char polynomialOrder) // polynomial order {

unsigned char lsb; unsigned char i; unsigned long msbmask;

msbmask = ((unsigned long)1)<<(polynomialOrder-1); for (i=0; i<polynomialOrder; i++) {

lsb = seed & 1;

if (lsb) seed ^= polynomial; seed >>= 1;

if (lsb) seed |= msbmask; }

return seed; // return the non-direct CRC initial value

(16)

5-2

に、上記の手順を示します。

5-2:

CRC モジュールを使って非直接初期値を求めるルーチン

unsigned long CalculateNonDirectSeed(unsigned long seed, // direct CRC initial value unsigned long polynomial, // polynomial

unsigned char polynomialOrder) // polynomial order (valid values are // 8, 16, 32 bits)

{

CRCCON1 = 0; CRCCON2 = 0;

CRCCON1bits.CRCEN = 1; // enable CRC

CRCCON1bits.CRCISEL = 0; // interrupt when all shifts are done CRCCON2bits.DWIDTH = polynomialOrder-1; // data width

CRCCON2bits.PLEN = polynomialOrder-1; // polynomial length CRCCON1bits.CRCGO = 1; // start CRC calculation

polynomial >>= 1; // shift the polynomial right

polynomial = ReverseBitOrder(polynomial, polynomialOrder); // reverse bits order of the

// polynomial

CRCXORL = (unsigned short)(polynomial&0x0000FFFF); // set the reversed polynomial CRCXORH = (unsigned short)(polynomial>>16);

seed = ReverseBitOrder(seed, polynomialOrder); // reverse bits order of the seed value CRCWDATL = (unsigned short)(seed&0x0000FFFF); // set seed value

CRCWDATH = (unsigned short)(seed>>16);

_CRCIF = 0; // clear interrupt flag

switch(polynomialOrder) // load dummy data to shift out the

// seed result

{

case 8:

*((unsigned char*)&CRCDATL) = 0; // load byte

while(!_CRCIF); // wait until shifts are done seed = CRCWDATL&0x00ff; // read reversed seed

case 16:

CRCDATL = 0; // load short

while(!_CRCIF); // wait until shifts are done seed = CRCWDATL; // read reversed seed

break; case 32:

// load long CRCDATL = 0; CRCDATH = 0;

while(!_CRCIF); // wait for shifts are done seed = ((unsigned long)CRCWDATH<<16)|CRCWDATL; // read reversed seed break;

default: ; }

seed = ReverseBitOrder(seed, polynomialOrder); // reverse the bit order to get the

// non-direct seed

return seed; // return the non-direct CRC initial value }

(17)

5-2:

CRC モジュールを使って非直接初期値を求めるルーチン ( 続き )

計算途中に

CRC の中間合計値を読み出す必要があるアプリケーションで、引き続きデータメッ

セージ全体に対する計算を実行する場合、非直接値を求めて再度

CRCWDAT レジスタに設定

する必要があります。その場合の

CRC 直接初期値は、読み出した中間の CRC 結果です。

// WHERE THE FUNCTION TO REVERSE THE BIT ORDER CAN BE

unsigned long ReverseBitOrder(unsigned long data, // input data

unsigned char numberOfBits) // width of the input data, // valid values are 8,16,32 bits {

unsigned long maskint = 0; unsigned long maskout = 0; unsigned long result = 0; unsigned char i; switch(numberOfBits) { case 8: maskin = 0x80; maskout = 0x01; break; case 16: maskin = 0x8000; maskout = 0x0001; break; case 32: maskin = 0x80000000; maskout = 0x00000001; break; default: ; }

for(i=0; i<numberOfBits; i++) { if(data&maskin){ result |= maskout; } maskint >>= 1; maskout <<= 1; } return result; }

(18)

5.5.4

CRC 結果

CRC モジュールは、計算を終了するのにさらに (PLEN<4:0> + 1)/2 命令サイクルを必要とします。

これらの追加サイクルを生成するために、

多項式の次数(長さ)に等しい幅のダミーデータをCRCDAT

レジスタに書き込む必要があります。シフト完了後、

CRC の最終結果は CRCWDAT レジスタ

から読み出せます(CRCWDAT レジスタにより CRC シフトレジスタへ直接アクセスできます )。

全データが

CRC モジュールに読み込まれたら、CRC の最終結果を得るために以下の手順を実

行する必要があります。データ幅

(DWIDTH<4:0> ビット ) が多項式の長さ (PLEN<4:0> ビット )

よりも大きい場合

:

1.

データ

FIFO がエンプティになる (CRCMPT ビットがセットされる ) のを待つ

2.

シフトバッファからのシフトが確実に完了するように

(DWIDTH<4:0> + 1)/2 命令サイクル

待つ

3.

データ幅を多項式の長さに変更する

(DWIDTH<4:0> = PLEN<4:0>)

4.

CRCDAT レジスタにダミーデータ ワードを 1 つ書き込む

5.

2 命令サイクル待って FIFO からシフトバッファにデータを移動し、(PLEN<4:0> + 1)/2 命

令サイクル待って結果をシフトアウトする

または

シフトが全て終了した時点で割り込みを受信できるように

CRC 割り込み選択ビットをク

リアする

(CRCISEL = 0) 。CRC 割り込みフラグをクリアする。CRCDAT レジスタにダ

ミーデータを書き込み、CRC 割り込みフラグがセットされるのを待つ

6.

CRCWDAT レジスタから CRC の最終結果を読み出す

7.

以降の計算のためにデータ幅

(DWIDTH<4:0> ビット ) の値を元に戻す ( 任意 )

データ幅

(DWIDTH<4:0> ビット ) が多項式の長さ (PLEN<4:0> ビット ) 以下の場合、結果を得

る手順は上記と異なります。

1.

シフトが全て終了した時点で割り込みを受信できるように

CRC 割り込み選択ビットをク

リアする

(CRCISEL = 0)

2.

CRCGO = 0 に設定して計算を一時停止する

3.

CRC 割り込みフラグをクリアする

4.

全長が多項式の長さに等しいダミーデータを

CRCDAT レジスタに書き込む

5.

CRCGO = 1 にセットして計算を再開する

6.

CRC 割り込みフラグがセットされるのを待つ

7.

CRCWDAT レジスタから CRC の最終結果を読み出す

CRC の結果が得られたら、CRCWDAT レジスタに再度 CRC 非直接初期値を書き込み、シフト

バッファ内のダミーデータをクリアして新たに計算を開始します。

(19)

5-3

に、多項式の次数が

8/16/32 ビットの場合について上記の手順を示します。

5-3:

CRC 最終結果を得るルーチン

5.6

割り込み動作

CRC モジュールは、ユーザの設定に従って下記の条件のどれかで割り込みを生成します。

CRCISEL が「1」の場合、VWORD<4:0> ビットの値が「1」から「0」に遷移すると割り込み

を生成します。

CRCISEL が「0」の場合、FIFO がエンプティになってシフトバッファからの

シフトが完了すると割り込みを生成します。

セクション

9.0「レジスタマップ」

の表に、CRC モジュールに関連する割り込みレジスタの

詳細を示します。

割り込みと割り込み優先度設定の詳細は『dsPIC33/PIC24 ファミリ リファ

レンス マニュアル』の「割り込み」セクションを参照してください。

unsigned long GetCRC(unsigned char polynomialOrder, // valid values are 8,16,32 unsigned char currentDataWidth) // valid values are 8,16,32 {

unsigned long crc = 0;

while(!CRCCON1bits.CRCMPT); // wait until data FIFO is empty asm volatile ("repeat %0\n nop" : : "r"(currentDataWidth>>1)); // wait until previous data

// shifts are done

CRCCON2bits.DWIDTH = polynomialOrder-1; // set data width to polynomial

// length

CRCCON1bits.CRCISEL = 0; // interrupt when all shifts are done

_CRCIF = 0; // clear interrupt flag

switch(polynomialOrder) {

case 8: // polynomial length is 8 bits

*((unsigned char*)&CRCDATL) = 0; // load byte

while(!_CRCIF); // wait until shifts are done crc = CRCWDATL&0x00ff; // get crc

break;

case 16: // polynomial length is 16 bits

CRCDATL = 0; // load short

while(!_CRCIF); // wait until shifts are done

crc = CRCWDATL; // get crc

break;

case 32: // polynomial length is 32 bits

CRCDATL = 0; // load long

CRCDATH = 0;

while(!_CRCIF); // wait until shifts are done crc = ((unsigned long)CRCWDATH<<16)|CRCWDATL; // get crc

break; default:

; }

CRCCON2bits.DWIDTH = currentDataWidth-1; // restore data width for further

// calculations

return crc; // return the final CRC value

(20)

6.0

プログラマブル

CRC モジュールの利点

CRC アルゴリズムは簡単にソフトウェアに組み込めます。しかしシフト、ビット検査、XOR

演算等の基本要件を実装するには、かなりの

CPU 処理能力が必要です。さらに、CRC 計算は

対話型処理であるため、データ転送命令による追加のソフトウェア オーバーヘッドがマイクロ

コントローラの

MIPS 要件にとって著しい重荷となります。

dsPIC33/PIC24 の CRC エンジンは、CPU に負荷を掛けずに CRC チェックサムを計算します。

しかもソフトウェア実装よりも大幅に高速です。CRC シフトクロックは dsPIC33/PIC24 の命

令クロックサイクルの

2 倍であるため、計算には 1 ビットあたり 1/2 命令サイクルしか要しま

せん。例えば、128 ビット (16x8) の長さを持つメッセージの CRC チェックサムを CRC ハー

ドウェア

エンジンを使って求めると、約 64 命令サイクルしかかかりません。同じ計算をソフ

トウェアで実行すると、最適化されたコードを使っても

1000 命令サイクル以上が必要です。

7.0

CRC モジュールのアプリケーション

CRC の計算は、複数のバイトまたはワードを格納したメッセージのデジタル通信における信頼

性の高い誤り検査アルゴリズムです。計算後にチェックサムを付加して、受信者にメッセージ

を送信します。受信者は、受信したメッセージのチェックサムを計算する事でデータの完全性

を検証します。

7.1

CRC 計算のバリエーション

dsPIC33/PIC24 の 32 ビット プログラマブル CRC モジュールでは、MSb または LSb のどちら

を先頭にシフトアウトするかを選択できます。MSb 先頭は、XMODEM プロトコルで採用され

ているため、広く用いられる方式です。通信プロトコルの

1 つである CCITT プロトコルの CRC

計算では、LSb を先頭にシフトアウトします。本書では個々の CRC 計算バリエーションにつ

いて説明しませんが、

dsPIC33/PIC24 の 32 ビット プログラマブル CRC モジュールを使えば、

各種の

CRC バリエーションを実装する事ができます。

多項式の長さと多項式そのものの選択はアプリケーションごとに異なります。各種の標準的な

実装では、多項式の長さとして通常

5、7、8、10、12、16、32 を使います。以降のセクショ

ンでは、

CRC 計算の推奨手順をステップごとに説明します。ユーザは、メッセージ ストリー

ムに

0 を付加するのか 0 以外の値を付加するのかを選択できます。アプリケーションに応じて、

ユーザはどのような値でも自由に付加する事ができます。

7.2

代表的な動作

代表的な

CRC 計算にこのモジュールを使う場合、以下の手順を実行します。

1.

CRCEN ビットをセットしてモジュールを有効にする

2.

目的とする動作に合わせて以下の通りモジュールを設定する

a) CRCXOR レジスタと PLEN<4:0> ビットで必要な多項式を設定する

b) DWIDTH<4:0> と LENDIAN ビットでデータ幅とシフト方向を設定する

3.

CRCGO ビットをセットして計算を始める

4.

CRCWDAT レジスタに書き込む事で、CRC 非直接初期値を設定する

5.

FIFO に空きができたら、CRCDAT レジスタに書き込む事で、FIFO に全てのデータを書き

込む

( 次のデータを書き込むには CRCFUL ビットが 0 である必要がある )

6.

データ

FIFO がエンプティになる (CRCMPT ビットがセットされる ) のを待つ

7.

セクション

5.5.4「CRC 結果」

で説明した方法で

CRC 結果を読み出す

(21)

7-1

,

7-2

,

7-3

,

7-4

7-5

に、多項式の長さ、データ幅、シフト方向の各種組み合わ

せの例を示します。

7-1:

8 ビット多項式、32 ビットデータ幅、MSb 先頭シフトの場合 (CRC SMBus)

// ASCII bytes "12345678"

volatile unsigned char __attribute__((aligned(2))) message[] = {'1','2','3','4','5','6','7','8'}; volatile unsigned char crcResultCRCSMBUS = 0;

int main (void) {

unsigned short* pointer; unsigned short length; unsigned short data_high; unsigned short data_low;

//////////////////////////////////////////////////////////////////////////////// // standard CRC-SMBUS

//////////////////////////////////////////////////////////////////////////////// #define CRCSMBUS_POLYNOMIAL ((unsigned short)0x0007)

#define CRCSMBUS_SEED_VALUE ((unsigned short)0x0000) // non-direct of 0x00 CRCCON1 = 0;

CRCCON2 = 0;

CRCCON1bits.CRCEN = 1; // enable CRC

CRCCON1bits.LENDIAN = 0; // big endian

CRCCON1bits.CRCISEL = 0; // interrupt when all shifts are done CRCCON2bits.DWIDTH = 32-1; // 32-bit data width

CRCCON2bits.PLEN = 8-1; // 8-bit polynomial order CRCCON1bits.CRCGO = 1; // start CRC calculation CRCXORL = CRCSMBUS_POLYNOMIAL; // set polynomial

CRCXORH = 0;

CRCWDATL = CRCSMBUS_SEED_VALUE; // set initial value CRCWDATH = 0;

pointer = (unsigned short*)message; // calculate CRC length = sizeof(message)/sizeof(unsigned long);

while(length--) {

(22)

7-1:

8 ビット多項式、32 ビットデータ幅、MSb 先頭シフトの場合 (CRC SMBus) ( 続き )

while(CRCCON1bits.CRCFUL); // wait if FIFO is full data_low = *pointer++; // load from little endian data_high = *pointer++;

asm volatile ("swap %0" : "+r"(data_low)); // swap bytes for big endian asm volatile ("swap %0" : "+r"(data_high));

CRCDATL = data_high; // 32-bit word access to FIFO CRCDATH = data_low; // swap 16-bit words for big endian }

while(!CRCCON1bits.CRCMPT); // wait until FIFO is empty

// wait until previous data shifts are done asm volatile ("repeat #16-#2\n nop"); // 16 cycles maximum for 32-bit data width

CRCCON2bits.DWIDTH = 8-1; // 8-bit

// switch data width to polynomial length

_CRCIF = 0; // clear the interrupt flag

// dummy data to shift out the CRC result *((unsigned char*)&CRCDATL) = 0; // byte access to FIFO

while(!_CRCIF); // wait until shifts are done crcResultCRCSMBUS = CRCWDATL&0x00ff; // get CRC result (must be 0xC7) while(1);

return 1; }

(23)

7-2:

16 ビット多項式、16 ビットデータ幅、LSb 先頭シフトの場合 (CRC 16)

// ASCII bytes "87654321"

volatile unsigned short message[] = {0x3738,0x3536,0x3334,0x3132}; volatile unsigned short crcResultCRC16 = 0;

int main (void) {

unsigned short* pointer; unsigned short length; unsigned short data;

//////////////////////////////////////////////////////////////////////////////// // standard CRC-16

//////////////////////////////////////////////////////////////////////////////// #define CRC16_POLYNOMIAL ((unsigned short)0x8005)

#define CRC16_SEED_VALUE ((unsigned short)0x0000) // non-direct of 0x0000 CRCCON1 = 0;

CRCCON2 = 0;

CRCCON1bits.CRCEN = 1; // enable CRC

CRCCON1bits.CRCISEL = 0; // interrupt when all shifts are done CRCCON1bits.LENDIAN = 1; // little endian

CRCCON2bits.DWIDTH = 16-1; // 16-bit data width CRCCON2bits.PLEN = 16-1; // 16-bit polynomial order CRCCON1bits.CRCGO = 1; // start CRC calculation CRCXORL = CRC16_POLYNOMIAL; // set polynomial

CRCXORH = 0;

CRCWDATL = CRC16_SEED_VALUE; // set initial value CRCWDATH = 0;

pointer = (unsigned short*)message; // calculate CRC lengthr = sizeof(message)/sizeof(unsigned short);

while(length--) {

while(CRCCON1bits.CRCFUL); // wait if FIFO is full

data = *pointer++; // load data

CRCDATL = data; // 16-bit word access to FIFO }

(24)

7-2:

16 ビット多項式、16 ビットデータ幅、LSb 先頭シフトの場合 (CRC 16) ( 続き )

CRCCON1bits.CRCGO = 0; // suspend CRC calculation to clear interrupt flag _CRCIFt = 0; // clear interrupt flag

CRCDATL = 0; // load dummy data to shift out the CRC result // data width must be equal to polynomial length

CRCCON1bits.CRCGO = 1; // resume CRC calculation while(!_CRCIF); // wait until shifts are done

crcResultCRC16 = CRCWDATL; // get CRC result (must be 0xE716) while(1);

return 1; }

(25)

7-3:

16 ビット多項式、16 ビットデータ幅、MSb 先頭シフトの場合 (CRC CCITT)

// ASCII bytes "87654321"

volatile unsigned short message[] = {0x3738,0x3536,0x3334,0x3132}; volatile unsigned short crcResultCRCCCITT = 0;

int main (void) {

unsigned short* pointer; unsigned short length; unsigned short data;

//////////////////////////////////////////////////////////////////////////////// // standard CRC-CCITT

//////////////////////////////////////////////////////////////////////////////// #define CRCCCITT_POLYNOMIAL ((unsigned short)0x1021)

#define CRCCCITT_SEED_VALUE ((unsigned short)0x84CF) // non-direct of 0xffff CRCCON1 = 0;

CRCCON2 = 0;

CRCCON1bits.CRCEN = 1; // enable CRC

CRCCON1bits.CRCISEL = 0; // interrupt when all shifts are done CRCCON1bits.LENDIAN = 0; // big endian

CRCCON2bits.DWIDTH = 16-1; // 16-bit data width CRCCON2bits.PLEN = 16-1; // 16-bit polynomial order CRCCON1bits.CRCGO = 1; // start CRC calculation CRCXORL = CRCCCITT_POLYNOMIAL; // set polynomial

CRCXORH = 0;

CRCWDATL = CRCCCITT_SEED_VALUE; // set initial value CRCWDATH = 0;

pointer = (unsigned short*)message; // calculate CRC lengthr = sizeof(message)/sizeof(unsigned short);

while(length--) {

while(CRCCON1bits.CRCFUL); // wait if FIFO is full

data = *pointer++; // load data

(26)

7-3:

16 ビット多項式、16 ビットデータ幅、MSb 先頭シフトの場合 (CRC CCITT) ( 続き )

CRCDATL = data; // 16 bit word access to FIFO }

while(CRCCON1bits.CRCFUL); // wait if FIFO is full

CRCCON1bits.CRCGO = 0; // suspend CRC calculation to clear interrupt flag

_CRCIF = 0; // clear interrupt flag

CRCDATL = 0; // load dummy data to shift out the CRC result // data width must be equal to polynomial length CRCCON1bits.CRCGO = 1; // resume CRC calculation

while(!_CRCIF); // wait until shifts are done

crcResultCRCCCITT = CRCWDATL; // get CRC result (must be 0x9B4D) while(1);

return 1; }

(27)

7-4:

32 ビット多項式、32 ビットデータ幅、LSb 先頭シフトの場合 (CRC 32)

// ASCII bytes "12345678"

volatile unsigned char __attribute__((aligned(4))) message[] = {'1','2','3','4','5','6','7','8'}; // function to reverse the bit order (OPTIONAL)

unsigned long ReverseBitOrder(unsigned long data); volatile unsigned long crcResultCRC32 = 0;

int main(void) {

unsigned short* pointer; unsigned short length;

//////////////////////////////////////////////////////////////////////////////// // standard CRC-32

//////////////////////////////////////////////////////////////////////////////// #define CRC32_POLYNOMIAL ((unsigned long)0x04C11DB7)

#define CRC32_SEED_VALUE ((unsigned long)0x46AF6449) // non-direct of 0xffffffff CRCCON1 = 0;

CRCCON2 = 0;

CRCCON1bits.CRCEN = 1; // enable CRC

CRCCON1bits.CRCISEL = 0; // interrupt when all shifts are done

CRCCON1bits.LENDIAN = 1; // little endian

CRCCON2bits.DWIDTH = 32-1; // 32-bit data width

CRCCON2bits.PLEN = 32-1; // 32-bit polynomial order

CRCCON1bits.CRCGO = 1; // start CRC calculation

CRCXORL = CRC32_POLYNOMIAL&0x0000ffff; // set polynomial CRCXORH = CRC32_POLYNOMIAL>>16;

CRCWDATL = CRC32_SEED_VALUE&0x0000ffff; // set initial value CRCWDATH = CRC32_SEED_VALUE>>16;

pointer = (unsigned short*)message; // calculate CRC lengthr = sizeof(message)/sizeof(unsigned long);

while(length--) {

while(CRCCON1bits.CRCFUL); // wait if FIFO is full // 32-bit word access to FIFO

CRCDATL = *pointer++; // must be written first

CRCDATH = *pointer++; // must be written last

}

(28)

7-4:

32 ビット多項式、32 ビットデータ幅、LSb 先頭シフトの場合 (CRC 32) ( 続き )

CRCCON1bits.CRCGO = 0; // suspend CRC calculation to clear interrupt flag

_CRCIF = 0; // clear interrupt flag

CRCDATL = 0; // dummy data to shift out the CRC result CRCDATH = 0;

CRCCON1bits.CRCGO = 1; // resume CRC calculation

while(!_CRCIF); // wait until shifts are done

crcResultCRC32 = ((unsigned long)CRCWDATH<<16)|CRCWDATL; // get the final CRC result

crcResultCRC32 = ~ReverseBitOrder(crcResultCRC32); // OPTIONAL

// reverse CRC value bit order and // invert (must be 0x9AE0DAAF) while(1);

return 1; }

unsigned long ReverseBitOrder(unsigned long data) {

unsigned long maskin; unsigned long maskout; unsigned long result = 0; unsigned char i;

maskin = 0x80000000; maskout = 0x00000001; for(i=0; i<32; i++) { if(data&maskin){ result |= maskout; } maskint >>= 1; maskout <<= 1; } return result; }

(29)

7-5:

32 ビット多項式、データ幅切り換え、MSb 先頭シフトの場合

// ASCII bytes "12345678"

volatile unsigned long message1[] = {0x34333231,0x38373635}; // ASCII bytes "123"

volatile unsigned char message2[] = {'1','2','3'}; volatile unsigned long crcResultCRC32 = 0;

int main(void) {

unsigned char* pointer8; unsigned short* pointer16; unsigned short length;

#define CRC32_POLYNOMIAL ((unsigned long)0x04C11DB7)

#define CRC32_SEED_VALUE ((unsigned long)0x46AF6449) // non-direct of 0xffffffff CRCCON1 = 0;

CRCCON2 = 0;

CRCCON1bits.CRCEN = 1; // enable CRC

CRCCON1bits.LENDIAN = 1; // little endian

CRCCON2bits.DWIDTH = 32-1; // 32-bit data width

CRCCON2bits.PLEN = 32-1; // 32-bit polynomial order

CRCCON1bits.CRCGO = 1; // start CRC calculation

CRCXORL = CRC32_POLYNOMIAL&0x0000ffff; // set polynomial CRCXORH = CRC32_POLYNOMIAL>>16;

CRCWDATL = CRC32_SEED_VALUE&0x0000ffff; // set initial value CRCWDATH = CRC32_SEED_VALUE>>16;

pointer16 = (unsigned short*)message1; // calculate CRC lengthttt = sizeof(message1)/sizeof(unsigned long);

while(length--) {

(30)

7-5:

32 ビット多項式、データ幅切り換え、MSb 先頭シフトの場合 ( 続き )

// 32-bit word access to FIFO CRCDATL = *pointer16++; // must be written first CRCDATH = *pointer16++; // must be written last }

// wait until previous // data shifts are done while(!CRCCON1bits.CRCMPT); // wait until FIFO is empty

asm volatile ("repeat #16-#2\n nop"); // 16 cycles maximum for 32-bit data CRCCON2bits.DWIDTH = 8-1; // switch the data width to 8-bit pointer8 = (unsigned char*)message2; // calculate CRC

lengthtt = sizeof(message2)/sizeof(unsigned char); while(length--)

{

while(CRCCON1bits.CRCFUL); // wait if FIFO is full *((unsigned char*)&CRCDATL) = *pointer8++; // byte access to FIFO }

while(!CRCCON1bits.CRCMPT); // wait until FIFO is empty

// wait until previous data shifts are done asm volatile ("repeat #4-#2\n nop"); // 4 cycles maximum for 8-bit data

// switch the data width to polynomial length

CRCCON2bits.DWIDTH = 32-1; // 32-bit

CRCDATL = 0; // dummy data to shift out the CRC result

CRCDATH = 0;

asm volatile ("repeat #2+#16-#2\n nop"); // delay 2 cycles to move data from FIFO // to shift buffer

// and 16 cycles for 32-bit word to shift out // the final result

crcResultCRC32 = ((unsigned long)CRCWDATH<<16)|CRCWDATL; // get the final CRC result // (must be0xE092727E) while(1);

return 1; }

(31)

8.0

省電力モードの動作

8.1

スリープ

モジュールが動作中にスリープに移行した場合、モジュールはクロック動作が再開するまで現

在の状態で一時停止します。

8.2

アイドル

アイドル中もモジュールを動作させるには、アイドル移行前に

CSIDL ビットをクリアする必要

があります。

CSIDL = 1 の場合、モジュールはスリープの場合と同じようにふるまいます。モジュールのク

ロックが使えなくても、保留中の割り込みイベントは継承されます。

(32)

ファミリ

リファレンス

マニュアル

29B_JP p.32 © 2011-2014 Microchip T echnolo

9-1

に、dsPIC33/PIC24 の 32 ビット プログラマブル巡回冗長検査 (CRC) モジュールに関連する特殊機能レジスタをまとめます。

9-1:

プログラマブル

CRC モジュール関連の特殊機能レジスタ

(

1

)

SFR 名 Bit 15 Bit 14 Bit 13 Bit 12 Bit 11 Bit 10 Bit 9 Bit 8 Bit 7 Bit 6 Bit 5 Bit 4 Bit 3 Bit 2 Bit 1 Bit 0

リセット CRCCON1 CRCEN - CSIDL VWORD4 VWORD3 VWORD2 VWORD1 VWORD0 CRCFUL CRCMPT CRCISEL CRCGO LENDIAN - - - 0040 CRCCON2 - - - DWIDTH4 DWIDTH3 DWIDTH2 DWIDTH1 DWIDTH0 - - - PLEN4 PLEN3 PLEN2 PLEN1 PLEN0 0000

CRCXORL X15 X14 X13 X12 X11 X10 X9 X8 X7 X6 X5 X4 X3 X2 X1 - 0000

CRCXORH X31 X30 X29 X28 X27 X26 X25 X24 X23 X22 X21 X20 X19 X18 X17 X16 0000

CRCDATL DATA15 DATA14 DATA13 DATA12 DATA11 DATA10 DATA9 DATA8 DATA7 DATA6 DATA5 DATA4 DATA3 DATA2 DATA1 DATA0 0000 CRCDATH DATA31 DATA30 DATA29 DATA28 DATA27 DATA26 DATA25 DATA24 DATA23 DATA22 DATA21 DATA20 DATA19 DATA18 DATA17 DATA16 0000 CRCWDATL SDATA15 SDATA14 SDATA13 SDATA12 SDATA11 SDATA10 SDATA9 SDATA8 SDATA7 SDATA6 SDATA5 SDATA4 SDATA3 SDATA2 SDATA1 SDATA0 0000 CRCWDATH SDATA31 SDATA30 SDATA29 SDATA28 SDATA27 SDATA26 SDATA25 SDATA24 SDATA23 SDATA22 SDATA21 SDATA20 SDATA19 SDATA18 SDATA17 SDATA16 0000

IFS4 - - - CRCIF U2ERIF U1ERIF - 0000

IEC4 - - - CRCIE U2ERIE U1ERIE - 0000

IPC16 - CRCIP2 CRCIP1 CRCIP0 - U2ERIP2 U2ERIP1 U2ERIP0 - U1ERIP2 U1ERIP1 U1ERIP0 - - - - 4440 凡例: - = 未実装、「0」として読み出し、網掛けしたビットは、プログラマブル CRC モジュールの動作には使いません。

(33)

10.0

関連アプリケーション ノート

マニュアルの本セクションに関連するアプリケーション

ノートの一覧を以下に記載します。こ

れらのアプリケーション ノートは dsPIC33/PIC24 ファミリ向けに記述されたものではありま

せんが、基本的な考え方は共通しているため、若干の修正と制約のみでそのまま使えます。32

ビット プログラマブル巡回冗長検査 (CRC) に関連する最新のアプリケーション ノートは以下

の通りです。

タイトル

アプリケーション

ノート番号

現在、関連するアプリケーション ノートはありません。

Note:

dsPIC33/PIC24 ファミリ関連のアプリケーション ノートとサンプルコードは

Microchip 社のウェブサイト (

www.microchip.com

) でご覧頂けます。

(34)

11.0

改訂履歴

リビジョン

A (2009 年 4 月 )

本書の初版です。

リビジョン

B (2013 年 8 月 )

このリビジョンでの変更内容は以下の通りです。

• 文書名を『PIC24F ファミリ リファレンス マニュアル』から『dsPIC33/PIC24 ファミリ リファ

レンス マニュアル』に変更しました。

• レジスタ 3-1 の CRCISEL の説明を改訂しました。

セクション

5.3「データのシフト方向」

に情報を追加しました。

セクション

5.4「FIFO」

に情報を追加しました。

5-1

5-2

5-3

を訂正しました。

セクション

5.5「CRC エンジン インターフェイス」

を改訂しました。

セクション

5.6「割り込み動作」

を改訂し、サンプルコードを追加しました。

セクション

7.2「代表的な動作」

を改訂し、サンプルコードを追加しました。

• 本書全体に文言の若干の訂正を加えました。

図 5-1: FIFO に 8 ビット幅以下のデータを格納する場合
表 9-1 に、dsPIC33/PIC24 の 32 ビット プログラマブル巡回冗長検査 (CRC) モジュールに関連する特殊機能レジスタをまとめます。

参照

関連したドキュメント

731 部隊とはということで,簡単にお話しします。そこに載せてありますのは,

に関して言 えば, は つのリー群の組 によって等質空間として表すこと はできないが, つのリー群の組 を用いればクリフォード・クラ イン形

5G Sub-6 GHz プラガブル インターフェイス モジュールは、 IoT 産業用ルータファミリに 5G 機 能を提供します。プラガブルモジュールの製品 ID は P-5GS6-GL

Scival Topic Prominence

Nintendo Switchでは引き続きハードウェア・ソフトウェアの魅力をお伝えし、これまでの販売の勢いを高い水準

この条約において領有権が不明確 になってしまったのは、北海道の北

つまり、p 型の語が p 型の語を修飾するという関係になっている。しかし、p 型の語同士の Merge

 このようなパヤタスゴミ処分場の歴史について説明を受けた後,パヤタスに 住む人の家庭を訪問した。そこでは 3 畳あるかないかほどの部屋に