2011年4月3日作成 2010年4月6日更新
PICプログラマを作ったときに調べた書き込み手順を、自分が忘れてしまわないうちに書いておきます。
マイクロチップ社のデータシートにすべて書かれているので、まずはそれを読みます。自分はPIC16F88に書き込みたかったので、PIC16F87/88 FLASH Memory Programming Specification 39607c を読みました。
PIC16の書き込みモードには、ICSPモードとLV-ICSPモードがあります。
MCLR(VPP)ピンに高電圧(13Vとか9Vとかデバイスにより異なる)を印加して書きこむのが以前からあるICSPモードで、多くの(たぶん全ての?)デバイスに書きこむことが出来ます。
対してLV(Low-Voltage)-ICSPモードは比較的最近のデバイスでサポートされた方法のようで、高電圧が必要無く、MCLRに掛ける電圧はVDD(2.0-5.5V)でよいので書き込み機の回路を簡単にできます。そのかわり書き込みモードと通常のプログラム実行モードの切り替えにPGM(PIC16F88の場合RB3)ピンを使用するので、PGMピンを通常のIOポートとして使えなくなります。また、LV-ICSPモードを使用するにはコンフィギュレーションワードのLVPビットが1でなければなりません。LVPビットは工場出荷時やチップイレース後には1になっています。
以上。
以上。PGMピンはずっとHに固定していても動いたので、自作の回路ではそのようにしている。
簡単でしょ?
ICSPモードとLV-モードでは書き込みモードへの入り方は違いますが、書き込みモードに入った後の書き込み手順は同じです。
書き込みは
の順で行います。消去コマンドには、現在のポインタが含まれるブロックを消去するBegin Eraseコマンド、プログラムメモリをすべて消去するBulk Erase Program Memoryコマンド、データメモリをすべて消去するBulk Erase Data Memoryコマンド、チップ全体を消去するChip Eraseコマンドがありますが、バルクイレースとチップイレースはVDDが4.5〜5.5Vの間の時しか使用できないので、今回作成したプログラマでは幅広い電圧で書き込みができるようにこれらのコマンドは使わず、Begin Eraseコマンドのみを使用することにしました。
5Vでしか使わない!という場合は、バルクイレース/チップイレースを使ったほうが、少しだけ書き込み手順が簡単になります。
コンフィグレーションワードでコードプロテクトを有効に設定すると、チップイレースコマンドでしか消去できなくなるので、注意が必要です。
Command | Mapping (MSB … LSB) | Data | Voltage Range |
---|---|---|---|
Load Configuration | 0 0 0 0 0 | 0000000000000000 | 2.0V-5.5V |
Load Data for Program Memory | 0 0 0 1 0 | 0, data (14), 0 | 2.0V-5.5V |
Read Data from Program Memory | 0 0 1 0 0 | 0, data (14), 0 | 2.0V-5.5V |
Increment Address | 0 0 1 1 0 | 2.0V-5.5V | |
Begin Erase | 0 1 0 0 0 | 2.0V-5.5V | |
Begin Programming Only Cycle | 1 1 0 0 0 | 2.0V-5.5V | |
Bulk Erase Program Memory | 0 1 0 0 1 | 4.5V-5.5V | |
Bulk Erase Data Memory | 0 1 0 1 1 | 4.5V-5.5V | |
Chip Erase | 1 1 1 1 1 | 4.5V-5.5V | |
Load Data for Data Memory | 0 0 0 1 1 | 0 0 0 0 0 0 0,data (8), 0 | 2.0V-5.5V |
Read Data from Data Memory | 0 0 1 0 1 | 0 0 0 0 0 0 0,data (8), 0 | 2.0V-5.5V |
End Programming | 1 0 1 1 1 |
コンフィギュレーションメモリの先頭アドレス(0x2000 デバイスによって違う)にアドレスポインタを移動する。コマンド6ビットの後に16ビット分0を出力する必要あり。
プログラムメモリに書き込むデータ1ワードを現在のアドレスポインタのラッチにセットする。フラッシュメモリにはまだ書き込まれずBegin Programming Only Cycleコマンドで実際に書き込まれる。
1ワード14ビットなので、前後に一つずつ0を追加して16ビット分送信する。
プログラムメモリから1ワード読み出す。
アドレスポインタを1だけ進める。
続けて2ms待ってからEnd Programmingコマンド発行。
フラッシュメモリの消去。
現在のアドレスポインタがあるブロックを消去する。プログラムメモリは1ブロック32ワード。データメモリは1ブロック1バイト。
(ICSPモードに入った直後にBegin Eraseコマンドを出しても消去されなかった。Load Data for Program Memoryコマンドで何か1ワード書いた後だと消去できた)
続けて2ms待ってからEnd Programmingコマンド発行。
このコマンドで、ラッチからフラッシュメモリへデータが書き込まれる。
続けてBegin Eraseコマンド発行後10ms待ってからEnd Programmingコマンド発行。
このコマンドに続けてBegin Eraseコマンドを出すとバルクイレースが実行される。
アドレスポインタがユーザーメモリを指していると、ユーザーメモリが全部消去されます。
アドレスポインタがコンフィギュレーションメモリを指していると、コンフィギュレーションメモリとユーザーメモリの両方が全部消去されます。
続けてBegin Eraseコマンド発行後10ms待ってからEnd Programmingコマンド発行。
このコマンドに続けてBegin Eraseコマンドを出すとデータメモリが全部消去されます。
すべてのフラッシュメモリを消去する。Chip Eraseコマンドだけを出せばすぐに消去を始める。消去には10msかかる。
データメモリに書き込むデータ1バイトを現在のアドレスポインタのラッチにセットする。フラッシュメモリにはまだ書き込まれずBegin Programming Only Cycleコマンドで実際に書き込まれる。
0を追加して16ビット分送信する。
データメモリから1バイト読み出す。
フラッシュメモリの書き込み/消去コマンドの後に発行する事になっている。
フラッシュメモリは消去後、ビットが1になります。プログラムメモリなら0x3FF、データメモリなら0xFF。
PICとは、PGCピンとPGDピンを使用したクロック同期式のシリアル通信でコマンドをやり取りします。
データシートのコマンド一覧表ではコマンドが5ビットで表記されていますが、実際に送信するときには最後に1ビット追加して6ビット分送信します。追加するビットは0でも1でも良いようなのですが、今回作ったプログラマでは0を追加しています。
コマンドの送信と同じで、クロックの立ち下がりでデータ有効。受信時はPGCピンをHにしてから80ns後にデータが確定するので、その後PGDピンを読み取ってからPGCをLにする。
実際にやり取りするデータは14ビットとか8ビットなので、前後に0を追加して16ビット分送受信する。
書き込み手順は、ICSPモードでもLV-ICSPモードでも同じです。
書き込み位置を示すアドレスポインタに直接値を設定することは出来ません。Increment Address コマンドでアドレスポインタを1進めることと、Load Configuration コマンドでアドレスポインタを 0x2000(コンフィギュレーションメモリの先頭)に設定することと、ICSPモードに入りなおしてアドレスポインタを0にリセットすることしか出来ません。現在のアドレスポインタを読み出すことも出来ません。
ICSPモードに入った直後のアドレスポインタは0
2〜4で1ブロック消去。PIC16F88の場合1ブロック32ワードなので、書きこむアドレスが32で割り切れる時にBegin Eraseコマンドを出せば良い
(バルクイレースコマンドとかで先に消去してあるなら、ここで消去する必要はない)
書き込みが終了したら書いたアドレスをすべて読み出してみて、正しく書けているかを確認する。
ICSPモードに入った直後のアドレスポインタは0
読み出しは簡単
コンフィギュレーションメモリの書き込みもプログラムメモリと同じ方法で書き込みできるのですが、Begin Eraseコマンドで8ワードしか消えないようでした。(0x2000番地でBegin Eraseコマンドを出すと、0x2000〜0x2007までしか消去されなかった。)
コンフィギュレーションワード2が0x2008番地なので、0x2008番地でもBegin Eraseコマンドを出すようにしました。
PIC16F88でLEDを点滅させるプログラムのHEXファイル
:040000008A11D12F61
:100FA20083018A11D42F7030831603138F009B01A3
:100FB20086018501FF30831203138600FF3085000E
:100FC2000630F2000E30F100B030F000F00BE72FE7
:100FD200F10BE72FF20BE72F831203138601850132
:100FE2000630F2000E30F100B030F000F00BF72FB7
:0E0FF200F10BF72FF20BF72FDB2F8A110028DF
:04400E00B93FFC3F7B
:00000001FF
数はすべて16進。2文字で1バイトを表す。
:
行頭は必ず':'で始まる04
この行に含まれるデータの数(この場合4バイト)0000
オフセットアドレス(ビッグエンディアン)PIC16は14ビットで1ワードなので、この値を1/2したものがPICのアドレスになる
00
レコードタイプ00はデータレコード
8A11D12F
データ上のデータの数の通り4バイトある。リトルエンディアンなのでこの場合
61
チェックサム1バイトづつ、チェックサム自身も含めてすべての数を加算して下位1バイトが0になれば正常
04+00+00+00+8A+11+D1+2F+61=0x200 で下位1バイトは0になり正常。
01
レコードタイプ01はファイル終了レコード。「この行で終了ですよ」の意味
('A`)