PICプログラマのソフトウェア1 〜hexファイルを解釈する〜

PICプログラマとは

 もう一度はっきりしておきましょう。PICプログラマは、PICマイコンにプログラムを書き込む(=ダウンロードする)ためのツールです。PICライタなどとも呼ばれるみたいですね。PICマイコンに電気的に刺激を与えて(?)データを書き込むためハードウェアと、刺激の与え方(?)を制御するためのソフトウェアが必要になります。そして、その書き込むプログラムの元データが、今から調べるhexファイルなのです。hexファイルは何なのかを理解しておかないことには、PICプログラマを作ることはできませんからね。

hexファイルとは

 hexファイルというのは、正しくはIntel hexadecimal object file format specificationで規定された文法で記述されたファイル、とでもいうのでしょうか、通称"Intel HEX"ファイルと呼ばれるファイルです。メモリに書き込むべきデータを記入したファイルで、メモ帳などでも開けるテキストファイルです。通常、拡張子は.hexになっていることが多いようです。

hexファイルのありか

 その中身を見てみましょう。前回ビルドした結果として、mikroCが作成してくれたhexファイルがありますので、それを開いてみましょう。指定したプロジェクトパスのフォルダを開いてみると、この画像のようなファイルの一覧が現れました。この中に「text.hex」というファイルができています。これをメモ帳などのテキストエディタで開いて見ましょう。

hexファイルの中身

 hexファイルを覗いてみると、こんな感じです。16進数を表す文字の羅列です。また、先頭は:(コロン)になっていますね。:から始まって改行コードまでの一行をレコードと呼び、このレコードごとに処理します。

Intel HEX ファイルフォーマット

 ではそのレコードの構造を見てみましょう。先ほどのhexファイルの一行目です。

: 10 0000 00 0428 FF3F FF3F FF3F 0313 8312 8601 8316 3F

 文字の羅列ですが、意味上の区切り(フィールド)に分けることができます。先の例をフィールド毎に色分けしてみました。それぞれのフィールドには次のような意味があるのです。カッコ内の数字は決められたバイト数です。

RECORD MARK(1) REC LEN(1) LOAD OFFSET(2) RECTYPE(1) INFO or DATA(n) CHKSUM(1)

 それぞれの意味を見ていきましょう。

RECORD MARK

 レコードの開始を示す文字です。':'(コロン)記号(文字コード3AH)1バイトが用いられます。

REC LEN

 後で出てくる、INFO or DATAフィールドのバイト数を表します。文字数ではありませんのでご注意下さい。データ列は2文字で1バイトを表します。つまり、文字が32個だと16バイト分ということになります。最大値は255(FFH)です。つまり、255バイト分のデータを一レコードに格納できるということです。

 先の例では、10Hバイト、つまり16バイト=8ワード分ということになります。

LOAD OFFSET

 このフィールドで、データ列を先頭から何バイトオフセットして書き始めるかを16ビットの数値で指定します。バイト単位ですのでご注意を。特にPICマイコンですとデータ列はワード単位ですから、このLOAD OFFSETの値は実際のアドレスの2倍になりますので注意が必要です。

 データ列以外では意味を為しませんので、データ列ではないレコードの場合は四つの0の文字が入っています。

RECTYPE

 レコードの内容を指定するフィールドです。次の6種類が定義されているようです。mikroCが出力するhexファイルでは、今のところ'00'と'01'だけしか見たことがありません。

00データレコード
01ファイル終了レコード
02拡張セグメントアドレスレコード
03スタートセグメントアドレスレコード
04拡張リニアアドレスレコード
05スタートリニアアドレスレコード

 mikroCが出力するhexファイルでは、'00'のレコードが全てで、最後に'01'のレコードが必ず現れるようです。その他は省略しますというかよくわかりません。

INFO or DATA

 0〜255個の可変長フィールドです。先ほどのREC LENフィールドでバイト数が規定されています。16進数を表す2文字で1バイトを表します。ここのフィールドが何を表しているかはRECTYPEフィールドにて規定されます。

CHKSUM

 データ列のチェックサムです。RECLENフィールドからINFO or DATAフィールドの最後まで、2文字1ペアで1バイトとした数の和を計算し、その結果の2の補数がここの値になっています。

 先ほどの一行目を計算してみましょう。

 また、RECLENフィールドからCHKSUMフィールドまで2文字1バイトずつ全て足すと、下位8bitは必ず00Hになります。

mikroCのhexファイル

 mikroCが出力したhexファイルを改めてもっと詳しく見ていきましょう。2行目まで見てみます。

