プログラミングと工作と

PythonとかPascalとかAVRマイコンとか、コンパイラつくったり電子工作なんかを楽しんでいるおっさんの記録

AVRマイコン アセンブリ言語入門 ― 割込み動作

  • 割込み動作ってなに?

ある人曰く、マイクロプロセッサの最大のイノベーションは割込み動作、だそうです。
基本的に、ひとつのプロセッサは一度にひとつの処理しか出来ません。
割込み動作とは、プロセッサが一生懸命ある処理をしている途中で、「あ、俺の仕事を優先で、」と横から割り込んでプロセッサの処理動作を奪い取ることです。

 

  • 割込みってどんな仕組みなの?

マイクロプロセッサの動作をちょっとでもわかっていれば、割込み動作の仕組みは簡単です。
AVRマイコンでいうと、我々が書いたプログラムはフラッシュメモリエリアへ書き込まれます。
マイコンは、電源を入れたりリセットボタンを押されたりすると、このフラッシュメモリの0番地から命令を読み込んで動作を開始します。
その後も番地を一つ進めて命令を読み込む、また一つ番地を進めて読み込む・・・をひたすら続けていきます。
ちなみに、このメモリ番地から命令を読み込む動作のことを「フェッチ」というみたいです(豆)。


この、読み込む番地を入れている場所をPC(プログラムカウンタ)と言います。
CPUは、このPCに入っている番地から命令を読み込もうとするので、処理の途中でPCの値を書き換えると、その番地へ飛んで行って命令を読み込もうとします。


そう、割込みが発生すると、PCの値を割込み処理のプログラムが書いてあるメモリ番地に書き換えます。
もうちょっと正確に言うと、割込みが発生すると、それぞれの割込み内容で決められているプログラムアドレスをPCに設定します。

例えば、8bitタイマ0 COMPAレジスタ一致割込みが発生すると0x001C番地をPCに設定する、と言った具合です。


この決められた番地それぞれに、実際の処理内容が書かれた番地へのジャンプ命令を書き込んで割込み処理をさせるという2段階右折状態で割込み処理へ飛んでいきます。


ここでいう「割込み内容に対応して決められた番地」の一覧を「割込みベクタテーブル」といいます。

ATmega48〜328シリーズの割込みベクタテーブルを書いておきます。

 

f:id:takashira:20151129184924p:plain

ややこしい話は置いておいて、割込みを使うには、

  1. 上の表から使いたい割込みのアドレスを調べる。
  2. そのアドレスに割込み処理へのジャンプ命令を書く。

まあ、基本はこれだけです。


.CSEG                           ←プログラムの先頭(0番地)を意味する
             RJMP    MAIN   ←MAINというラベルの処理へジャンプする
.ORG    0x001C     ←0x001Cへ飛んできたら
             RJMP    ICTC0 ←ICTC0ラベルの処理へジャンプする
.ORG    0x002A
             RJMP    ADCOK

 

上の例は定形表現みたいなものなので、ベクタアドレスの部分と、自分のプログラムのラベル部分に合わせれば、それだけで割込み処理の完成です。

 

  • 使用上の注意

「それだけで割込み処理の完成です」といった舌の根も乾かないうちになんですが、割込み処理を書く上でいくつかの注意点があります。


まずは「許可」が必要です。
各機能がそれぞれ勝手に割込みしまくったら、処理がめちゃくちゃになってしまいます。
割込みには「今なら割込みOKだよ」といった許可が必要になります。
これには2種類あって、

  1. 全割り込み許可
  2. 機能別の割込み許可

の2つを同時に満たしてはじめて割りこみが実行されます。

 

割込みを使うには、このような割込み許可を含めた初期設定が必要になりますが、その初期設定のやりかたは

  1. メインルーチンの最初に全割り込み禁止(CLI命令)を行う
  2. ポートの入出力や各種機能別の初期設定を行う
  3. 全割り込み許可(SEI命令)を行う

の順番で行います。

 

また、割込み初理中にほかの割込みを行う(多重割込みという)のは基本的に禁止されています。
割込み処理が発生すると、ハードウェアは自動的に全割り込みを禁止にします。
割込み処理が終了すると、自動的に再び許可に戻ります。


多重割込みを行いたい場合は、この辺をうまくコントロールしなければなりませんが、処理が複雑になるのでもっと先でやりましょう。

 

では、今回はこのへんで。