(toppers-users 1860) H8/3048Fでの割り込みハンドラ利用手順に関する質問です.

Yuki WAKUDA wakuda @ robo.mein.nagoya-u.ac.jp
2005年 1月 29日 (土) 06:46:22 JST


関係者の皆様へ

始めまして,
名古屋大学工学研究科の学生で,
湧田と申します.

現在,H8を搭載した実機へのjspカーネル実装を行っています.

開発環境は,cygwin上のgccでmakeし,毎回FLASH書き込みにてデバッグしています.
ターゲットはAki-H8/3048Fに1MbitのSRAMを増設し,CPUモード6にて動作テスト中です.

これまで,組み込み初心者なりに苦心してどうやら動くようになってきているのですが,割り込みに関して,どうしても自分では解決できそうにな
く,メーリングリスト過去ログやマニュアルを読んだり実機で試行錯誤をしても全く解決の糸口が見つからないので,質問させていただきます.

HW割り込みやタイマ割り込みなど,割り込み機能を使いたいのですが,タイマ割り込み,IRQ,どちらで試しても,割り込みがかかった段階で,OS
が停止してしまいま
す.
長文になりますが,IRQ1とITU2タイマ割り込みに関して,現在行っている割り込み機能実装に関して以下の手順で間違っている点,足りない点等あ
りましたら,アドバイスいただければありがたく思います.
以下は,jsp-1.4セットに付属のサンプルsample1.cを改造して行っています.
=======================================================

1.カーネルへの割り込みハンドラの登録
./sample/sample1.cfg内に
DEF_INH(13,  /*13:IRQ_EXT1 定義対象割り込みハンドラ番号*/
 {TA_HLNG,   /*割り込みハンドラ属性*/
 irq1_handler }); /*割り込みハンドラの起動番地*/
DEF_INH(32,  /*32:IRQ_IMIA2 定義対象割り込みハンドラ番号*/
 {TA_HLNG,  /*割り込みハンドラ属性*/
 imia2_handler }); /*割り込みハンドラの起動番地*/
などを定義し,

2.
./sample/sample1.h内に
extern void irq1_handler(void);  /**/
extern void imia2_handler(void); /**/
を追加.

3.ベクタテーブルへの登録
./config/h8/akih8_3048f/sys_support.S内,割り込みベクタテーブルの対応した箇所に割り込み入り口へのアドレスを指定
 .long _no_reg_exception  /* 13, 0x0034: IRQ1 */
 .long _no_reg_exception  /* 32, 0x0080: IMIA2 */
  上記を↓↓↓下記のように書き換え
 .long _irq1_handler_entry    /* 13, 0x0034: IRQ1 */
 .long _imia2_handler_entry    /* 32, 0x0080: IMIA2 */
 (inthdr##_entryはINT_ENTRY(inthdr)によって自動的に生成されると認識しています)

4.割り込み出入り口処理の追加
cpu_support.S内にて,
/* IRQ1   */
 .globl _irq1_handler_enable_int
_irq1_handler_enable_int:
 rts
/* ITU2   */
 .globl _imia2_handler_enable_int
_imia2_handler_enable_int:
 rts
/* IRQ1   */
 .globl _irq1_handler_disable_int
_irq1_handler_disable_int:
 rts
/* ITU2   */
 .globl _imia2_handler_disable_int
_imia2_handler_disable_int:
 mov.l #0xFF7B, er0    /*ITU2用IMFAフラグのクリア*/
 bclr #0, @er0
 rts
以上を自力で付加.

5.割り込みがかかったときの関数の記述
./sample/sample1.c内に実際の関数を記述する.
void irq1_handler(void){
syslog(LOG_NOTICE, "I'm irq!",0);
}
void imia2_handler(void){
syslog(LOG_NOTICE, "I'm IMIA2!",0);
}

6.初期化と実行
最後に初期化の記述をし,
実行するプログラム中で割り込みを許可する.

【IRQについて】
#define H8IER   0xfffff5  /*IRQイネーブルレジスタ*/
  と宣言してあるので,
*(volatile UB*)H8IER |= 0x02;  /*IRQ1割り込み許可セット*/
  以上によりIRQ1に対応したポートを接続したボタンを押下することで割り込みが発生する予定.

【IMIA2について】
#define w_TSTR 0xffff60                       /*初期値0xE0*/
#define w_ITU2_TCR (H8ITU2 + H8TCR)  /**/
#define w_ITU2_TCR_BIT (H8TCR_CCLR0 | H8TCR_TPSC1 | H8TCR_TPSC0) /*GRAのコンペアマッチでTCNTをクリア*/
#define w_ITU2_TCNT (H8ITU2 + H8TCNT)  /*ITU4のTCNTカウンタの値*/
#define w_ITU2_GRA (H8ITU2 + H8GRA)    /**/
#define w_TIER2  (H8ITU2 + H8TIER)  /* タイマインタラプトイネーブルレジスタ*/
#define w_TIER2_BIT (H8TIER_IMIEA)   /* 0x01 IMIEA:TIERレジスタのうちIMFAフラグによる割り込みのみ許可*/
#define w_TIOR2  (H8ITU2 + H8TIOR)  /* タイマI/Oコントロールレジスタ*/
#define w_TIOR2_BIT (H8TIOR_IOA1)   /* 0x02 GRAのコンペアマッチで1出力*/
  と勝手に宣言した上で,以下のように初期化
*(volatile UB*)w_ITU2_TCR |= w_ITU2_TCR_BIT; /* ITU2用TCR設定 */
*(volatile UH*)w_ITU2_GRA = 20000;   /*GRA2を 20000(10msec)に設定*/
*(volatile UB*)w_TIER2 |= w_TIER2_BIT;  /* w_TIER2_BIT=0x01 IMIA2をIMFAフラグによる割り込み許可に設定*/
*(volatile UB*)w_TIOR2 |= w_TIOR2_BIT;  /* w_TIOR2_BIT=0x02 GRAのコンペアマッチで1出力に設定*/
*(volatile UB*)w_ITU2_TCNT = 0;  /*TCNT2カウンタクリア*/
  その後,ITU2のTCNTカウント開始する
*(volatile UB*)w_TSTR |= 0x04;   /*ITU2 動作開始*/
  以上により10msecごとに割り込みがかかる予定.

=======================================================

以上のような手順で割り込み機能の追加を試みていますが,
IRQ1を用いて対応したボタンを押した場合,または,IMIA2を用い,カウントを開始した場合,どちらも,同様にカーネルが停止(もしくはsyslog
による出力が反応なし)してしまいます.
予定していた“I'm irq1 !”などの出力も無く,前後にあるsyslogの出力途中などで止まったりするという症状です.

sys_support.S内のベクタテーブルでの対応する箇所を変更せず,“_no_reg_exception”のままになっている場合には,割り込みに対応して,きち
んと_no_reg_exceptionが呼び出されていることから,割り込み自体は,かかっていると思っているのですが.

また,わざと_no_reg_exceptionに飛ばして,その中のcpu_experr()を書き換えて利用すれば,割り込みが機能してもカーネルが停止することな
く,延々と割り込み処理をかけることはできました.

 ということで,予想としては,割り込み要求と,ジャンプ先のirq1_handler()などの対応関係ができていないか,もしくは,割り込みの出入り口
処理の途中で止まってしまっているように見えるのですが,
これ以上進みません.
経験のある方,アドバイスいただけますでしょうか.

また,_irq1_handler_entryなどは実体が見当たりませんが,上述のように,sys_support.Sでは_irq1_handler_entryを指定するという形式で合っ
ているのでしょうか.

以上よろしくお願いいたします.

湧田 雄基