: 10 0000 00 0428 FF3F FF3F FF3F 0313 8312 8601 8316 3F
: 10 0010 00 8601 8312 8609 0630 FC00 FF30 FB00 FF30 AA

 REC LENフィールドはそれぞれ10ですから、各行10Hバイト、つまり16バイト分のデータがあることがわかります。

 LOAD OFFSETフィールドは1行目=1レコード目が0000H、2レコード目が0010Hとなっています。1レコード目のデータはアドレス0000H番地から、2レコード目のデータはアドレス0010H番地から書けばいいのでしょうか???

 RECTYPEフィールドは00ですので、後に続くのはデータフィールドということが指定されています。

 INFO or DATAフィールドは32文字、16バイトのデータが記録されています。先ほどのREC LENの通りですね。また、CHKSUMも計算してみてください。正しいはずです。

 ところで、PIC16F628Aではプログラム領域・コンフィギュレーションレジスタは1アドレスに14ビットのデータを保存します。また、この14ビットを1ワードとします。従って、不要な2ビットが出ますが、hexファイル上では2バイトで1ワードを表します。ということは、REC LENで16バイトと指定されていれば、8ワード分のデータが記録されていることがわかります。確かに、8ワード分ありますね?

 この各データは、リトルエンディアンといって、上位8ビットと下位8ビットがひっくり返っています。ですから、1ワードごとに見ていくと、先頭から2804 3FFF 3FFF...という値を書いていかなければなりません。

 ちなみに、データ領域は8ビット単位ですが、mikroCが出力するデータ領域のhexファイルは16ビット単位です。これもリトルエンディアンですので上位・下位8ビットをひっくり返し、ひっくり返した後の下位8ビットのみを使用します。なんで8ビットずつにしないんだろう?と思いましたが、両方同じ16ビットにしておけば書き込み時に便利なのでした。なお、今のところデータ領域のデータは出力する設定にしていませんので詳しくは扱いません。

 このデータ列は先頭から順に並んでいます。連続するレコードのデータ列は必ずしも並んでいません(間を飛ばして飛ぶことがあります)が、同じレコード内のデータ列は必ず並んでいます。ということは、1レコード目はLOAD OFFSET0000Hで、先頭から並んでいますので、プログラム領域のアドレスと対比させてみると次のようになります。

0000 2804
0001 3FFF
0002 3FFF
0003 3FFF
0004 1303
0005 1283
0006 0186
0007 1683

 だんだんイメージが見えてきました。つまり1レコード目は、アドレス0000から0007までのプログラム領域のデータを記録していたのですね。

 では2レコード目ですが、今度はLOAD OFFSET0010ですね。だからアドレス0010から埋めて行けばいいのです。と思ったら大間違い。LOAD OFFSETはバイト単位なので、0010H、つまり16バイト目からだから、8ワード目から書き込まなければなりません。8ワード目というと、プログラム領域のアドレス0008H、ということになります。以上を踏まえて、続けて整理してみましょう。

0008 0186
0009 1283
000A 0986
000B 3006
000C 00FC
000D 30FF
000E 00FB
000F 30FF

 hexファイルに何が書いてあったのか、おぼろげながら見えてきました。何か、どこかで見たような数字だと思いませんか?思いませんね・・・。これは、前回アセンブラソースを見るで開いて見たときに出てきたアドレスとデータなんです。この数字をたよりにPICマイコンが動いてくれるんですね。ハハァ〜

 それと見比べてみると、データがないアドレスについては3FFFで埋められているようですね。ちなみに3FFFは2進数に直すと0011 1111 1111 1111ということで、下位14ビット全てが1となっています。命令が何もないところは、この3FFFとなっているようです。PIC16F628Aの内部は14ビットなんだなぁっていうのが何となく垣間見えますね?

全体をチェック

 整形してみました。するとこんな感じです。

0000: 2804 3FFF 3FFF 3FFF 1303 1283 0186 1683 :3F
0008: 0186 1283 0986 3006 00FC 30FF 00FB 30FF :AA
0010: 00FA 0BFC 2814 281B 0BFB 2817 281A 0BFA :C4
0018: 2817 2814 2811 301A 00FB 30FF 00FA 0BFB :98
0020: 2822 2825 0BFA 2822 281F 3042 00FA 0BFA :12
0028: 2827 2809 282A 3FFF 3FFF 3FFF 3FFF 3FFF :98
2000: ---- ---- ---- ---- ---- ---- ---- 3FF9 :78

 アドレス0028の行を見てみましょう。3FFFが並んでいますね。どうやら、プログラムがない部分は8ワード単位でキリがいいところまで3FFFで埋めるようです。

 そしてその次の行、遠く飛んだ2007番地にひとつだけデータがあります。これがコンフィギュレーションレジスタの値です。プロジェクト作成のときに「Device Flags」のチェックをしましたよね?あの値がここに入るわけですね。

 ここまででhexファイルの中身がわかったので、これを踏まえてPICマイコンへプログラムをダウンロードしてみましょう。

 せっかくなので、上記に使ったmikroCのhexファイルを整形するPerlスクリプトをこっそり載せておきます。PIC16F628A用のhexファイル以外使えないかもしれませんが、何か使えます?

PIC PICの一年生