[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
CASSIOPEA report
鈴木(康)です。
<200006150132.KAA24421@ortmail.rt.osaka.omronsoft.co.jp>の記事において
kuwana@rt.osaka.omronsoft.co.jpさんは書きました。
|
| # vr_intr()変更後のサスペンドの調子は如何ですか?
| R530で追試したつもり・・なのですが、復帰できませんでした。
| もう少し、どこをどうすれば良いか教えてもらえないでしょうか?
---
いちおう修正点と注意点をまとめてみました。
追試して頂けると嬉しいです。
-----------------
1) 割り込み実行レベル IPL の設定
mips では、IPL 制御をしていないので、いれてみることにする。
machdep.c:cpu_intr()
if (ipending & MIPS3_HARD_INT_MASK) {
_sepset((*platform.iointr)(status, cause, pc, ipending));
}
となっている部分を
if (ipending & MIPS3_HARD_INT_MASK) {
(*platform.iointr)(status, cause, pc, ipending);
}
に変更して、vr.c:vr_intr() 実行前に IPL を設定
if (ipending & MIPS_INT_MASK_1) {
_spllower(MIPS_SPL_0_1);
(*intr_handler[1])(intr_arg[1], pc, status);
}
if (ipending & MIPS_INT_MASK_0) {
_spllower(MIPS_SPL0);
(*intr_handler[0])(intr_arg[0], pc, status);
}
次に netintr() 実行前に
_spllower(MIPS_SOFT_INT_MASK_0|MIPS_SOFT_INT_MASK_1);
をいれる。
最後に、softclock() 実行前に
_spllower(MIPS_SOFT_INT_MASK_0);
をいれる。
これで、4 段階の IPL の設定ができたことになる。
cpu_intr() の先頭で、MIPS_INT_SR_IE を enable しないといけないという
コメントが sato さんからあったが、まだやっていない。
また、ssir が race condition になっていないかチェックしないといけない。
さらに、mips/mips/trap.c:netintr() で netisr を触っている部分の
splnet() での保護を チェックする必要がある。
----------------------
2) btnmgr の ソフトウェア割り込み 化
1) をいれたことで、ソフトウェア割り込み中に ハードウェア割り込みが
上がってくることになる。
btnmgr の intr の中で スタンバイまたはサスペンドして 割り込みをうけたいので
btnmgr をソフトウェア割り込み化してみる。
machdep.c で
DO_SIR(SIR_NET, netintr());
の後に
DO_SIR(SIR_CONFIG_HOOK, config_hook_intr());
を追加。SIR_CONFIG_HOOK を include/intr.h に
#define SIR_CONFIG_HOOK 0x2
という風にいれてみたが、ほとんど全コンパイルになる。
( 実験と割り切るのであれば、もっと local にいれた方が良かった。)
config_hook.c: config_hook_intr 回りの修正。
オリジナルの config_hook_call を __config_hook_call にする。
次に、イベントを保存するバッファを定義して、config_hook_call で
登録するように変更。
#define CONFIG_HOOK_EVENT_MAX 16
volatile int config_hook_event_count;
volatile struct config_hook_event {
int type;
long id;
void *msg;
} config_hook_event[CONFIG_HOOK_EVENT_MAX];
int
config_hook_call(int type, long id, void *msg) {
int ret = 0;
int s;
s = splhigh();
if (config_hook_event_count >= CONFIG_HOOK_EVENT_MAX) {
ret = -1;
goto err;
}
config_hook_event[config_hook_event_count].type = type;
config_hook_event[config_hook_event_count].id = id;
config_hook_event[config_hook_event_count].msg = msg;
config_hook_event_count++;
setsoft(SIR_CONFIG_HOOK);
err:
splx(s);
return ret;
}
こんな感じ。
さらに、config_hook_intr() を作る。
config_hook_intr() {
int i,n,s;
struct config_hook_event e[CONFIG_HOOK_EVENT_MAX];
s = splhigh();
n = config_hook_event_count;
while (n) {
for (i=0; i<n; i++) {
e[i] = config_hook_event[i];
}
config_hook_event_count = 0;
splx(s);
for (i=0; i< n; i++) {
__config_hook_call( e[i].type, e[i].id, e[i].msg);
}
splhigh();
n = config_hook_event_count;
}
splx(s);
}
こんな風に、__config_hook_call を呼び出す。
この修正で、config_hook_call() の戻り値が返せないという仕様変更に
なってしまう。
ただし、___config_hook_call() 自体は、low レベルの IPL に統一されるので、
spl での排他制御がやりやすくなっているというアドバンテージもある。
竹村さんから、やるのなら timeout() を使って softintr() で動く
ようにすべきという指摘があった。
また ___config_hook_call() での排他制御がやりにくいという問題があれば、
ソフトウェア割り込みによる方法よりは、カーネルスレッドでの解決が
今流かもしれないという気がする。
以上の理由で、このコードは実験だけで終るように思う。
----------
3) 1),2) の修正を行ってはじめて、btnmgr で スタンバイモードにしてみる
ことができる。
btnmgr_hook() のなかで いろいろコードをいれてみた。
#ifdef CASSIOPEIA_HACK
if ((id == CONFIG_HOOK_BUTTONEVENT_POWER) && !msg) {
printf("OFF -> stopping %08x\n",_splget());
vrip_intr_suspend();
__asm(".set noreorder");
#if 0
__asm(__CONCAT(".word ",___STRING(VR_OPCODE_SUSPEND)));
#else
__asm(__CONCAT(".word ",___STRING(VR_OPCODE_STANDBY)));
#endif
__asm("nop");
__asm("nop");
__asm("nop");
__asm("nop");
__asm("nop");
__asm(".set reorder");
vrip_intr_resume();
}
if ((id == CONFIG_HOOK_BUTTONEVENT_APP0) && msg) {
__vrgiu_dump();
}
if ((id == CONFIG_HOOK_BUTTONEVENT_APP1) && msg) {
static int st=0;
st = !st;
__vrgiu_out(26,st);
}
if ((id == CONFIG_HOOK_BUTTONEVENT_APP2) && msg) {
printf("spl = %08x\n",_splget());
}
if ((id == CONFIG_HOOK_BUTTONEVENT_APP3) && msg) {
static int st=1; /* default 1 */
st = !st;
printf("LCD %s\n",st?"ON":"OFF");
if (st) {
__vrgiu_out(25,1);
__vrgiu_out(24,1);
__vrgiu_out(23,1);
} else {
__vrgiu_out(25,0);
__vrgiu_out(24,0);
__vrgiu_out(23,0);
}
}
---- こんな感じ。
__vrgiu_out() とか __vrgiu_dump() とかは、適当に作ったもの。
APP0 で バックライトの ON/OFF ができるようにしてみた。
これは、シリアルが死んでしまったとしても カーネルが動いているかどうか
動作確認するための コード。
-------------------------
結果)
ここまでやってみたが、かなり不安定になってしまった。
数分間は動作するが、フリーズする。
スタンバイにして、POWER BUTTON での復帰は確認したが、
SUSPEND は、うまくもどって来ない。
また、スタンバイからの復帰も うまくいくときといかないときがあったように
思う。
このあたりを確認/修正しようと思っていながら、なかなか時間が取れていない。
この実験は このままコードを捨てて終りそうなので、やったことを
記録だけしておくことにする。
本来の実験は、スタンバイがうまくいくのを確認して、サスペンドをやってみる
ことにあった。そのためには、リソースのセーブ/リストアなど いろいろ
いれていかないといけないはずである。
全然目的を達していないのが残念である。また時間が取れしだいやってみたい
とは思うが、竹村さんの フレームワークが先に入るような気がする。
---- ここまで。
---
--
鈴木 康司 (1ソフ四開 ALi)
suz@hpc.bs1.fc.nec.co.jp
8-23-26604 ←変更になりました。