source: rtos_arduino/trunk/asp_1.9.2/doc/ovrhdr_memo.txt@ 136

Last change on this file since 136 was 136, checked in by ertl-honda, 8 years ago

ライブラリとOS及びベーシックなサンプルの追加.

File size: 19.3 KB
Line 
1 TOPPERS Confidential
2 TOPPERSプロジェクト ディスカッションメモ
3 オーバランハンドラに関する設計メモ
4
5 作成者
6: 高田広章(名古屋大学)
7 最終更新: 2014年9月28日
8
9○メモの位置付け
10
11このドキュメントは,TOPPERS/ASPカーネルのオーバランハンドラ機能拡張に関
12する設計メモである.
13
14○データ型と定数の定義
15
16プロセッサ時間を表現するデータ型OVRTIMの定義を,kernel.hに含める.
17
18----------------------------------------
19typedef ulong_t OVRTIM; /* プロセッサ時間 */
20----------------------------------------
21
22プロセッサ時間に指定できる最大値は,ターゲット依存部(target_kernel.hま
23たはそこからインクルードされるファイル)で定義するものとするが,デフォ
24ルトの定義をkernel.hに含める.
25
26----------------------------------------
27#ifndef TMAX_OVRTIM
28#define TMAX_OVRTIM ULONG_MAX
29#endif /* TMAX_OVRTIM */
30----------------------------------------
31
32また,オーバランハンドラのデータ型OVRHDRの定義を,kernel.hに含める.
33
34----------------------------------------
35typedef void (*OVRHDR)(ID tskid, intptr_t exinf);
36----------------------------------------
37
38この他に,オーバランハンドラ機能のサービスコールの宣言と関連する定数の
39定義を,kernelに含める.
40
41○用いるハードウェア資源とサポートできない場合の措置
42
43オーバランハンドラを実現するに,タイムティックの割込みを発生させるのと
44は別のタイマ(以下,これをオーバランタイマと呼ぶ)を用いる.そのため,
45ターゲットによっては,オーバランハンドラをサポートできない場合も考えら
46れる.また,オーバランハンドラをサポートすることで,タスク切換えにかか
47るオーバヘッドが問題になる場合も考えられる.
48
49そこで,オーバランハンドラをサポートできる場合には,ターゲット依存部に
50おいて,TOPPERS_TARGET_SUPPORT_OVRHDRをマクロ定義するものとする.
51
52オーバランハンドラ機能拡張のkernel.hでは,TOPPERS_TARGET_SUPPORT_OVRHDR
53がマクロ定義されていれば,TOPPERS_SUPPORT_OVRHDRを定義する.
54
55----------------------------------------
56#ifdef TOPPERS_TARGET_SUPPORT_OVRHDR
57#define TOPPERS_SUPPORT_OVRHDR /* オーバランハンドラ機能拡張 */
58#endif /* TOPPERS_TARGET_SUPPORT_OVRHDR */
59----------------------------------------
60
61オーバランハンドラ機能は,TOPPERS_SUPPORT_OVRHDRが定義されている場合の
62み組み込む.これにより,オーバランハンドラ機能拡張を使用し,ターゲット
63依存部がオーバランハンドラをサポートしている場合のみ,オーバランハンド
64ラ機能が組み込まれることになる.
65
66○オーバランハンドラに関連するデータ構造
67
68オーバランハンドラを実装
69するために,TCBに,残りプロセッサ時間を表すフィー
70ルドleftotmを設ける(task.h).
71
72----------------------------------------
73typedef struct task_control_block {
74 ...
75 OVRTIM leftotm; /* 残りプロセッサ時間 */
76 ...
77} TCB;
78----------------------------------------
79
80オーバランハンドラが動作していない状æ…
81‹ã®æ™‚は,leftotmを0に設定すること
82とし,make_dormantの中で0に初期化する(task.c).
83
84----------------------------------------
85void
86make_dormant(TCB *p_tcb)
87{
88 ...
89 p_tcb->leftotm = 0U;
90 ...
91}
92----------------------------------------
93
94オーバランハンドラに対しては,管理ブロックは必
95要なく,DEF_OVRで定義した
96情
97報を格納した初期化ブロックのみを用意する.初期化ブロックも,単一の要
98素で十分であり,é…
99åˆ—である必
100要はない(overrun.h).
101
102----------------------------------------
103typedef struct overrun_handler_initialization_block {
104 ATR ovratr; /* オーバランハンドラ属性 */
105 OVRHDR ovrhdr; /* オーバランハンドラの起動番地 */
106} OVRINIB;
107----------------------------------------
108extern const OVRINIB ovrinib;
109----------------------------------------
110
111オーバランタイマが動作中かを示すフラグとして,boot_t型の変数
112ovrtimer_flagを用意する(overrun.h,overrun.c).
113
114----------------------------------------
115extern boot_t ovrtimer_flag;
116----------------------------------------
117
118シングルプロセッサの場合には,オーバランタイマが動作中かは,次の方法で
119判別することができる.
120
121 タスクコンテキストでは,(p_runtsk->leftotm > 0U)の時のみ動作している.
122 非タスクコンテキストでは,動作していない.
123
124そのため,このフラグを用いない実装
125も可能であるが,マルチプロセッサへの
126拡張性やターゲット依存性を下げるために,これを用いる実装
127としている(実
128際,Mac OS Xターゲット依存部では,これを活用している).
129
130○残りプロセッサ時間の保存/復帰処理の内
131容
132
133ディスパッチャおよび割込み処理/CPU例外処理の出å…
134¥å£ã§ï¼Œã‚¿ã‚¹ã‚¯ã®æ®‹ã‚Šãƒ—ロ
135セッサ時間を保存/復帰する必
136要がある.å…
137·ä½“的には,以下のような処理が必
138
139要である.
140
141(a) dispatchへのå…
142¥å£
143
144ovrtimer_flagがtrueであれば(または,p_runtsk->leftotmが0でなければ),
145オーバランタイマを停止させ,残りプロセッサ時間をp_runtsk->leftotmに格納
146する.残りプロセッサ時間が0(またはそれ未満)になっていた場合には,
147p_runtsk->leftotmに1を格納する.
148
149(b) dispatchからの出口
150
151タスク例外処理ルーチンの呼出し前に,p_runtsk->leftotmが0でなければ,残
152りプロセッサ時間をp_runtsk->leftotmとしてオーバランタイマを動作開始する.
153
154(c) 割込み処理/CPU例外処理のå…
155¥å£
156
157ovrtimer_flagがtrueであれば,オーバランタイマを停止させ,残りプロセッサ
158時間をp_runtsk->leftotmに格納する.残りプロセッサ時間が0(またはそれ未
159満)になっていた場合には,p_runtsk->leftotmに1を格納する.
160
161この処理は,カーネル管理の割込みをすべて禁止した状æ…
162‹ã§è¡Œã†å¿…
163要がある.
164割込み/CPU例外発生直後にすべての割込みが禁止されないプロセッサでは,割
165込みを禁止した後にこの処理を行う必
166要がある.
167
168(d) 割込み処理/CPU例外処理の出口
169
170タスクコンテキストに戻る場合に,p_runtsk->leftotmが0でなければ,残りプ
171ロセッサ時間をp_runtsk->leftotmとしてオーバランタイマを動作開始する.
172
173(e) タスクの終了時
174
175ovrtimer_flagがtrueであれば(または,p_runtsk->leftotmが0でなければ),
176オーバランタイマを停止させる.残りプロセッサ時間をp_runtsk->leftotmに格
177納する必
178要はない(make_dormantで0が格納される).
179
180(f) タスクの実行開始時
181
182p_runtsk->leftotmが0でなければ,残りプロセッサ時間をp_runtsk->leftotmと
183してオーバランタイマを動作開始する.
184
185○ターゲット依存部のインタフェース
186
187オーバランハンドラ機能のターゲット依存部では,オーバランハンドラ用のタ
188イマ(以下,オーバランタイマと呼ぶ)を操作するための機能を提供する.
189
190まず,次の定数をマクロ定義する.
191
192(1) TMAX_OVRTIM
193
194プロセッサ時間としてオーバランハンドラ用タイマに設定できる最大の値.単
195位はマイクロ秒とする.ターゲット依存部で定義しない場合には,kernel.hで
196ULONG_MAXに定義する.
197
198また,次の5つの関数を用意する.
199
200(1) void target_ovrtimer_initialize(intptr_t exinf)
201
202オーバランタイマの初期化処理を行う.タイマの動作開始は行わない.
203
204この関数は,target_timer.cfg中に記述する静的APIにより,初期化ルーチンと
205してカーネルに登録することを想定している.
206
207(2) void target_ovrtimer_terminate(intptr_t exinf)
208
209オーバランタイマの停止処理を行う.
210
211この関数は,target_timer.cfg中に記述する静的APIにより,終了処理ルーチン
212としてカーネルに登録することを想定している.
213
214(3) void target_ovrtimer_start(OVRTIM ovrtim)
215
216オーバランタイマを,ovrtimで指定した時間が経過したら割込みが発生するよ
217うに設定し,動作開始する.ovrtimの単位はマイクロ秒とする.
218
219(4) OVRTIM target_ovrtimer_stop(void)
220
221オーバランタイマを停止し,タイマの残り時間を読み出す.もし残り時間が
2220(またはそれ未満)になっていた場合には,1を返す.また,オーバランタイ
223マからの割込みをクリアする.
224
225(5) OVRTIM target_ovrtimer_get_current(void)
226
227オーバランタイマの残り時間を読み出す.もし残り時間が0(またはそれ未満)
228になっていた場合には,0を返す.オーバランタイマからの割込みはクリアしな
229い.
230
231○残りプロセッサ時間の保存/復帰の実装
232(ターゲット非依存部)
233
234前記の処理内
235容の中で,(a)と(c)は,呼出し条件が違うだけで処理内
236容は同一
237であるため,これを実現する関数ovrtimer_stopをターゲット非依存部に設け,
238ターゲット依存部の該当箇所から呼び出すようにする.
239
240----------------------------------------
241void
242ovrtimer_stop(void)
243{
244 if (ovrtimer_flag) {
245 assert(p_runtsk->leftotm > 0U);
246 p_runtsk->leftotm = target_ovrtimer_stop();
247 ovrtimer_flag = false;
248 }
249}
250----------------------------------------
251
252また(b),(d),(f)も,呼出し条件が違うだけで処理内
253容は同一であるため,これ
254を実現する関数ovrtimer_startをターゲット非依存部に設け,ターゲット依存
255部の該当箇所から呼び出すようにする.
256
257----------------------------------------
258void
259ovrtimer_start(void)
260{
261 if (p_runtsk->leftotm > 0U) {
262 target_ovrtimer_start(p_runtsk->leftotm);
263 ovrtimer_flag = true;
264 }
265}
266----------------------------------------
267
268(e)は,残りプロセッサ時間をp_runtsk->leftotmに格納する必
269要はない点で
270(a),(c)と処理内
271容が異なるが,p_runtsk->leftotmはmake_dormantで0に初期化
272されるため,make_dormantを呼び出す前であれば,ovrtimer_stopを流用するこ
273とができる.そこで,ext_tskに次の修正を加える(task_manage.c).
274
275----------------------------------------
276ER
277ext_tsk(void)
278{
279 ...
280 (void) make_non_runnable(p_runtsk);
281|#ifdef TOPPERS_SUPPORT_OVRHDR
282| ovrtimer_stop();
283|#endif /* TOPPERS_SUPPORT_OVRHDR */
284 make_dormant(p_runtsk);
285 ...
286}
287----------------------------------------
288
289○残りプロセッサ時間の保存/復帰の実装
290(ターゲット依存部)
291
292(a) dispatchへのå…
293¥å£
294
295----------------------------------------
296void
297dispatch(void)
298{
299|#ifdef TOPPERS_SUPPORT_OVRHDR
300| ovrtimer_stop(); /* オーバランタイマの停止 */
301|#endif /* TOPPERS_SUPPORT_OVRHDR */
302 スクラッチレジスタを除くすべてのレジスタをスタックに保存する
303 ...
304}
305----------------------------------------
306
307(b) dispatchからの出口
308
309----------------------------------------
310void
311dispatch(void)
312{
313 ...
314
315 dispatch_r:
316 スクラッチレジスタを除くすべてのレジスタをスタックから復帰する
317|#ifdef TOPPERS_SUPPORT_OVRHDR
318| ovrtimer_start(); /* オーバランタイマの動作開始 */
319|#endif /* TOPPERS_SUPPORT_OVRHDR */
320 calltex(); … (*b)
321}
322----------------------------------------
323
324(c) 割込み処理/CPU例外処理のå…
325¥å£
326
327割込み処理/CPU例外処理のå…
328¥å£ã¯æ¬¡ã®é€šã‚Šã«ä¿®æ­£ã™ã‚‹ï¼Ž
329
330----------------------------------------
331void
332<割込みの出å…
333¥å£å‡¦ç†>(void)
334{
335 スクラッチレジスタをスタックに保存する
336 if (タスクコンテキストで割込み発生) {
337|#ifdef TOPPERS_SUPPORT_OVRHDR
338| (少なくとも)カーネル管理の割込みを禁止した状æ…
339‹ã«ã™ã‚‹
340| ovrtimer_stop(); /* オーバランタイマの停止 */
341| (必
342要なら)å…
343ƒã®çŠ¶æ…
344‹ã«æˆ»ã™
345|#endif /* TOPPERS_SUPPORT_OVRHDR */
346 スタックを非タスクコンテキスト用のスタックに切り換え,
347 非タスクコンテキストに切り換える
348 }
349 ...
350}
351----------------------------------------
352void
353<CPU例外の出å…
354¥å£å‡¦ç†>(void)
355{
356 スクラッチレジスタをスタックに保存する
357 if (タスクコンテキストでCPU例外発生) {
358|#ifdef TOPPERS_SUPPORT_OVRHDR
359| (少なくとも)カーネル管理の割込みを禁止した状æ…
360‹ã«ã™ã‚‹
361| ovrtimer_stop(); /* オーバランタイマの停止 */
362| (必
363要なら)å…
364ƒã®çŠ¶æ…
365‹ã«æˆ»ã™
366|#endif /* TOPPERS_SUPPORT_OVRHDR */
367 スタックを非タスクコンテキスト用のスタックに切り換え,
368 非タスクコンテキストに切り換える
369 }
370 ...
371}
372----------------------------------------
373
374(d) 割込み処理/CPU例外処理の出口
375
376割込み処理/CPU例外処理の出口は次の通りに修正する.
377
378----------------------------------------
379void
380<割込みの出å…
381¥å£å‡¦ç†>(void)
382{
383 ...
384
385 ret_int_r:
386 スクラッチレジスタを除くすべてのレジスタをスタックから復帰する
387 }
388|#ifdef TOPPERS_SUPPORT_OVRHDR
389| ovrtimer_start(); /* オーバランタイマの動作開始 */
390|#endif /* TOPPERS_SUPPORT_OVRHDR */
391 calltex(); … (*b)
392 }
393|#ifdef TOPPERS_SUPPORT_OVRHDR
394| else {
395| (少なくとも)カーネル管理の割込みを禁止した状æ…
396‹ã«ã™ã‚‹
397| ovrtimer_start(); /* オーバランタイマの動作開始 */
398| }
399|#endif /* TOPPERS_SUPPORT_OVRHDR */
400 }
401 ...
402}
403----------------------------------------
404void
405<CPU例外の出å…
406¥å£å‡¦ç†>(void)
407{
408 ...
409
410 ret_exc_r:
411 スクラッチレジスタを除くすべてのレジスタをスタックから復帰する
412 }
413|#ifdef TOPPERS_SUPPORT_OVRHDR
414| ovrtimer_start(); /* オーバランタイマの動作開始 */
415|#endif /* TOPPERS_SUPPORT_OVRHDR */
416 calltex(); … (*b)
417 }
418|#ifdef TOPPERS_SUPPORT_OVRHDR
419| else {
420| (少なくとも)カーネル管理の割込みを禁止した状æ…
421‹ã«ã™ã‚‹
422| ovrtimer_start(); /* オーバランタイマの動作開始 */
423| }
424|#endif /* TOPPERS_SUPPORT_OVRHDR */
425 }
426 CPU例外処理からのリターンで,CPUロック状æ…
427‹ï¼ãƒ­ãƒƒã‚¯è§£é™¤çŠ¶æ…
428‹ãŒ
429 CPU例外発生時の状æ…
430‹ã«æˆ»ã‚‹ã‚ˆã†ã«æº–備する
431 スクラッチレジスタをスタックから復帰する
432 CPU例外処理からのリターン
433}
434----------------------------------------
435
436(e) タスクの終了時
437
438ターゲット非依存部のext_tskで対応した.
439
440(f) タスクの実行開始時
441
442----------------------------------------
443void
444activate_context(TCB *p_tcb)
445{
446 ...
447
448 start_r:
449|#ifdef TOPPERS_SUPPORT_OVRHDR
450| ovrtimer_start(); /* オーバランタイマの動作開始 */
451|#endif /* TOPPERS_SUPPORT_OVRHDR */
452 CPUロック解除状æ…
453‹ã«ã™ã‚‹
454 自タスク(p_runtsk)の起動番地を,拡張情
455報をパラメータとして呼び出す
456 ext_tskに分岐する ... (*c)
457}
458----------------------------------------
459
460○オーバランハンドラの呼出しの実装
461
462
463オーバランタイマが満了し,割込みが発生した場合には,ターゲット依存部の
464割込みハンドラ(または,割込みサービスルーチン)から,ターゲット非依存
465部のcall_ovrhdrを呼び出す.
466
467ここで,オーバランタイマ割込みハンドラの起動と,sta_ovr/stp_ovrの呼出
468しの競合の問題がある.å…
469·ä½“例として,オーバランタイマが満了した直後に,
470他の高優å…
471ˆåº¦ã®å‰²è¾¼ã¿ãŒç™ºç”Ÿã—,その処理中でオーバランハンドラが再動作開
472始(残りプロセッサは更新される)された場合や停止された場合が問題になる.
473この場合,オーバランタイマ割込みハンドラの中で,オーバランハンドラを呼
474び出さないようにすべきである.
475
476ターゲット非依存部のcall_ovrhdrの実装
477は次の通り.
478
479----------------------------------------
480void
481call_ovrhdr(void)
482{
483 assert(sense_context());
484 assert(!sense_lock());
485 assert(ovrinib.ovrhdr != NULL);
486
487 i_lock_cpu();
488 if (p_runtsk!= NULL && p_runtsk->leftotm == 1U) {
489 p_runtsk->leftotm = 0U;
490 i_unlock_cpu();
491
492 LOG_OVR_ENTER(p_runtsk);
493 ((OVRHDR)(ovrinib.ovrhdr))(TSKID(p_runtsk), p_runtsk->p_tinib->exinf);
494 LOG_OVR_LEAVE(p_runtsk);
495 }
496 else {
497 /*
498 * このルーチンが呼び出される前に,オーバランハンドラの起動が
499 * キャンセルされた場合
500 */
501 i_unlock_cpu();
502 }
503}
504----------------------------------------
505
506p_runtskがNULLの場合を考æ…
507®ã—ているのは,スプリアス割込みに対するロバス
508ト性を確保するためである.
509
510オーバランハンドラの呼出し後に,呼出し前の状æ…
511‹ï¼ˆCPUロック,割込み優å…
512ˆåº¦
513マスク)に戻さないのは,このルーチンからのリターン後に,割込み出口処理
514でå…
515ƒã®çŠ¶æ…
516‹ã«æˆ»ã™ãŸã‚ã§ã‚る.
517
518call_ovrhdrは,割込みハンドラから(または,割込みハンドラとして)呼び出
519されるため,このルーチンに来るまでに,ovrtimer_stopが呼ばれている(すな
520わち,オーバランタイマが停止している).
521
522割込みハンドラの設定は,以下のような静的APIを,target_timer.h中に記述す
523ることで行うものとする(ターゲットの事情
524で変更してよい).
525
526----------------------------------------
527#ifdef TOPPERS_SUPPORT_OVRHDR
528ATT_INI({ TA_NULL, 0, target_ovrtimer_initialize });
529ATT_TER({ TA_NULL, 0, target_ovrtimer_terminate });
530CFG_INT(INTNO_OVRTIMER, { TA_ENAINT | INTATR_OVRTIMER, INTPRI_OVRTIMER });
531DEF_INH(INHNO_OVRTIMER, { TA_NULL, target_ovrtimer_handler });
532#endif /* TOPPERS_SUPPORT_OVRHDR */
533----------------------------------------
534
535これらの静的API中の,INHNO_OVRTIMER,INTNO_OVRTIMER,INTPRI_OVRTIMER,
536INTATR_OVRTIMERの4つの定数は,target_timer.h中で定義する.
537
538○オーバヘッドの低減方法
539
540以上で説明した方法では,ターゲット依存部のアセンブリ言語で記述すること
541を想定したコードから,ターゲット非依存部のovrtimer_startと
542ovrtimer_stopを呼び出しているが,これらの関数は短いもので,アセンブリ言
543語の中に展開した方が効率がよい.これらの関数をアセンブリ言語の中に展開
544する場合には,それぞれ,OMIT_OVRTIMER_STARTとOMIT_OVRTIMER_STOPをマクロ
545定義する.
546
547○マルチプロセッサ対応カーネルへの対応に関するメモ
548
549マルチプロセッサ対応カーネルにおいて,sta_ovr/ista_ovr,stp_ovr/
550istp_ovrを,呼び出した処理単位と異なるプロセッサに割り付けられたタスク
551を対象に発行した場合の実装
552は工夫を要する.
553
554基本的には,対象タスクが割り付けられたプロセッサに対してプロセッサ間割
555込みをかけることによって,対象タスクのオーバランハンドラの動作を開始/
556停止させることが必
557要であるが,割込みのå…
558¥å£å‡¦ç†ã§å‘¼ã³å‡ºã™ovrtimer_stopで,
559ovrtimer_flagと(p_runtsk->leftotm > 0U)が一貫しなくなるため,工夫を要す
560るものと思われる.
561
562以上
Note: See TracBrowser for help on using the repository browser.