(toppers-users 3184) M32CからR32C移植時の注意点

kouta wada kouta.wada @ konicaminolta.jp
2010年 4月 23日 (金) 17:13:59 JST


コニカミノルタセンシング派遣のKota Wadaと申します。

TOPPERS/ASP(M32C対応)をR32Cへ移植を行っています。

M32CのコンパイラNC308と
R32CのコンパイラNC100の違いにより、
つまづいた点がいくつかあります。
参考になれば思い、情報展開しておきました。

【発生した現象】
prc_support.a30の以下の箇所でタスクスタックポインタを
R3R1に退避しているが、Cルーチン実行後はR3R1が書きかわっている。

_kernel_interrupt:
	・・・(中略)・・・

	; 初段の割込み
	stc	isp,r3r1        ; スタックポインタを取り出し

	(Cルーチン実行)

	・・・(中略)・・・
	; 初段の割込み
	ldc	r3r1,isp        ; タスクのスタックに戻す

	・・・(中略)・・・

【原因】
Cルーチン実行時に多重割り込みが発生し、
R3R1を書きかえてしまっていた。

M32CコンパイラとR32Cコンパイラの違いの一つとして、
レジスタの退避があります。

(M32CのコンパイラNC308マニュアル抜粋)
C言語の関数を呼び出す場合のレジスタの退避規則を以下に示します。
(1) 関数の呼び出し側で退避するレジスタ
	R0 レジスタ
	呼び出す関数の戻り値に使用するレジスタ。
(2) 呼び出された関数の入口処理で退避するレジスタ
	R0 および戻り値に使用するレジスタ以外で、
	関数内で使用されるレジスタ。

(R32CのコンパイラNC100マニュアル抜粋)
C言語の関数を呼び出す場合のレジスタの退避規則を以下に示します。
(a)関数の呼び出し側で退避するレジスタ
	呼び出し側で使用するレジスタ。
(b)呼び出された関数の入口処理で退避するレジスタ
	退避しません

以上より、R32Cにおいて、アセンブラからCコードを呼び出すときは
注意が必要です。

【今回の対処方法】
すべての割り込みハンドラ処理内で全レジスタの退避・復帰を追加します。

例 (target_timer.c)
/*
 *  タイマ割込みハンドラ
 */
void
target_timer_handler(void)
{
#if 1	/* 追加 */
        i_begin_int(INTNO_TIMER);
#endif
	signal_time();       /* タイムティックの供給 */
#if 1	/* 追加 */
        i_end_int(INTNO_TIMER);
#endif
}

※i_begin_intとi_end_intに全レジスタの退避・復帰を
追加しました。

以上、参考になれば幸いです。