H8向けVer2コンパイラによる割り込みルーチンの記述
Copyright(C) 20June2003 coskx TNCT
1.はじめに
「Ver2コンパイラ」になり,記述性が少し進歩したため,Cソース中のにインラインでasm記述ができるようになった。そのため,Cソースファイルだけで,割り込みに関する記述が1箇所に集中してできるようになった。
入門用環境では,割り込みに関しては,タイマ割り込みのみ紹介し,割り込みのメカニズムは隠して紹介している。しかし,割り込みに関する記述がCソースファイル中に集中して書けるようになったため,中級者が学びやすくなっている。
このページでは,プログラム記述バリエーションについて述べる。
ファイルのダウンロード
DownLoad |
2.「Ver2コンパイラ」になり,できるようになったこと
(1)Cソース中のにインラインでasm記述ができるようになった
(2)文字列定数中に漢字が使えるようになった
(3)コンパイラがasmコードを出力することができるようになった。 これは,Cプログラムとasmプログラムを比較でき,入門者にとってよい勉強になる。
(4)リストの出力ができるようになった。
3.前提
(1)「Ver2コンパイラ」として配布されたCD中のフォルダ「H8Tools\DEVELOP\VER2.0」が「C:\Program Files\h8v2」にコピーされているものとする。
C:\Program Files\h8v2
|
|---BIN
|---INCLUDE
|---LIB
(2)適当なフラッシュメモリ書き込みツールが用意されている
(3)フォルダ「C:\Program
Files\h8v2\LIB」中に「start3048.OBJ」「start3048I.OBJ」が入っているものとする。
4.割り込みの記述と割り込み動作
設定した時間ごとに励起されるタイマ割り込みについて解説しよう。
タイマ割り込みを起動させるには次の3つのことが必須である。
(1)ベクタテーブルの所定の位置に割り込み関数のアドレスを書いておく。
(2)割り込み関数の最初と最後にレジスタの退避と復帰を書いておく。
(3)プログラムの最初にタイマ割り込みの初期化により,タイマユニットに割り込み周期,割り込み要因を設定しておく。
実際にタイマユニットが割り込み信号を発すると,その信号により,ベクタテーブルからタイマ割り込みに対応した割り込み関数のアドレスを取り出し,その関数を実行する。
すなわちプログラミングにおいては,
(1)ベクタテーブルにタイマ割り込み関数のアドレスを設定する
(2)割り込み関数の最初と最後にレジスタの退避と復帰を行なうようにする
の2つを書くことが通常のプログラムと異なる点である。
(1)ベクタテーブルにタイマ割り込み関数のアドレスを設定するには,Cソースプログラムにおいて次の記述ができる
(2)割り込み関数の最初と最後にレジスタの退避と復帰を行なうようにするには,Cソースプログラムにおいて次の記述により,コンパイラが自動的に退避・復帰コードを生成する。
#pragma asm
.SECTION MYVEC, DATA, LOCATE=H'000070
.ORG H'000070 ;IMIA1
.DATA.L _TimerIntFunc
.SECTION P,CODE,ALIGN=2 ;これを忘れてはいけない
#pragma endasm
#pragma interrupt (TimerIntFunc)
void TimerIntFunc() /*タイマ割り込みルーチン*/
{
clearTimer1Flag(); /*タイマステータスフラグのクリア 忘れないこと*/
if (tick==1) {
P5.DR.BYTE=1;
} else {
P5.DR.BYTE=2;
}
if (++loop==50) {
tick=1-tick;
loop=0;
}
}アドレス70の位置に
TimerIntFuncの
アドレスを格納
TimerIntFuncは
割り込み関数である
5.割り込みプログラム記述バリエーション
4つの記述バリエーションを紹介する。
実用上は
初心者:(1)の方法
中級者:(2)の方法
がお勧めとなる
概要 |
割り込みの無い例 | 割り込みのある例 |
コンパイルCMD |
リンカスクリプト |
スタートアップ | |
(1) | 初心者向け スタートアップルーチンやタイマ割り込みの舞台裏は提供されたものをそのまま使う。 タイマ割り込みのあるCプログラム(タイマ割り込み関数名は固定)が書ける。 割り込みベクタ,割り込み関数特有の操作はスタートアップルーチン中に隠されている。 |
LEDtest.c |
LEDinttest.c |
h8_3048I.cmd |
自動生成 |
start3048I.OBJ |
(2) | 中級者向け スタートアップルーチンは提供されたものを使う。 割り込み部分(割り込みベクタ,割り込み関数)は,自分でCプログラム中に記述する。 |
LEDtest.c |
LEDinttest.c |
h8_3048.cmd |
h8_3048.sub |
start3048.OBJ |
(3) | 中級者向け スタートアップルーチンはasmソースで自分で用意する。 割り込み部分(割り込みベクタ,割り込み関数)は,自分でCプログラム中に記述する。 |
h8_3048B.cmd |
h8_3048.sub |
自分で用意 | ||
(4) | 中級者向け スタートアップルーチンはインラインasmを使う。 割り込み部分(割り込みベクタ,割り込み関数)もすべて,自分でCプログラム中に記述する。 |
LEDtest.c |
LEDinttest.c |
h8_3048B.cmd |
h8_3048.sub |
インラインで記述 |
メモリ配置に関するリンカオプション(リンカスクリプト)は共通で次のようになっている。
: ROM (D,X) : START P,C,D(100),X,B(0FEF10) |
6.「#pragma interrupt」の役割の検証
「#pragma
interrupt」の役割をテストプログラムで見てみよう。
このCソースプログラムで関数「testfunc1()」と関数「testfunc2()」は作業は同じだが,関数「testfunc1()」は割り込み関数であると宣言されている。
Cソースプログラム |
int a=0; |
コンパイラが生成したasmソースでみると,関数「testfunc1()」では,関数の初めに利用しているレジスタの退避コードがあり,関数の終わりにレジスタの復帰コードが生成されている。さらに関数の終わりは,関数「testfunc1()」では,「RTE」(ReTurn
from Exception)で終了し,関数「testfunc2()」では,「RTS」(ReTurn from
Subroutine)で終了しているのが分る。
コンパイラが生成したasmソース |
_testfunc1: PUSH.W R1 PUSH.L ER0 ; MOV.L #_a:32,ER0 ;a++; MOV.W @ER0,R1 ; : INC.W #1,R1 ; : MOV.W R1,@ER0 ; : ; POP.L ER0 POP.W R1 RTE ; _testfunc2: MOV.L #_a:32,ER0 ;a++; MOV.W @ER0,R1 ; : INC.W #1,R1 ; : MOV.W R1,@ER0 ; : ; RTS |
参考 コンパイラのバージョン
トランジスタ技術誌が2002年3月に「H8向けVer2コンパイラ」をCDROMで配布した。以下「Ver2コンパイラ」と呼ぶ。
AKI−H8の開発では秋月が販売しているコンパイラが用いられている。これは「評価版Ver1」と呼ぶ。
2つのバージョンを比較すると次のようになる。
「評価版Ver1」(秋月CDROM) |
H8/300H C COMPILER(Evaluation software) Ver.1.0 H8/300H ASSEMBLER (Evaluation software) Ver.1.0 H8/300H LINKAGE EDITOR (Evaluation software) Ver.1.0 H8/300H OBJECT CONVERTER (Evaluation software) Ver.1.0 |
「H8向けVer2コンパイラ」(トランジスタ技術誌が2002年3月CDROM) |
H8S,H8/300 SERIES C Compiler Ver. 2.0D Evaluation
software H8S,H8/300 SERIES CROSS ASSEMBLER Ver. 2.0A Evaluation software H SERIES LINKAGE EDITOR Ver. 5.3B Evaluation software H SERIES SYSROF STYPE OBJECT CONVERTER Ver. 1.5B Evaluation software |