(toppers-users 1940) Re: H8S、非タスクコンテキストでの割込みについて質問
二村誠示
snimura @ icrl.mew.co.jp
2005年 2月 16日 (水) 21:01:27 JST
松下電工の二村です。
お世話になっております。
H8SへのToppers移植において、割込み制御モード1への対応のために
修正を行った点について、ご連絡いたします。
修正点を簡単にまとめますと以下の通りです。詳細については、最後に載せます。
なにかお気づきの点などありましたら、ご指摘いただきたいと思います。
○cpu_config.h
・MAX_IPMを7から3へ変更(ccrのI,UIビット操作をMAX_IPMのビットシフトで行えるようにするため)
・chg_ipm/get_ipmのサポート解除
・割込みハンドラ入り口処理(_INTHDR_ENTRY)のexr操作をccr操作に変更
・割込みレベル設定用マクロ(icu_set_ilv)を修正
○cpu_config.c
・割込みレベル初期化処理修正(icu_set_ilvの修正に合わせて)
○cpu_support.S
・タスクディスパッチャ内のexrによる割込み禁止/許可をccrによる割込み禁止/許可に変更
・割込みハンドラ出入り口処理内のexrによる割込み禁止/許可をccrによる割込み禁止/許可に変更
・タスク起動処理内のexrによる割込み許可をccrによる割込み許可に変更
○cpu_insn.h
・割込みマスク制御用マクロ処理をexr操作からccr操作に変更
といったところです。
現在、岩沢様にご指摘いただいたようにH8のソースを参考にしようと思い、まずは
H8/3048Fのハードウェアマニュアルにて割込み制御の方法を確認中です。
ざっと見たところ、H8Sの割込み制御モード1と同様の方法のようなので、参考に
できそうかな、と感じています。
以下、修正点の詳細になります。ソースコードを載せてしまっているため、非常に
見にくくなっていますが、ご容赦下さい。
-------------------------------------------------------------------------------------------
-------------------- ◆割込み制御モード1対応のための変更点 -------------------------------
-------------------------------------------------------------------------------------------
【cpu_config.h】
・MAX_IPMの値を7から3に変更(ccrのIビットとUIビットへのマスク処理をビットシフトで対応するため)
#define MAX_IPM 3
・chg_ipm/get_ipmをサポートしないように変更
/*#define SUPPORT_CHG_IPM*/
・割込みハンドラ入口処理において、exr操作部分をccr操作に変更
#define _INTHDR_ENTRY(entry, inthdr) \
asm(" .text \n" \
" .align 2 \n" \
" .global _"#entry" \n" \
" \n" \
"_"#entry": \n" \
" push.l er0 \n" \
/* CPUロックに必要なレジスタをタスクスタックに待避 */ \
/*" stc.b exr, r0l \n" */ \
/* exr を r0l (er0) にコピー \
" (_kernel_ret_main 内で、割込み禁止許可制御に使う) */ \
/*" \n" */ \
/*" ldc.b #"str_MAX_IPM", exr \n" */ \
/* lock_cpu 相当 (割込み禁止) */ \
/*" \n" */ \
" stc.b ccr, r0l \n" \
/* ccr を r0l (er0) にコピー \
" (_kernel_ret_main 内で、割込み禁止許可制御に使う) */ \
" \n" \
" orc.b #0xc0, ccr \n" \
/* lock_cpu 相当 (割込み禁止) */ \
" \n" \
" push.l er1 \n" \
/* er1 をタスクスタックに待避 */ \
" mov.l #_"#inthdr", er1 \n" \
/* er1 = 割込みハンドラのアドレス */ \
" jmp _kernel_ret_main \n" \
/* 割込み入口処理へジャンプ */ \
)
・割込みレベル設定用マクロをレベル0/1の指定のみに変更
/*
* 割込みレベル設定用マクロ(もしくは、インライン関数)
* ・x : インタラプトコントロールレジスタ (ICRA - ICRC)
* ・y : ICR設定用マスク(設定ビット) (BIT7 - BIT1)
* ・z : 割込みレベル (0 - 1)
* 2005/01/15 h8s2145用 二村修正
*/
Inline void icu_set_ilv( VP icr, UB mask, INT level ) {
if( level == 1 ) {
h8s_orb( icr, mask );
} else if( level == 0 ) {
h8s_andb( icr, ~mask );
}
}
【cpu_config.c】
・割込みレベル初期化処理を、割込みレベル設定用マクロの変更に合わせて修正
/* 割込みレベルの初期化 */
icu_set_ilv( (VP) ICRA, ICR7, 0 );
(以下、割込みコントロールレジスタの全ビットをセット)
【cpu_support.S】
・タスクディスパッチャ内の処理(dispatcher_2_enable_interrupt)にてexrによる
割込み禁止/許可をccrによる割込み禁止/許可に変更
/*#ifdef SUPPORT_CHG_IPM*/
/* ldc.b @_task_intmask, exr unlock_cpu相当(割込み許可) */
/*#else SUPPORT_CHG_IPM */
/* ldc.b #0, exr unlock_cpu相当(割込み許可) */
/*#endif SUPPORT_CHG_IPM */
andc.b #0x3f, ccr /* unlock_cpu相当(割込み許可)B'00111111とCCRの& */
sleep /* 割込み待ち */
/* ldc.b #MAX_IPM, exr lock_cpu 相当 (割込み禁止) */
orc #0xc0:8, ccr /* lock_cpu相当(割込み禁止)B'11000000とCCRのOR */
・割込みハンドラ出入り口処理内の多重割込みの処理(multipul_exception)にて
exrによる割込み禁止/許可をccrによる割込み禁止/許可に変更
/* ldc.b r0l, exr (現在の割込みレベル以上)割込み許可 */
ldc.b r0l, ccr
jsr @er1 /* 割込みハンドラ呼出 */
/* ldc.b #MAX_IPM, exr lock_cpu 相当 (割込み禁止) */
orc #0xc0:8, ccr /* lock_cpu相当(割込み禁止)B'11000000とCCRのOR */
・割込みハンドラ出入り口処理内の初段の割込みの場合(first_exception)にて
exrによる割込み禁止/許可をccrによる割込み禁止/許可に変更
/* ldc.b r0l, exr (現在の割込みレベル以上)割込み許可 */
ldc.b r0l, ccr
jsr @er1 /* 割込みハンドラ呼出 */
/* ldc.b #MAX_IPM, exr lock_cpu 相当 (割込み禁止) */
orc #0xc0:8, ccr /* lock_cpu相当(割込み禁止)B'11000000とCCRのOR */
・割込みハンドラ出入り口処理内の遅延ディスパッチ/タスク例外に関する処理
(occur_dispatch_or_tsk_exception)にて、割込み発生箇所の判定処理変更
mov.b @(EXR_offset, sp), r0l /* r01 = スタック上のEXR */
/* and.b #EXR_I_MASK, r0l r01 = スタック上の割り込みマスク */
and.b #CCR_I_UI, r0l
shlr.b #2, r0l /* I,UIビットが7,6ビット目のため、 */
shlr.b #2, r0l /* 1,0ビット目にビットシフト */
shlr.b #2, r0l
・タスク起動処理内のexrによるCPUロックの解除をccrによるCPUロックの解除に変更
/*#ifdef SUPPORT_CHG_IPM */
/* ldc.b @_task_intmask, exr unlock_cpu相当(割込み許可) */
/*#else SUPPORT_CHG_IPM */
/* ldc.b #0, exr unlock_cpu相当(割込み許可) */
/*#endif SUPPORT_CHG_IPM */
andc.b #0x3f, ccr /* unlock_cpu相当(割込み許可)B'00111111とCCRの& */
【cpu_insn.h】
・割込みマスクの読出し関数をccrでのマスク読出しに変更
Inline IPM current_intmask(void)
{
// return( (IPM) (current_exr() & EXR_I_MASK) );
/*
* I,UIは7,6ビット
* 6ビットシフトさせ、IPMを0〜3の範囲にする
*/
return( (IPM) ( (IPM) (current_ccr() & CCR_I_UI ) >> 6 ) );
}
・割込みマスクの設定関数をccrでのマスク設定に変更
Inline void set_intmask(IPM intmask)
{
// set_exr( (IPM) ((current_exr() & ~EXR_I_MASK) | intmask ) );
/*
* I,UIビットは7,6ビット
* intmaskが0〜3なので6ビットシフトさせて対応
*/
set_ccr( (IPM) ((current_ccr() & ~CCR_I_UI) | (intmask << 6)) );
}
・disint()関数をccrによる割込み禁止に変更
Inline void disint(void)
{
/* set_intmask( (IPM) MAX_IPM ); */
// set_exr( (IPM) ((current_exr() & ~EXR_I_MASK) | MAX_IPM ) );
set_ccr( (IPM) (current_ccr() | CCR_I_UI ) );
}
・enaint()関数をccrによる割込み許可に変更
Inline void enaint()
{
/* set_intmask( (IPM) 0 ); */
// set_exr( (IPM) (current_exr() & ~EXR_I_MASK) );
set_ccr( (IPM) (current_ccr() & ~CCR_I_UI) );
}
・割込みロック状態の制御用関数をccrによる制御に変更
Inline void _disint_()
{
/* set_intmask( (IPM) 7 ); */
// set_exr( (IPM) (current_exr() | EXR_I_MASK) );
set_ccr( (IPM) (current_ccr() | CCR_I_UI) );
}
------------------------------------------------------------------------------------------