4: 2007-01-26 (金) 23:09:59 |
現: 2024-01-06 (土) 22:39:13 |
| -tssの作成と登録の実際 | | -tssの作成と登録の実際 |
| struct TSS32 tss_a,tss_b; /*構造体として親切する | | struct TSS32 tss_a,tss_b; /*構造体として親切する |
| + | |
| tss_a.ldtr = 0; /*ldtrとiomapはとりあえずこの数値にする。 | | tss_a.ldtr = 0; /*ldtrとiomapはとりあえずこの数値にする。 |
| tss_a.iomap = 0x40000000; | | tss_a.iomap = 0x40000000; |
| tss_b.ldtr = 0; | | tss_b.ldtr = 0; |
| tss_b.iomap = 0x40000000; | | tss_b.iomap = 0x40000000; |
| + | |
| /*gdtへの登録 | | /*gdtへの登録 |
| set_segmdesc(gdt + 3,103,(int) &tss_a,AR_TSS32); /*それぞれ、GDT3番と4番に | | set_segmdesc(gdt + 3,103,(int) &tss_a,AR_TSS32); /*それぞれ、GDT3番と4番に |
| P296の初期設定 | | P296の初期設定 |
| tss_b.eip = (int) &task_b_main; /* 関数task_b_mainの先頭アドレス | | tss_b.eip = (int) &task_b_main; /* 関数task_b_mainの先頭アドレス |
- | | + | |
| + | |
| /* これはtask_b専用のスタックの設定。mamman_allocと使い64kbを確保。 | | /* これはtask_b専用のスタックの設定。mamman_allocと使い64kbを確保。 |
| /* 後ろの計算式はスタックの最終番地を計算したもの | | /* 後ろの計算式はスタックの最終番地を計算したもの |
| task_b_esp = memman_alloc_4k(memman,64*1024)+64*1024; | | task_b_esp = memman_alloc_4k(memman,64*1024)+64*1024; |
| tss_b.esp = tssk_b_esp; | | tss_b.esp = tssk_b_esp; |
- | | + | |
| + | |
| tss_b.eflags = 0x00000202; /*??? どういう意味だ? | | tss_b.eflags = 0x00000202; /*??? どういう意味だ? |
| + | |
| tss_b.eax = 0; /* 通常の各レジスタの初期値。 | | tss_b.eax = 0; /* 通常の各レジスタの初期値。 |
| tss_b.ecx = 0; | | tss_b.ecx = 0; |
| { | | { |
| (中略) | | (中略) |
| + | |
| /*タイマー timer_tsを新設。*/ | | /*タイマー timer_tsを新設。*/ |
| struct TIMER *timer, *timer2, *timer3, *timer_ts; | | struct TIMER *timer, *timer2, *timer3, *timer_ts; |
| + | |
| (中略) | | (中略) |
| + | |
| /*新設したタイマーを初期化*/ | | /*新設したタイマーを初期化*/ |
| timer_ts = timer_alloc(); | | timer_ts = timer_alloc(); |
| timer_init(timer_ts, &fifo, 2); /* タイムアウトしたら「2」をFIFOに送るよう設定 | | timer_init(timer_ts, &fifo, 2); /* タイムアウトしたら「2」をFIFOに送るよう設定 |
| timer_settime(timer_ts, 2); /* タイムアウト時間を0.02秒に設定 | | timer_settime(timer_ts, 2); /* タイムアウト時間を0.02秒に設定 |
| + | |
| (中略) | | (中略) |
| + | |
| /* 上記は設定。ここ以下のforループがtask_aの本質部分*/ | | /* 上記は設定。ここ以下のforループがtask_aの本質部分*/ |
| for (;;) { | | for (;;) { |
| + | |
| (中略) | | (中略) |
| /* FIFOに2が来たら(timer_tsがタイムアウトしたら */ | | /* FIFOに2が来たら(timer_tsがタイムアウトしたら */ |
| timer_settime(timer_ts, 2); /*ここに復帰した時、再度タイマーをセットする | | timer_settime(timer_ts, 2); /*ここに復帰した時、再度タイマーをセットする |
| } else if (256 <= i && i <= 511) { /* キーボードデータ */ | | } else if (256 <= i && i <= 511) { /* キーボードデータ */ |
| + | |
| (中略) | | (中略) |
| + | |
| } | | } |
- | | + | |
| + | |
| void task_b_main(void) | | void task_b_main(void) |
| { | | { |
| struct TIMER *timer_ts; /*ために必要なもの。 | | struct TIMER *timer_ts; /*ために必要なもの。 |
| int i, fifobuf[128]; | | int i, fifobuf[128]; |
| + | |
| fifo32_init(&fifo, 128, fifobuf); /*FIFOを初期化して準備する。 | | fifo32_init(&fifo, 128, fifobuf); /*FIFOを初期化して準備する。 |
| timer_ts = timer_alloc(); /*そうしないとタイマーが使えないから | | timer_ts = timer_alloc(); /*そうしないとタイマーが使えないから |
| timer_init(timer_ts, &fifo, 1); /*タイムアウトすると1を返してくるタイマー。 | | timer_init(timer_ts, &fifo, 1); /*タイムアウトすると1を返してくるタイマー。 |
| timer_settime(timer_ts, 2); | | timer_settime(timer_ts, 2); |
| + | |
| for (;;) { | | for (;;) { |
| + | |
| (中略) | | (中略) |
| + | |
| i = fifo32_get(&fifo); /*FIFOから一つ数値を得る。 | | i = fifo32_get(&fifo); /*FIFOから一つ数値を得る。 |
| io_sti(); | | io_sti(); |
| farjmp(0, 3 * 8); | | farjmp(0, 3 * 8); |
| timer_settime(timer_ts, 2); | | timer_settime(timer_ts, 2); |
| + | |
| } | | } |
| } | | } |
| | | |
| -「とにかくこの方法でsht_backの値をtask_b_mainに渡せる」と理解しておこう。(これ以上は無理) | | -「とにかくこの方法でsht_backの値をtask_b_mainに渡せる」と理解しておこう。(これ以上は無理) |
| + | --ただ、一つ解ったことがある。 |
| + | --通常、別のタスク(task_bとか)には、それ用のtssと同時にそれ用のスタックが必要。(そらそーだ。分けないとごっちゃごちゃになっちゃう) |
| + | --別のタスクになにも変数を渡す必要がない場合。(たとえば void task_b_main() なんて場合) |
| + | -- task_b_esp = memman_alloc_4k(memman,64*1024)+64*1024; |
| + | --こんなことして、task_b用のスタックを確保している。おそらく、大半のタスクでもこれは必要な行為だろう。(スタックを一切使用しない動作だけのタスクとかそういう特殊なのは別ね) |
| + | --それに対して、今回はようするに、task_bに対して値を渡したいというだけ。 |
| + | --で、task_bは引数を持つ関数になっている。(void task_b_main(struct SHEET *sht_back); ) |
| + | --普通に関数を呼ぶだけならなんの問題もない。そのまま呼べばよい。 |
| + | --しかし、今回の相手は「別に動くタスク」だ。なので、呼び出しで引数を渡せない |
| + | --しかし、今回どうしても理解できなかった部分の登場となる。いまだにわからない。 |
| + | --・・・しかし、このわからない部分は、 |
| + | -- task_b_esp = memman_alloc_4k(memman,64*1024)+64*1024 -8; |
| + | --である。普通に用意するスタックから 8 を引いているだけだ。 |
| + | --これがヒントになるかもしれない。いずれ解るかも。 |
| + | |
| + | |
| + | |
| + | |
| | | |
| | | |
| | | |
| -タスクスイッチ専用の特殊なタイマーを1個確保したと考えればよい。 | | -タスクスイッチ専用の特殊なタイマーを1個確保したと考えればよい。 |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | |
| + | COLOR(Blue){''疑問点解決?:''タスクはかならずしもメモリを別セグメントにして動かすとは限らない(上記参照)。また、状況によってはtssを共有することすら可能。(タスクA,B,Cとあった場合、絶対tssが3個必要というわけではない。屁理屈チックだが、タスクAとタスクCが絶対同時に動かないような調整をすればtssは2個でも十分マルチタスクは可能)よってこの場合は、タスクではなく''tssはどう頑張っても8,190個以上は作れない''ということでOKのようだ。(・・・なんかあったりまえな答えになってしまったな・・・(^^;))} |