昨日から始まった マイコン向けバイナリの動作を見ていこうシリーズ第 2 回は「割り込みベクタ」です。
まず始めに割り込みベクタと割り込みが何かを簡単に説明しておきます。一般にコンピュータは 演算装置と入力装置、出力装置、そしてそれらを制御する制御装置からなっていますが、割込とは CPU の命令とは非同期に発生する入出力の完了などを制御装置に知らせる仕組みです。例えばユーザがスイッチを押したのを伝えたり、A/D 変換が完了したことを伝えたり、タイマがタイムアウトしたことを伝えたりするのが主な用途ですが、一方でゼロ割りが行われたり、メモリの R/W に失敗したときなどエラー系の通知にも使われます。パソコンだと CPU の割り込みは OS で管理されているため我々にはあまり馴染みがないかもしれませんが、分かりやすいアナロジーをあげると、イベントドリブンプログラムにおけるリスナー登録でしょうか。
通常は制御装置が割り込みを検知すると、通常は割り込みの種類ごとに決められたアドレスに CPU の処理が飛ぶことになっています。その「割り込みの種類ごと決められたアドレス」のことを割り込みベクタと言います。
割り込みベクタは通常 0 番地から割り込みの数だけ並んでいて、それぞれのベクタにはジャンプ命令が書かれています。実際に以下のようになっていました。「アドレス: アセンブリ命令 ; コメント」という型式になっています。
0 番地は リセット割り込みのベクタですが、電源を ON にしたことでリセットが起こるとプログラムカウンタが 0 番地をさして、次のサイクルで 0 番地に書かれている「 jmp 0x68」という「0x68 番地にジャンプしなさい」命令が実行されるといった具合です。今回のプログラムでは他に 18 番(シリアル受信割り込み)と 20 番(シリアル送信完了割り込み)に具体的なジャンプ先が設定されていること分かります。使わない残りのベクタはすべて 0xa2 へのジャンプになっています。そこで 0xa2 番地を見てみると、
となっており 0 番地に戻っているだけということが分かります。つまり、なんらかの不具合で予期せぬ割り込みが発生した場合にはマイコンにリセットがかかった状態と同じ処理をするということです。 これは avr-gcc がそうするようにしているだけであって、別に CPU 停止命令でもいいわけですが、次のアドレスは他の割り込みベクタなので 1 命令で済ます必要があり、殆どの場合において割り込みベクタにはジャンプ命令が書かれます。また、このベクタテーブルは私が書いたわけではありません。私が書いたのは用意されたマクロを使って割り込み関数を定義しただけです。おそらくそのマクロを使う事で、その関数が割り込み関数であることが gcc に伝わり、gcc は対応するベクタにその関数のアドレスへのジャンプ命令を設定するようになっているものと考えられます。
以上が割り込みベクタの説明です。割り込みを更に細かく分けると要因がマイコンの内部なのか外部なのか、またその割り込みをユーザが無視することができるのかできないのか、などの軸で割り込みもいろいろな種類に分かれますが、割り込みベクタに関しては皆同じです。
次回は 0x00 番地から 0x68 番地にジャンプして以降の処理について説明してみたいと思います。 0x68 番地に付けられたラベルが __main ではないので、すぐに main 関数が実行されるわけではないということは何となく察しがつきますが、さてさて何をやっているのでしょうか。












コメントする