[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  ←変更になりました。