AVRの割込ベクタアドレス †
Tag: AVR
普段はtiny2313を使っている*1のですが、初めてmega168を使ってドハマりしたのが割込ベクタの書き方でした。
今時普通Cで書くでしょうから気付き難い&判ってしまえばアタリマエなんでしょうが、僕のような右も左もわからないド素人は、気付くのに3日程必要でした。(^^;
さて、まずはtiny2313のベクタアドレスをアセンブラで書いた時はこんなカンジですよね。
.cseg rjmp reset rjmp ext_int0 rjmp ext_int1 ;以下略
で、初めてmega168を使う時に、以前tiny2313で書いたソースを引っ張ってきて、データシート見て割込の種類だけ見て変えて動かしてみたら、どうも動きが変なんですよ。
結局、判明した大ボケの原因は、
相対ジャンプと絶対ジャンプの違い
だったワケなんです。
mega168はプログラムメモリがデカいので、相対ジャンプでは飛びきれないので絶対ジャンプで飛ぶのが作法なんです。
だから、割込ベクタは1ワードでなく2ワードになっており、相対ジャンプで書くと割込ベクタの位置がズレるんです。
途中で薄々感付いてはいたのですが、じゃあ2ワードにするには具体的にどう書くのよ?となり、ゴリ押しでこう書いたら思う通りに動いたワケです。
.cseg .org $0000 rjmp reset .org $0002 rjmp ext_int0 .org $0004 rjmp ext_int1
でもなんか納得が行かないモンで、三串のコミュで相談してみた所、
何故絶対ジャンプで書かない?
というお返事・・・そこでやっと相対ジャンプと絶対ジャンプの違いにハッ!と気付くワケです。
根本の敗因は、
絶対ジャンプの存在忘れてた
事ですかね。
いや、命令の存在は知ってたし、違いがなんたるかは分かっているつもりだったんですよ。
けど、今までTiny2313で小規模なプログラムばかり組んでいたので、絶対ジャンプの
存在意義を考えた事すら無かった
訳ですよ。
むしろ今まで参考にしてきたソースは、全て相対ジャンプ使ってたので、
そういうモンだ
という程度の認識だったワケですね。
そして、rjmpとjmpをコンパイルして実際に出てくるコードの違いを理解してなかった事です。
「rjmp」だと1ワードなんですが、「jmp」だと2ワード使うんです。
だから本来「jmp」と書くべき場所に「rjmp」を書いてしまうと、1ワードづつズレて行くワケなんですね。
言われてみれば、ああそうか!で済むツマラン事なんですが、ド初心者はソコに注目出来なかったワケです。(^^;
結局こう書けば済んでた事でした。
.cseg jmp reset jmp ext_int0 jmp ext_int1 ;以下略
素直にデータシートからコピペしてりゃスンナリ動いてたのに、中途半端に動かせる自信がついたモンですから、色々と回り道をしてしまったワケです。(^^;;;;;;