OSDN Git Service

Change the directry name to hirado
[trx-305dsp/dsp.git] / hirado / kernel / doc / config.txt
1
2        = JSPカーネル ターゲット依存部 ポーティングガイド =
3
4              (Release 1.4.3対応,最終更新: 22-Apr-2007)
5
6 ------------------------------------------------------------------------ 
7  TOPPERS/JSP Kernel
8      Toyohashi Open Platform for Embedded Real-Time Systems/
9      Just Standard Profile Kernel
10
11  Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory
12                              Toyohashi Univ. of Technology, JAPAN
13  Copyright (C) 2004-2005 by Embedded and Real-Time Systems Laboratory
14              Graduate School of Information Science, Nagoya Univ., JAPAN
15
16  上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation 
17  によって公表されている GNU General Public License の Version 2 に記
18  述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
19  を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
20  利用と呼ぶ)することを無償で許諾する.
21  (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
22      権表示,この利用条件および下記の無保証規定が,そのままの形でソー
23      スコード中に含まれていること.
24  (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
25      用できる形で再配布する場合には,再配布に伴うドキュメント(利用
26      者マニュアルなど)に,上記の著作権表示,この利用条件および下記
27      の無保証規定を掲載すること.
28  (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
29      用できない形で再配布する場合には,次のいずれかの条件を満たすこ
30      と.
31    (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
32        作権表示,この利用条件および下記の無保証規定を掲載すること.
33    (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
34        報告すること.
35  (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
36      害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
37
38  本ソフトウェアは,無保証で提供されているものである.上記著作権者お
39  よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
40  含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
41  接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
42
43  @(#) $Id: config.txt,v 1.1 2009/01/31 05:27:37 suikan Exp $
44 ------------------------------------------------------------------------
45
46
47 このドキュメントでは,JSPカーネルのターゲット依存部で提供すべきデータ
48 型や関数などについて解説する.
49
50 JSPカーネルのターゲット依存部は,依存部の再利用性を考慮し,プロセッサ
51 依存部,システム依存部,開発環境依存部に分離している.開発環境依存部に
52 関しては,おおよその役割分担を決まっているが,プロセッサ依存部とシステ
53 ム依存部については,役割分担が明確なわけではない.以下のデータ型や関数
54 の多くは,どの依存部で定義してもかまわない.シミュレーション環境などの
55 極端なケースでは,システム依存部を全く使わないことも考えられる.
56
57 JSPカーネルのデバイスドライバ等は,トロン協会において検討されているデ
58 バイスドライバ設計ガイドラインに沿う形で実装している.デバイスドライバ
59 設計ガイドラインWGの中間報告は,以下のURLからダウンロードすることがで
60 きる.
61         http://www.ertl.jp/ITRON/GUIDE/device-j.html
62
63
64 1.システム構築環境
65
66 JSPカーネルは,GNU開発環境を標準としており,コンフィギュレータや開発支
67 援ユーティリティは,主にGNU開発環境と組み合わせて動作するように実装さ
68 れている.そこで以下では,GNU開発環境を用いる場合を中心に説明する.そ
69 れ以外の開発環境を用いる場合には,開発支援ユーティリティの改造が必要に
70 なったり,一部のユーティリティが使用できないケースがある.
71
72 (1) ターゲット略称の決定
73
74 新しいターゲット依存部を作成する時は,プロセッサ略称とシステム略称を定
75 める.また,GNU以外の開発環境を用いる場合には,開発環境略称を定める.
76 これらの略称に用いる文字は,英文字,数字および "_" に限定する.
77
78 (2) ターゲット依存部のファイルを置くためのディレクトリ
79
80 ターゲット依存部のファイルを置くためのディレクトリを,config の下に作
81 成する.ディレクトリ名は,ターゲット略称から以下のように決定する.ただ
82 し,ディレクトリ名に含まれる英文字はすべて小文字とする.すなわち,ディ
83 レクトリ名には,英小文字,数字および "_" のみを使うことができる.
84
85 GNU開発環境を用いる場合には,config の下にプロセッサ略称を用いてプロセッ
86 サ依存部のファイルを置くためのディレクトリ(プロセッサ依存部ディレクト
87 リ)を,さらにその下にシステム略称を用いてシステム依存部のファイルを置
88 くためのディレクトリ(システム依存部ディレクトリ)を作成する.
89
90 GNU以外の開発環境を用いる場合には,config の下にプロセッサ略称と開発環
91 境略称を "-" で連結した名称(例えば,"sh3-hitachi")で,プロセッサ依存
92 部ディレクトリを作成する.さらにその下に,システム略称を用いてシステム
93 依存部ディレクトリを作成する.これらのディレクトリには,GNU開発環境用
94 のディレクトリに置かれているファイルと異なるファイルのみを置く.ファイ
95 ルが置かれていない場合には,GNU開発環境用のディレクトリを参照する.た
96 だし,Makefile.config に関しては,GNU開発環境用のディレクトリを参照し
97 ないため,同じ内容であっても用意しなければならない.
98
99 (3) システム構築方法の設定
100
101 プロセッサ依存部ディレクトリおよびシステム依存部ディレクトリの下に,そ
102 れぞれ,システム構築方法を設定するための Makefile.config ファイルを用
103 意する.これらのファイルは,Makefile からインクルードされる.
104
105 プロセッサ依存部およびシステム依存部の Makefile.config で定義すべき変
106 数には,開発環境のコマンド名を設定するもの,コンパイルオプションを設定
107 するもの,その他のものがある.ここでは,その他の変数とその定義の方法に
108 ついて説明する.
109
110 (3-1) TEXT_START_ADDRESS        テキストセクションの先頭番地
111 (3-2) DATA_START_ADDRESS        データセクションの先頭番地
112
113 各セクションの先頭番地の指定が必要な場合には,これらの変数に先頭番地を
114 定義する.
115
116 (3-3) LDSCRIPT                  リンカスクリプトのファイル名
117
118 専用のリンカスクリプトを用いる場合には,この変数にリンカスクリプトのファ
119 イル名を定義する.ファイル名は,config ディレクトリからの相対パスで指
120 定する.
121
122 (4) 開発環境のコマンド名の設定
123
124 (4-1) TARGET            ターゲット名
125
126 GNU開発環境を configure する場合に指定するターゲット名で,コンパイラ等
127 のコマンド名の先頭に付与される文字列(最後の "-" は不要)に定義する.
128 例えば,TARGET が m68k-unknown-elf に定義された場合には,コンパイラと
129 して m68k-unknown-elf-gcc が使われる.この変数が定義されない場合には,
130 単なる gcc が使われる.GNU以外の開発環境を用いる場合には,定義する必要
131 がない.
132
133 (4-2) CC                Cコンパイラドライバの名称
134 (4-3) CXX               C++コンパイラドライバの名称
135 (4-4) AS                アセンブラの名称
136 (4-5) LD                リンカの名称
137 (4-6) AR                アーカイバの名称
138 (4-7) NM                nmプログラムの名称
139 (4-8) RANLIB            ranlibプログラムの名称
140 (4-9) OBJCOPY           objcopyプログラムの名称
141 (4-10) OBJDUMP          objdumpプログラムの名称
142
143 GNU以外の開発環境を用いる場合に,それぞれのコマンドの名称に定義する.
144 対応するコマンドがない場合や,コマンドパラメータが異なる場合には,
145 Makefile 中のそのコマンドを呼び出している部分を変更する必要がある.GNU
146 開発環境では,これらは TARGET を用いて定義されるので,定義する必要はな
147 い.
148
149 (5) コンパイルオプションの設定
150
151 (5-1) CDEFS             マクロ定義オプション(-D)
152 (5-2) INCLUDES          インクルードファイルのディレクトリ指定オプション(-I)
153 (5-3) COPTS             コンパイラに対するその他のオプション
154 (5-4) LDFLAGS           リンカに対するオプション
155 (5-5) LIBS              ライブラリリンク指定のためのオプション
156
157 ターゲットに依存して,すべてのソースファイルに共通するコンパイルオプショ
158 ンの追加が必要な場合には,オプションの種類毎に上に示した変数に定義する.
159
160 システム依存部の Makefile.config でこれらの変数を定義する時は,":=" を
161 用いて,それまでの定義に追加する形で行う.例えば,プロセッサ依存部で 
162 「-Wall -g -O2 -m68020-40」というオプションを追加したい場合には,以下
163 の記述をプロセッサ依存部の Makefile.config に含める.
164
165     COPTS := $(COPTS) -Wall -g -O2 -m68020-40
166
167 それに対して,システム依存部の Makefile.config は Makefile の最初でイ
168 ンクルードされるため,このような配慮は必要ないが,変更に強くするために
169 同様に扱うことにする.
170
171 ほとんどの場合に,プロセッサ依存部の Makefile.config には以下の記述を
172 含める必要がある.
173
174     GNU開発環境を用いる場合
175         INCLUDES := -I$(SRCDIR)/config/$(CPU)
176
177     その他の開発環境を用いる場合
178         INCLUDES := -I$(SRCDIR)/config/$(CPU)-$(TOOL) -I$(SRCDIR)/config/$(CPU)
179
180 また,システム依存部の Makefile.config には以下の記述を含める必要があ
181 る.
182
183     GNU開発環境を用いる場合
184         INCLUDES := $(INCLUDES) -I$(SRCDIR)/config/$(CPU)/$(SYS)
185
186     その他の開発環境を用いる場合
187         INCLUDES := $(INCLUDES) -I$(SRCDIR)/config/$(CPU)-$(TOOL)/$(SYS) \
188                                 -I$(SRCDIR)/config/$(CPU)/$(SYS)
189
190 また,アセンブリ言語レベルの識別名が,C言語レベルの識別名の先頭に "_" 
191 が付いたものになる場合には,いずれかの Makefile.config で CDEFS に 
192 -DLABEL_ASM を追加する.
193
194 (5-6) STASK_DIR         システムサービスのソースが置かれたディレクトリ
195 (5-7) STASK_ASMOBJS     アセンブラで記述されたシステムサービスのオブジェクト
196 (5-8) STASK_COBJS       C言語で記述されたシステムサービスのオブジェクト
197 (5-9) STASK_CFLAGS      システムサービスに対するコンパイルオプション
198 (5-10) STASK_LIBS       システムサービスに対するライブラリリンク指定
199
200 システムサービス(システムログタスクやデバイスドライバなど)のソースが
201 置かれたディレクトリ,それを構成するオブジェクトファイルのリスト,それ
202 らをコンパイルする際に適用するコンパイルオプション,その構成に必要なラ
203 イブラリリンク指定を行う場合には,上に示した変数に定義する.
204
205 システム依存部の Makefile.config でこれらの変数を定義する時は,CDEFS 
206 などと同様の扱いが必要である.
207
208 (5-11) KERNEL_DIR       カーネルのソースが置かれたディレクトリ
209 (5-12) KERNEL_ASMOBJS   アセンブラで記述されたカーネルのオブジェクト
210 (5-13) KERNEL_COBJS     C言語で記述されたカーネルのオブジェクト
211 (5-14) KERNEL_CFLAGS    カーネルに対するコンパイルオプション
212
213 カーネルのソースが置かれたディレクトリ,それを構成するオブジェクトファ
214 イルのリスト,それらをコンパイルする際に適用するコンパイルオプションを
215 指定する場合には,上に示した変数に定義する.
216
217 システム依存部の Makefile.config でこれらの変数を定義する時は,CDEFS 
218 などと同様の扱いが必要である.
219
220 ほとんどの場合に,プロセッサ依存部の Makefile.config には以下の記述を
221 含める必要がある.
222
223     GNU開発環境を用いる場合
224         KERNEL_DIR := $(KERNEL_DIR):$(SRCDIR)/config/$(CPU)
225         KERNEL_ASMOBJS := $(KERNEL_ASMOBJS) cpu_support.o
226         KERNEL_COBJS := $(KERNEL_COBJS) cpu_config.o
227
228     その他の開発環境を用いる場合
229         KERNEL_DIR := $(KERNEL_DIR):$(SRCDIR)/config/$(CPU)-$(TOOL)
230         KERNEL_DIR := $(KERNEL_DIR):$(SRCDIR)/config/$(CPU)
231         KERNEL_ASMOBJS := $(KERNEL_ASMOBJS) cpu_support.o
232         KERNEL_COBJS := $(KERNEL_COBJS) cpu_config.o
233
234 また,システム依存部ディレクトリの Makefile.config には以下の記述を含
235 める必要がある.
236
237     GNU開発環境を用いる場合
238         KERNEL_DIR := $(KERNEL_DIR):$(SRCDIR)/config/$(CPU)/$(SYS)
239         KERNEL_ASMOBJS := $(KERNEL_ASMOBJS) sys_support.o
240         KERNEL_COBJS := $(KERNEL_COBJS) sys_config.o
241
242     その他の開発環境を用いる場合
243         KERNEL_DIR := $(KERNEL_DIR):$(SRCDIR)/config/$(CPU)-$(TOOL)/$(SYS)
244         KERNEL_DIR := $(KERNEL_DIR):$(SRCDIR)/config/$(CPU)/$(SYS)
245         KERNEL_ASMOBJS := $(KERNEL_ASMOBJS) sys_support.o
246         KERNEL_COBJS := $(KERNEL_COBJS) sys_config.o
247
248 (6) オフセットファイルの生成
249
250 アセンブリ言語で記述されるプログラムから,C言語の構造体にアクセスする
251 場合には,構造体の各フィールドのオフセットを参照することが必要である. 
252 JSPカーネルでは,必要なオフセット値をファイル(標準では offset.h)に出
253 力するための仕組みとして,makeoffset.c と genoffset を用意している.
254 makeoffset.c は,どのオフセット値をファイルに出力するかを指定するもの
255 で,ターゲット依存部で用意する必要がある.genoffset は,現時点ではGNU
256 開発環境にのみ対応している.
257
258 makeoffset.c と genoffset を使うことで,例えば,TCB 中の texptn フィー
259 ルドのオフセット値を TCB_texptn にマクロ定義することや,TCB 中のタスク
260 コンテキストブロック(tskctxb)に含まれる pc フィールドのオフセット値
261 を TCB_pc にマクロ定義することができる.また,TCB 中の enatex フィール
262 ドのオフセット値,ビット位置,ビットマスクを,それぞれ TCB_enatex,
263 TCB_enatex_bit,TCB_enatex_mask にマクロ定義することができる.マクロ定
264 義するビット位置やビットマスクは,アクセスするサイズやエンディアンを指
265 定することができる.
266
267 GNU開発環境以外を用いる場合など,この仕組みでオフセットファイルを生成
268 できない時には,offset.h をターゲット依存部で用意し,Makefile.config 
269 で OMIT_MAKEOFFSET をヌルストリング以外に定義する.
270
271 makeoffset.c と genoffset に関するマニュアルは,現時点では用意できてい
272 ない.使い方がわからない場合や,機能が足りない場合には,相談されたい.
273
274 (7) スタートアップモジュールなど
275
276 ターゲットによっては,ロードモジュールの先頭と最後にリンクすべきプログ
277 ラムを,ターゲット依存部で用意する必要がある.多くの場合,スタートアッ
278 プモジュールをロードモジュールの先頭にリンクする必要がある.
279
280 ロードモジュールの先頭にリンクすべきプログラムがある場合には,
281 Makefile.config において,そのオブジェクトファイル名を START_OBJS に定
282 義し,それに対するコンパイルルールと依存関係作成ルールを定義しなければ
283 ならない.ロードモジュールの最後にリンクすべきプログラムがある場合には,
284 そのオブジェクトファイル名を END_OBJS に定義し,それに対するコンパイル
285 ルールと依存関係作成ルールを定義しなければならない.
286
287 例えば,スタートアップモジュールのソースファイルが start.S の場合には,
288 Makefile.config に次のような記述を入れるとよい.
289
290         # スタートアップモジュールのオブジェクトファイル名
291         START_OBJS = start.o
292
293         # スタートアップモジュールのコンパイルルール
294         $(START_OBJS): %.o: %.S
295                 $(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
296
297         # スタートアップモジュールの依存関係作成ルール
298         $(START_OBJS:.o=.d): %.d: %.S
299                 @$(PERL) $(SRCDIR)/utils/makedep -C $(CC) \
300                         -O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
301
302 また,コンパイラに標準の crtbegin.o と crtend.o を用いる場合には,
303 Makefile.config に次のような記述を入れるとよい.
304
305         # オブジェクトファイル名
306         START_OBJS = $(shell $(CC) -print-file-name=crtbegin.o)
307         END_OBJS = $(shell $(CC) -print-file-name=crtend.o)
308
309         # 依存関係作成ルール
310         $(START_OBJS:.o=.d): %.d:
311         $(END_OBJS:.o=.d): %.d:
312
313 この場合,これらのファイルをコンパイルすることはないため,コンパイルルー
314 ルは不要である.また,依存関係作成ルールはダミーでよい(依存関係作成ルー
315 ルがないとエラーになる).
316
317 なお,カーネル用のスタートアップモジュールからは,main 関数ではなく,
318 kernel_start 関数を起動する必要がある.
319
320 (8) リンカスクリプト
321
322 開発環境に標準のリンカスクリプトが使用できない場合には,ターゲット依存
323 部で用意する.
324
325
326 2.アプリケーション用のインクルードファイル
327
328 ターゲット依存部で提供すべきアプリケーション用の定義は次の通りである.
329 これらの定義の中で,(1) および (2) は tool_defs.h に含めなければならな
330 い.その他の定義は,cpu_defs.h または sys_defs.h(またはそれらからイン
331 クルードされるファイル)に含める.
332
333 (1) コンパイラ依存のデータ型の定義
334
335 コンパイラ依存のデータ型を以下のシンボルに定義する.これらの定義は,
336 typedef ではなく,#define によりマクロ定義しなければならない.
337
338 (1-1) _int8_            8ビットの整数型
339 (1-2) _int16_           16ビットの整数型
340 (1-3) _int32_           32ビットの整数型
341 (1-4) _int64_           64ビットの整数型
342
343 各サイズの整数型を,これらのシンボルにマクロ定義する._int32_ 以外は,
344 コンパイラがサポートしていない場合には定義する必要がない._int32_ の定
345 義は必須である.
346
347 (1-5) _bool_            BOOLの型
348
349 BOOL は,標準では int に型定義されるが,それで不都合な場合には,適切な
350 型を _bool_ にマクロ定義する.
351
352 (1-6) _vp_int_          VP_INTの型
353
354 VP_INT は,標準では VP に型定義されるが,それで不都合な場合(例えば,
355 ポインタが16ビットで,int が32ビットの場合)には,適切な型を _vp_int_ 
356 にマクロ定義する.
357
358 (1-7) _intptr_          ポインタを格納できる整数型
359
360 _intptr_ は,フォーマット出力において,int型もポインタ型も格納できる整
361 数型として使用する.これを定義しない場合,long が使われる.
362
363 (2) コンパイラの拡張機能のためのマクロ定義
364
365 (2-1) inline            インライン指定
366 (2-2) Inline            ファイル内のみに有効なインライン指定
367 (2-3) asm               インラインアセンブラ(最適化を許す)
368 (2-4) Asm               インラインアセンブラ(最適化を抑止)
369
370 これらの中で,asm と Asm は,ターゲット依存部で用いていなければ定義す
371 る必要がない.
372
373 (3) タイムティックの定義
374
375 (3-1) TIC_NUME          タイムティックの周期の分子(単位: 1ミリ秒)
376 (3-2) TIC_DENO          タイムティックの周期の分母(単位: 1ミリ秒)
377
378 (4) 割込みハンドラ/CPU例外ハンドラ関連の定義
379
380 (4-1) INHNO             割込みハンドラ番号のデータ型
381 (4-2) EXCNO             CPU例外ハンドラ番号のデータ型
382
383 (5) 割込みマスクと割込みマスクの変更/参照関連の定義(オプション)
384
385 chg_ixx,get_ixx をターゲット依存にサポートする場合には,以下の定義お
386 よび宣言をターゲット依存部で提供する.xx,xxxx,XXXX は,ターゲット毎
387 に適切な文字列に定める.xxxx および XXXX は,4文字でなくてもよい.
388
389 (5-1) IXXXX                             割込みマスクのデータ型
390 (5-2) ER chg_ixx(IXXXX ixxxx)           chg_ixx のプロトタイプ宣言
391 (5-3) ER get_ixx(IXXXX *p_ixxxx)        get_ixx のプロトタイプ宣言
392
393 (6) 割込み番号と割込みの禁止/許可関連の定義(オプション)
394
395 dis_int,ena_int をターゲット依存にサポートする場合には,以下の定義お
396 よび宣言をターゲット依存部で提供する.
397
398 (6-1) INTNO                             割込み番号のデータ型
399 (6-2) ER dis_int(INTNO intno)           dis_int のプロトタイプ宣言
400 (6-3) ER ena_int(INTNO intno)           ena_int のプロトタイプ宣言
401
402 (7) 性能評価用システム時刻関連の定義(オプション)
403
404 JSPカーネルは,研究への利用を主目的の一つとしていることから,ターゲッ
405 ト依存に,性能評価用のサービスコール vxget_tim をサポート可能としてい
406 る.vxget_tim をサポートする場合には,以下の定義および宣言をターゲット
407 依存部で提供する.
408
409 (7-1) SYSUTIM                           性能評価用システム時刻のデータ型
410 (7-2) ER vxget_tim(SYSUTIM *p_sysutim)  vxget_tim のプロトタイプ宣言
411
412 (8) ターゲット識別マクロの定義
413
414 cpu_defs.h ではプロセッサ略称(cpu_defs.h の置かれているディレクトリ名
415 を大文字にしたもの),sys_defs.h ではシステム略称(sys_defs.h の置かれ
416 ているディレクトリ名を大文字にしたもの)をマクロ定義する.
417
418 (9) プロセッサのエンディアンの定義
419
420 (9-1) SIL_ENDIAN
421
422 プロセッサがビッグエンディアンの場合には SIL_ENDIAN_BIG(=1),リトル
423 エンディアンの場合には SIL_ENDIAN_LITTLE(=0)にマクロ定義する.
424
425 (10) システムの停止処理の定義
426
427 (10-1) kernel_abort(void)
428
429 assertマクロにおけるアサーションの失敗や,サービスコールが致命的なエラー
430 を返した場合に,システムを停止させる関数またはマクロ.kernel_exit を呼
431 び出す方法も考えられるが,デバッグを容易にするためには,インライン関数
432 かマクロで定義し,その場でシステムを停止させる処理に定義するのが望まし
433 い(kernel_exit を呼び出すと,エラーが発生した時点の状態から変化してし
434 まう).
435
436
437 3.カーネル用のデータ型や関数など
438
439 ターゲット依存部で提供すべきカーネル用のデータ型や関数などは次の通りで
440 ある.これらのデータ型やマクロの定義と関数のプロトタイプ宣言は,別に記
441 述がない限り,cpu_config.h または sys_config.h(またはそれらからインク
442 ルードされるファイル)に含める.また,関数の実体は,C言語の場合は 
443 cpu_config.c または sys_config.c に,アセンブリ言語の場合は 
444 cpu_support.S または sys_support.S に記述する.
445
446 (0) インクルード方法に関するルール
447
448 ヘッダファイルをインクルードする記述は,以下のルールに従うのを原則とす
449 る.
450
451 ANSI Cの標準インクルードファイルは,#include <…> でインクルードする.
452 また,Makefile または Makefile.config で INCLUDES に -Iオプションで指
453 定したディレクトリにあるファイルは,#include <…> でインクルードする.
454 カーネルを構成するファイルからのインクルードに対しては,以下のディレク
455 トリにあるファイルがこれに該当する(ターゲットにも依存).
456         jsp/include/
457         jsp/config/$(CPU)
458         jsp/config/$(CPU)/$(SYS)
459         jsp/config/$(CPU)-$(TOOL)
460         jsp/config/$(CPU)-$(TOOL)/$(SYS)
461         pdic/simple_sio
462
463 その他のインクルードファイルは #include "…" でインクルードする.カー
464 ネルを構成するファイルからのインクルードに対しては,以下のディレクトリ
465 にあるファイルがこれに該当する(ターゲットにも依存).
466         jsp/kernel
467         jsp/systask
468
469 (1) タスクコンテキストブロックのデータ型
470
471 (1-1) CTXB
472
473 ターゲット依存のタスクコンテキストを保存するために,TCB 中に持つことが
474 必要なデータ構造の型.
475
476 (2) システム状態参照
477
478 (2-1) BOOL sense_context(void)
479
480 現在の実行コンテキストが,タスクコンテキストの場合は FALSE,非タスクコ
481 ンテキストの場合は TRUE を返す関数.
482
483 (2-2) BOOL sense_lock(void)
484
485 現在のシステム状態が,CPUロック状態の場合は TRUE,CPUロック解除状態の
486 時は FALSE を返す関数.
487
488 (2-3) BOOL t_sense_lock(void)
489
490 タスクコンテキストにおいて,現在のシステム状態が,CPUロック状態の場合
491 は TRUE,CPUロック解除状態の時は FALSE を返す関数.この関数が,非タス
492 クコンテキストから呼ばれることはない.
493
494 (2-4) BOOL i_sense_lock(void)
495
496 非タスクコンテキストにおいて,現在のシステム状態が,CPUロック状態の場
497 合は TRUE,CPUロック解除状態の時は FALSE を返す関数.この関数が,タス
498 クコンテキストから呼ばれることはない.
499
500 ※ 原理的には,sense_lock が提供されていれば t_sense_lock と 
501 i_sense_lock は必要なく,逆に t_sense_lock と i_sense_lock が提供され
502 ていれば sense_lock を実現することはできるが,ターゲットに依存せずに高
503 い実行効率を実現するために,ターゲット依存部が3つの関数を提供すること
504 としている.
505
506 (3) CPUロックとその解除
507
508 (3-1) void t_lock_cpu(void)
509
510 タスクコンテキストにおいて,CPUロック解除状態から,CPUロック状態に遷移
511 させる関数.この関数が,CPUロック状態で呼ばれることはない.また,非タ
512 スクコンテキストから呼ばれることもない.
513
514 (3-2) void t_unlock_cpu(void)
515
516 タスクコンテキストにおいて,CPUロック状態から,CPUロック解除状態に遷移
517 させる関数.この関数が,CPUロック解除状態で呼ばれることはない.また,
518 非タスクコンテキストから呼ばれることもない.
519
520 (3-3) void i_lock_cpu(void)
521
522 非タスクコンテキストにおいて,CPUロック解除状態から,CPUロック状態に遷
523 移させる関数.この関数が,CPUロック状態で呼ばれることはない.また,タ
524 スクコンテキストから呼ばれることもない.
525
526 (3-4) void i_unlock_cpu(void)
527
528 非タスクコンテキストにおいて,CPUロック状態から,CPUロック解除状態に遷
529 移させる関数.この関数が,CPUロック解除状態で呼ばれることはない.また,
530 タスクコンテキストから呼ばれることもない.
531
532 (4) タスクディスパッチャ
533
534 (4-1) void dispatch(void)
535
536 タスクディスパッチャ(以下,単にディスパッチャと言う)を明示的に呼ぶた
537 めの関数.タスクコンテキストから呼ばれたサービスコール処理から,CPUロッ
538 ク状態で呼ばれる.
539
540 この関数が呼ばれると,関数を呼んだタスクのコンテキストを保存し, 実行
541 できるタスクの中で最高優先順位のタスク(schedtsk)のコンテキストを復帰
542 して実行状態とする.実行できるタスクがない場合(schedtsk が NULL の場
543 合)には,割込みを許可して,実行できるタスクができるまで待つ.ここで,
544 実行できるタスクができるのを待つ間に起動された割込みハンドラの出口で,
545 ディスパッチャが呼ばれないように対策することが必要である.具体的には,
546 実行できるタスクができるのを待つ間,一時的に非タスクコンテキストに切り
547 換えるか,ディスパッチを保留するようにする.
548
549 新たに実行状態になったタスクが,タスク例外処理ルーチンの起動条件を満た
550 していれば,タスク例外処理ルーチンを起動する.また,この関数を呼び出し
551 たタスクが次に実行状態になった時,タスク例外処理ルーチンの起動条件を満
552 たしていれば,タスク例外処理ルーチンの起動を行う.タスク例外処理ルーチ
553 ンの起動には,ターゲット非依存部が提供する calltex または call_texrtn 
554 を用いることができる.
555
556 (4-2) void exit_and_dispatch(void)
557
558 現在実行中のコンテキストを捨て,ディスパッチャを呼び出すための関数.タ
559 スクコンテキストから呼ばれたサービスコール(具体的には,ext_tsk)処理
560 またはカーネルの初期化処理から,CPUロック状態で呼ばれる.
561
562 この関数が呼ばれると,関数を呼んだタスクのコンテキストを保存せず,実行
563 できるタスクの中で最高優先順位のタスク(schedtsk)のコンテキストを復帰
564 して実行状態とする.実行できるタスクがない場合(schedtsk が NULL の場
565 合)の処理は,dispatch と同様である.
566
567 新たに実行状態になったタスクが,タスク例外処理ルーチンの起動条件を満た
568 していれば,タスク例外処理ルーチンを起動する.
569
570 この関数は,カーネルの初期化処理からも呼ばれるために,非タスクコンテキ
571 ストからも呼ばれても正しく処理できることが必要である.なお,この関数か
572 らはリターンしない.
573
574 (5) 割込みハンドラ/CPU例外ハンドラの出入口処理
575
576 (5-1) INTHDR_ENTRY(inthdr)
577 (5-2) INT_ENTRY(inthdr)
578
579 INTHDR_ENTRY(inthdr) は起動番地が inthdr の割込みハンドラを呼び出す出
580 入口処理ルーチンを生成するマクロ,INT_ENTRY(inthdr) は生成する出入口処
581 理ルーチンの先頭のラベルを得るためのマクロである.INT_ENTRY(inthdr) で
582 得られるラベルは,割込みハンドラ初期化ブロックに出入口処理ルーチンの先
583 頭番地を登録するために使われる.出入口処理ルーチンを生成する必要がない
584 場合には,INTHDR_ENTRY(inthdr) を単に extern 宣言に展開すればよい.
585
586 割込みハンドラの出入口処理は,実行コンテキストを非タスクコンテキストに
587 切り換え,スクラッチレジスタを保存して,割込みハンドラを呼び出す.割込
588 みハンドラから戻ると,元の実行コンテキストに戻すとともに,必要に応じて
589 ディスパッチとタスク例外処理ルーチンの起動処理を行う.ディスパッチとタ
590 スク例外処理ルーチンの起動処理は,具体的には次のように行う.
591
592 (a) 以下の処理は,割込みハンドラがタスクコンテキスト実行中に起動された
593 場合で,reqflg が TRUE の時のみ行う.
594
595 (b) enadsp が TRUE で,実行状態のタスク(runtsk)と実行できるタスクの
596 中で最高優先順位のタスク(schedtsk)が一致していない場合には,前者のタ
597 スクのコンテキストを保存し,後者のタスクのコンテキストを復帰して実行状
598 態とする.実行できるタスクがない場合(schedtsk が NULL の場合)には,
599 割込みを許可して,実行できるタスクができるまで待つ.ここでも,実行でき
600 るタスクができるのを待つ間に起動された割込みハンドラの出口で,タスクディ
601 スパッチャが呼ばれないようにすることが必要であるが,出入口処理を非タス
602 クコンテキストで実行していれば,特に対策する必要はない.
603
604 (c) 実行状態のタスク((b) でタスクディスパッチを行った場合は,新たに実
605 行状態となったタスク)がタスク例外処理ルーチンの起動条件を満たしていれ
606 ば,タスク例外処理ルーチンを起動する.また,(b) でタスクディスパッチを
607 行った場合は,それまで実行状態であったタスクが次に実行状態になった時,
608 タスク例外処理ルーチンの起動条件を満たしていれば,タスク例外処理ルーチ
609 ンの起動を行う.タスク例外処理ルーチンの起動には,ターゲット非依存部が
610 提供する calltex または call_texrtn を用いることができる.
611
612 このマクロで生成するルーチンでは,上記の処理の一部のみを行い,残りの処
613 理は別に用意したルーチンに任せてもよい.具体的には,タスクディスパッチ
614 とタスク例外処理ルーチンの起動処理は,別にルーチンとして用意するのが適
615 当であろう.
616
617 (5-3) EXCHDR_ENTRY(exchdr)
618 (5-4) EXC_ENTRY(exchdr)
619
620 EXCHDR_ENTRY(exchdr) は起動番地が exchdr のCPU例外ハンドラを呼び出す出
621 入口処理ルーチンを生成するマクロ,EXC_ENTRY(exchdr) は生成する出入口処
622 理ルーチンの先頭のラベルを得るためのマクロである.EXC_ENTRY(exchdr) で
623 得られるラベルは,CPU例外ハンドラ初期化ブロックに出入口処理ルーチンの
624 先頭番地を登録するために使われる.出入口処理ルーチンを生成する必要がな
625 い場合には,EXCHDR_ENTRY(exchdr) を単に extern 宣言に展開すればよい.
626
627 CPU例外ハンドラの出入口処理は,実行コンテキストを非タスクコンテキスト
628 に切り換え,スクラッチレジスタを保存して,CPU例外ハンドラを呼び出す.
629 CPU例外ハンドラには,VP型のパラメータ p_excinf を渡す.このパラメータ
630 は,CPU例外に関する情報を保存したスタック領域へのポインタであることを
631 想定しているが,具体的にはターゲット毎に定める.
632
633 CPU例外ハンドラから戻ると,元の実行コンテキストに戻すとともに,必要に
634 応じてタスクディスパッチとタスク例外処理ルーチンの起動処理を行う.タス
635 クディスパッチとタスク例外処理ルーチンの起動処理は,割込みハンドラの出
636 入口処理の場合と同様である(上記の (a)〜(c)).
637
638 (6) タスクコンテキスト設定処理(cpu_context.h)
639
640 ターゲット依存のタスクコンテキストを設定するために create_context と 
641 activate_context の2つの関数を用意する.2つの関数を呼び出すことで,タ
642 スクのコンテキスト(具体的には,タスクコンテキストブロックの内容とタス
643 クのスタック領域)をタスクが起動できる状態に設定する.2つの関数は呼ば
644 れるタイミングが異なるだけで明確な役割分担はなく,どのような処理はどち
645 らの関数で行わなければならないという制約はない.
646
647 これらの関数の宣言およびマクロの定義は,cpu_context.h に含める.これは,
648 cpu_config.h を処理する時点では TCB が定義されていないためである.
649
650 (6-1) void create_context(TCB *tcb)
651
652 タスクが休止状態に移行する時に呼ばれる.具体的には,タスクの生成時
653 (JSPカーネルでは,CRE_TSK でタスクを生成するため,タスク管理モジュー
654 ルの初期化)とタスクの終了時(ext_tsk,ter_tsk)に呼ばれる.
655
656 (6-2) void activate_context(TCB *tcb)
657
658 タスクが実行できる状態に移行する時に呼ばれる.具体的には,act_tsk でタ
659 スクを起動する時,タスクの終了時(ext_tsk,ter_tsk)に起動要求のキュー
660 イングにより再起動する時,TA_ACT 属性を指定してタスクを生成した時(タ
661 スク管理モジュールの初期化)に呼ばれる.
662
663 (6-3) ACTIVATED_STACK_SIZE(オプション)
664
665 ext_tsk がスタック上に確保するダミー領域のサイズを定義するためのマクロ.
666 ダミー領域が必要ない場合は,このマクロを定義する必要はない.
667
668 ext_tsk は,自タスクを終了させた後,自タスクに対して create_context を
669 呼ぶ.また,タスクの起動要求がキューイングされていた場合には,自タスク
670 に対して activate_context も呼ぶ.create_context と activate_context 
671 は,対象タスクのスタック領域を書き換える場合があるが,これが ext_tsk
672 (およびそこから呼ばれる関数)が使用しているスタック領域と重なった場合,
673 自分の使用しているスタック領域を自分で破壊する結果になる.
674
675 ACTIVATE_STACK_SIZE を,create_context と activate_context が書き換え
676 るスタック領域のサイズ(厳密には,スタックの底から何バイトめまでを書き
677 換えるか)にマクロ定義しておくと,ext_tsk 内でスタック上に定義したサイ
678 ズのダミー領域を確保し,自分の使用しているスタック領域を破壊するのを防
679 ぐ.
680
681 なお,これを実現するために,処理系依存の機能である alloca を用いている.
682 gcc は alloca をサポートしているが,他のコンパイラを用いる場合には,
683 alloca をサポートしているか確認が必要である.また,alloca を用いる場合
684 にインクルードファイルが必要な場合には,tool_config.h からインクルード
685 する必要がある.
686
687 (7) ターゲット依存の初期化/終了処理
688
689 (7-1) void cpu_initialize(void)
690
691 プロセッサ依存の初期化処理.カーネルの初期化処理で,カーネル内の各モジュ
692 ールを初期化する前に呼ばれる.
693
694 (7-2) void sys_initialize(void)
695
696 システム依存の初期化処理.カーネルの初期化処理で,cpu_initialize に続
697 いて呼ばれる.
698
699 (7-3) void tool_initialize(void)
700
701 開発環境依存の初期化処理.カーネルの初期化処理で,sys_initialize に続
702 いて呼ばれる.
703
704 上の3つの関数は,カーネル起動処理(kernel_start 関数)の最初でこの順に
705 呼び出される.3つの関数を呼び出した後の時点で,CPUロック状態になってい
706 なければならない.
707
708 (7-4) void cpu_terminate(void);
709
710 プロセッサ依存の終了時処理.カーネルの終了処理で呼ばれる.
711
712 (7-5) sys_exit(void)
713
714 システムの終了処理.カーネルの終了処理で,cpu_terminate に続いて呼ばれ
715 る.この関数からはリターンしない.ROMモニタを持つシステムでは,ROMモニ
716 タ呼出しで実現することを想定している.
717
718 (7-6) call_atexit(void)
719
720 開発環境依存の終了処理.必要に応じて,atexit によって登録された関数の
721 実行や C++ におけるデストラクタの実行を行う.
722
723 (8) 割込みハンドラ/CPU例外ハンドラの定義
724
725 (8-1) void define_inh(INHNO inhno, FP inthdr)
726
727 割込みハンドラ番号 inhno の起動番地を inthdr に設定する.割込み管理機
728 能の初期化処理から呼ばれる.
729
730 (8-2) void define_exc(EXCNO excno, FP exchdr)
731
732 CPU例外ハンドラ番号 excno の起動番地を exchdr に設定する.CPU例外ハン
733 ドラ管理機能の初期化処理から呼ばれる.
734
735 (9) CPU例外発生時点のシステム状態の参照
736
737 (9-1) BOOL exc_sense_context(VP p_excinf)
738
739 CPU例外が発生したコンテキストが,タスクコンテキストの場合は FALSE,非
740 タスクコンテキストの場合は TRUE を返す関数.CPU例外ハンドラから呼ばれ
741 たサービスコール処理から呼ばれる.p_excinf には,CPU例外ハンドラへの引
742 数がそのまま渡される.
743
744 (9-2) BOOL exc_sense_lock(VP p_excinf)
745
746 CPU例外が発生したコンテキストが,CPUロック状態の場合は TRUE,CPUロック
747 解除状態の時は FALSE を返す関数.CPU例外ハンドラから呼ばれたサービスコ
748 ール処理から呼ばれる.p_excinf には,CPU例外ハンドラへの引数がそのまま
749 渡される.
750
751 (10) TCB 中のフィールドのビット幅の定義(オプション)
752
753 TCB 中のフィールドの配置は性能に大きく影響すると思われるため,ターゲッ
754 ト依存にフィールドのビット幅を変更できるようにしている.具体的には,以
755 下の2つのフィールドのビット幅を変更できる.これらのマクロを定義しない
756 場合,最小ビット幅となる.
757
758 (10-1) TBIT_TCB_TSTAT           tstat(タスク状態)のビット幅
759 (10-2) TBIT_TCB_PRIORITY        priority(優先度)フィールドのビット幅
760
761 32ビットプロセッサの場合には,これらを 8 に定義するのが効率的である.
762
763 (11) ビットマップサーチにビットサーチ命令を使うための定義(オプション)
764
765 プロセッサがビットサーチ命令を持つ場合,レディキューのビットマップサー
766 チにその命令を用いた方が効率がよい.その場合,以下の関数およびマクロを
767 ターゲット依存部で定義する.
768
769 (11-1) CPU_BITMAP_SEARCH
770
771 プロセッサのビットサーチ命令を用いる場合,このマクロを定義する.このマ
772 クロを定義することにより,ターゲット非依存部から bitmap_search が取り
773 除かれる.
774
775 (11-2) UINT bitmap_search(UINT bitmap)
776
777 ビットサーチを行う関数.bitmap 内の 1 のビットの内,最も下位のものをサ
778 ーチし,そのビット番号を返す.ビット番号は,最下位ビット(LSB)を 0 と
779 する.bitmap の下位16ビットに,必ず 1 のビットがある(すなわち,bitmap 
780 に 0 が指定されることはない)ことを仮定してよい.
781
782 標準ライブラリにビットサーチ命令を用いた ffs がある場合,ffs を用いて 
783 bitmap_search を次のように定義すればよい.
784         #define bitmap_search(bitmap)   (ffs(bitmap) - 1)
785
786 プロセッサの持つビットサーチ命令が,最も上位の 1 のビットをサーチする
787 ものである場合には,次のマクロを定義して,ビットの割付けを変更すること
788 ができる.
789
790 (11-3) UINT PRIMAP_BIT(pri)
791
792 タスク優先度の内部表現(最高優先度を 0 とする)を,それに対応するビッ
793 トマップに変換する.デフォルトの定義は次の通り.
794         #define PRIMAP_BIT(pri)         (1 << (pri))
795
796 (12) ターゲット依存のサービスコール(オプション)
797
798 以下のサービスコールをターゲット依存にサポートする場合には,その処理ル
799 ーチンをターゲット依存部で定義する.
800
801 (12-1) chg_ixx
802 (12-2) get_ixx
803 (12-3) dis_int
804 (12-4) ena_int
805
806 (13) 性能評価用システム時刻関連の定義(オプション)
807
808 (13-1) SUPPORT_VXGET_TIM
809
810 ターゲット非依存部の vxget_timサービスコール処理を用いる場合に,このマ
811 クロを定義する.
812
813 (13-2) hw_timer.h
814
815 ターゲット依存のタイマモジュールのインクルードファイル.ターゲット非依
816 存部の vxget_timサービスコール処理を用いる場合,ターゲット依存のタイマ
817 モジュールが必要になる.そのためのインクルードファイルである 
818 hw_timer.h は,システムサービスのシステムクロックドライバで用いるもの
819 と共通にしている.
820
821 (14) カーネルの内部識別名のリネームとその解除(cpu_rename.h,
822      cpu_unrename.h,sys_rename.h,sys_unrename.h)
823
824 ターゲット依存部で用いている識別名(モジュール内に閉じた識別名を除く)
825 を,μITRON4.0仕様に従って _kernel_ で始まるものにリネームする必要があ
826 る.
827
828 具体的には,プロセッサ依存部で用いている識別子をリストアップしたファイ
829 ルを cpu_rename.def に,システム依存部で用いている識別子をリストアップ
830 したファイルを sys_rename.def に作成する.genrename 使って,これらのファ
831 イルから,それぞれ cpu_rename.h と cpu_unrename.h,sys_rename.h と 
832 sys_unrename.h を生成する.xxx_rename.def から xxx_rename.h と 
833 xxx_unrename.h を生成するには,「$(KERNEL_DIR)/utils/genrename xxx」を
834 実行すればよい.
835
836 また,cpu_config.h の先頭から cpu_rename.h を,sys_config.h の先頭から 
837 sys_rename.h をインクルードする.
838
839 genrename が生成するファイルは次のような内容である.xxx_rename.def に
840 xxxx という識別子が含まれている場合,xxx_rename.h には次のようなマクロ
841 定義が生成される.
842
843 #define xxxx            _kernel_xxxx
844 #ifdef LABEL_ASM
845 #define _xxxx           __kernel_xxxx
846 #endif /* LABEL_ASM */
847
848 ここで,LABEL_ASM は,アセンブリ言語レベルの識別名が,C言語レベルの識
849 別名の先頭に "_" が付いたものになる場合に定義すべきマクロである(定義
850 の方法については「システム構築方法の設定」を参照).
851
852 また,xxx_unrename.h には次のようなマクロ定義解除が生成される.
853
854 #undef xxxx
855 #ifdef LABEL_ASM
856 #undef _xxxx
857 #endif /* LABEL_ASM */
858
859 (15) トレースログのためのマクロ定義(tool_config.h)
860
861 カーネルのトレースログの取得は,開発環境依存部でトレースログのためのマ
862 クロを定義することによって行う.トレースログのためのマクロは約150種類
863 あり,取得したいログ情報に対応するマクロを定義する.トレースログを取得
864 しない場合には,これらのマクロを空に定義すればよい.
865
866 (16) その他
867
868 (16-1) TARGET_NAME
869
870 起動メッセージのターゲット名.
871
872 (16-2) void sys_putc(char c)
873
874 ターゲットシステムの低レベルの文字出力ルーチン.ROMモニタを持つシステ
875 ムでは,ROMモニタ呼び出しで実現することを想定している.
876
877 (16-3) OMIT_CALLTEX(オプション)
878
879 ターゲット非依存部が calltex を提供する必要がない場合に,このマクロを
880 定義する.詳しくは,「タスク例外処理ルーチンの起動関数とその中で参照す
881 る TCB のフィールド」の節を参照のこと.
882
883 (16-4) LABEL_ALIAS(new_label, defined_label)(オプション,tool_config.h)
884
885 new_label を defined_label と同じアドレスに定義するためのマクロ.この
886 ようなマクロを実現できない場合には,定義を省略することができる.このマ
887 クロ定義は,tool_config.h の中で行うのを標準とする.
888
889 (16-5) COPYRIGHT_CPU(オプション)
890 (16-6) COPYRIGHT_SYS(オプション)
891
892 カーネル起動時のメッセージに,それぞれプロセッサ依存部およびシステム依
893 存部の著作権表示を追加するためのマクロ.
894
895 (16-7) __STK_UNIT(オプション)
896 (16-8) __MPF_UNIT(オプション)
897
898 標準では,スタック領域と固定長メモリプール領域は,VP型のサイズにアライ
899 ンする.これを,より大きい単位でアラインさせる必要がある場合には,
900 __STK_UNIT と __MPF_UNIT を,それぞれアラインさせる単位のデータ型に定
901 義する.ただし,__STK_UNIT および __MPF_UNIT のサイズは,2の巾乗でなけ
902 ればならない.
903
904 (16-9) __EMPTY_LABEL(x, y)(オプション,tool_config.h)
905
906 型 x のサイズ 0 の配列 y を定義するためのマクロ.サイズ 0 の配列を定義
907 できるコンパイラ(GNU開発環境はこれに該当)では定義を省略することがで
908 きる.このマクロ定義は,tool_config.h の中で行うのを標準とする.
909
910
911 4.ターゲット依存部が用いることができるターゲット非依存部の変数・関数
912
913 (1) タスク管理関連の変数
914
915 (1-1) TCB *runtsk
916
917 実行状態のタスク(=プロセッサがコンテキストを持っているタスク)の TCB 
918 を指すポインタ.実行状態のタスクがない場合は NULL にする.サービスコー
919 ルの処理中で,自タスク(サービスコールを呼び出したタスク)に関する情報
920 を参照する場合は runtsk を使う.カーネルの初期化処理以外で,この変数を
921 書き換えるのは,タスクディスパッチャ(すなわち,ターゲット依存部)のみ
922 である.
923
924 (1-2) TCB *schedtsk
925
926 実行できるタスクの中で最高優先順位のタスクの TCB を指すポインタ.実行
927 できるタスクがない場合は NULL となる.ディスパッチ禁止状態など,ディス
928 パッチが保留されている間は,runtsk と一致しているとは限らない.この変
929 数を書き換えるのはスケジューラのみで,ターゲット依存部はこの変数を書き
930 換えてはならない.
931
932 (1-3) BOOL reqflg
933
934 割込みハンドラ/CPU例外ハンドラの出口処理に,タスクディスパッチまたは
935 タスク例外処理ルーチンの起動を要求することを示すフラグ.この変数はサー
936 ビスコール処理(ターゲット非依存部)でセットし,割込みハンドラ/CPU例
937 外ハンドラの出口処理(ターゲット依存部)で参照/クリアする.
938
939 (1-4) BOOL enadsp
940
941 タスクディスパッチ許可状態である(すなわち,タスクディスパッチ禁止状態
942 でない)ことを示すフラグ.この変数はサービスコール(dis_dsp,ena_dsp,
943 ターゲット依存に chg_ixx)処理の中で書き換える.
944
945 また,タスクディスパッチャ(ターゲット依存部)の中で,実行できるタスク
946 ができるのを待つ間に起動された割込みハンドラの出口でタスクディスパッチャ
947 が呼ばれないようにするために,この変数を一時的に FALSE に設定すること
948 ができる.
949
950 (2) タスク例外処理ルーチンの起動関数とその中で参照する TCB のフィールド
951
952 (2-1) void calltex(void)
953 (2-2) void call_texrtn(void)
954
955 タスク例外処理ルーチンの起動を行う関数.calltex は,実行状態のタスクが
956 タスク例外処理ルーチンの起動条件を満たしていれば,call_texrtn を呼び出
957 す.call_texrtn は,タスク例外処理ルーチンの呼び出しを行う.タスク例外
958 処理ルーチンを呼び出す時は,一時的にCPUロックを解除する.
959
960 これらの関数は,ディスパッチャや割込みハンドラ/CPU例外ハンドラの出口
961 処理から,CPUロック状態で呼ばれることを想定している.calltex を呼び出
962 すのが最も簡単であるが,実行効率を上げるためには,起動条件のチェックを
963 アセンブリ言語で記述し,call_texrtn を呼び出した方がよい.チェックすべ
964 き起動条件については,ターゲット非依存部の calltex のソースコードを参
965 照すること.またその場合には,OMIT_CALLTEX をマクロ定義することで,タ
966 ーゲット非依存部から calltex が取り除かれる.
967
968 (2-3) BOOL enatex
969 (2-4) TEXPTN texptn
970
971 call_texrtn を呼び出すために,起動条件のチェックをアセンブリ言語で記述
972 する場合には,TCB 内のこれらのフィールドを参照する必要がある.
973
974 (3) システムログ機能
975
976 異常事象を通知するために,システムログ機能へのログ出力関数を用いること
977 ができる.システムログ機能については,ユーザズマニュアルを参照すること.
978
979
980 5.システムサービス用のデータ型や関数など
981
982 5.1 システムインタフェースレイヤ(SIL)のための定義
983
984 ターゲット依存部で提供すべきシステムインタフェースレイヤ(SIL)のため
985 の定義は次の通りである.これらの定義は,cpu_defs.hまたはsys_defs.h(ま
986 たはそれらからインクルードされるファイル)に含める.また,関数の実体が
987 必要な場合,C言語の場合はcpu_config.cまたはsys_config.cに,アセンブリ
988 言語の場合はcpu_support.Sまたはsys_support.Sに記述する.
989
990 (1) 微少時間待ち関連
991
992 (1-1) void sil_dly_nse(UINT dlytim)
993
994 dlytimで指定される時間(単位: 1ナノ秒)待つ関数をターゲット依存部で提
995 供する.
996
997 実現方法はターゲット依存であるが,以下の関数をアセンブリ言語で記述した
998 ものを,プロセッサ依存部に含めるのを標準的な方法とする.アセンブリ言語
999 で記述するのは,コンパイラの最適化に依存しないようにするためである.ま
1000 たこの関数は,できる限りメモリアクセスを行わないように実装すべきである.
1001
1002         void sil_dly_nse(UINT dlytim)
1003         {
1004                 if (dlytim > SIL_DLY_TIM1) {
1005                         dlytim -= SIL_DLY_TIM1;
1006                         while (dlytim > SIL_DLY_TIM2) {
1007                                 dlytim -= SIL_DLY_TIM2;
1008                         }
1009                 }
1010         }
1011
1012 (1-2) SIL_DLY_TIM1(オプション)
1013 (1-3) SIL_DLY_TIM2(オプション)
1014
1015 sil_dly_nseを上記の標準的な方法で実現した場合,この2つの定数をシステム
1016 依存部でマクロ定義する.なお,この2つの定数の決定を助けるプログラムを
1017 用意している.希望される方は,相談されたい.
1018
1019 (2) 割込みロック状態の制御関連(オプション)
1020
1021 (2-1) SIL_PRE_LOC
1022 (2-2) SIL_LOC_INT()
1023 (2-3) SIL_UNL_INT()
1024
1025 ターゲット依存で割込みロック状態の制御方法を変更したい場合には,これら
1026 のマクロにその方法を定義する.これらマクロを定義しない場合には, ター
1027 ゲット非依存部において,カーネルのCPUロックの機能を用いて割込みロック
1028 状態が実現される.
1029
1030 (3) プロセッサのエンディアンの定義
1031
1032 (3-1) SIL_ENDIAN
1033
1034 リトルエンディアンプロセッサではSIL_ENDIAN_LITTLE(=0),ビッグエンディ
1035 アンプロセッサではSIL_ENDIAN_BIG(=1)にマクロ定義する.
1036
1037 (4) エンディアンの反転(オプション)
1038
1039 (4-1) VH SIL_REV_ENDIAN_H(VH data)
1040 (4-2) VW SIL_REV_ENDIAN_W(VW data)
1041
1042 エンディアンの反転を効率よく実現する方法がある場合には,これらのマクロ
1043 にその方法を定義する.これらのマクロを定義しない場合には,標準的な方法
1044 でエンディアンの反転が行われる.
1045
1046 (5) エンディアン反転付きのメモリ空間アクセス(オプション)
1047
1048 エンディアンを反転してメモリを読出し/書込みする効率的な方法がある場合,
1049 該当するメモリ空間アクセス関数をターゲット依存部で用意し,ターゲット非
1050 依存部の標準的な定義を無効にするためのマクロを定義する.
1051
1052 (5-1) VH sil_reh_bem(VP mem)                OMIT_SIL_REH_BEM
1053 (5-2) void sil_wrh_bem(VP mem, VH data)     OMIT_SIL_WRH_BEM
1054 (5-3) VW sil_rew_bem(VP mem)                OMIT_SIL_REW_BEM
1055 (5-4) void sil_wrw_bem(VP mem, VW data)     OMIT_SIL_WRW_BEM
1056
1057 リトルエンディアンプロセッサでは,これらのメモリ空間アクセス関数をター
1058 ゲット依存部で用意し,右に示すマクロを定義する.
1059
1060 (5-5) VH sil_reh_lem(VP mem)                OMIT_SIL_REH_LEM
1061 (5-6) void sil_wrh_lem(VP mem, VH data)     OMIT_SIL_WRH_LEM
1062 (5-7) VW sil_rew_lem(VP mem)                OMIT_SIL_REW_LEM
1063 (5-8) void sil_wrw_lem(VP mem, VW data)     OMIT_SIL_WRW_LEM
1064
1065 ビッグエンディアンプロセッサでは,これらのメモリ空間アクセス関数をター
1066 ゲット依存部で用意し,右に示すマクロを定義する.
1067
1068 (6) 標準のアクセス関数の無効化(オプション)
1069
1070 (6-1) OMIT_SIL_ACCESS
1071
1072 シミュレーション環境などで,すべてのメモリ空間アクセス関数をターゲット
1073 依存部で用意する場合には,ターゲット非依存部の標準的な定義を無効にする
1074 ために,このマクロを定義する.
1075
1076 5.2 システムクロックドライバ用のデータ型や関数など
1077
1078 ターゲット依存部で提供すべきシステムクロックドライバ用のデータ型や関数
1079 などは次の通りである.これらの定義は,hw_timer.h(またはそれらからイン
1080 クルードされるファイル)に含める.関数の実体が必要な場合には,適切なファ
1081 イルを用意する.
1082
1083 (1) INHNO_TIMER
1084
1085 タイマ割込みハンドラのベクタ番号を定義したマクロを,ターゲット依存部で
1086 提供する.
1087
1088 (2) タイマの制御
1089
1090 (2-1) void hw_timer_initialize(void)
1091
1092 タイマを初期化し,タイマ割込みを周期的に発生させる関数を,ターゲット依
1093 存部で提供する.タイマ割込みの周期は,TIC_NUMEとTIC_DENOで指定された時
1094 間と一致させる.
1095
1096 (2-2) void hw_timer_int_clear(void)
1097
1098 タイマ割込み要求をクリアする関数を,ターゲット依存部で提供する.
1099
1100 (2-3) void hw_timer_terminate(void)
1101
1102 タイマの動作を停止させ,タイマ割込みを発生しないようにする関数を,ター
1103 ゲット依存部で提供する.
1104
1105 (3) 性能評価用システム時刻参照機能関連(オプション)
1106
1107 ターゲット非依存部のvxget_timサービスコール処理を用いる場合に,以下の
1108 データ型や関数などをターゲット依存部で提供する.
1109
1110 (3-1) CLOCK
1111
1112 タイマ値の内部表現のためのデータ型.
1113
1114 (3-2) CLOCK hw_timer_get_current(void)
1115
1116 タイマの現在値を読み出し,内部表現で返す関数.
1117
1118 (3-3) BOOL hw_timer_fetch_interrupt(void)
1119
1120 タイマ割込み要求をチェックする関数.タイマ割込みが要求されている場合に
1121 TRUE,要求されていない場合にFALSEを返す.
1122
1123 (3-4) UINT TO_USEC(CLOCK clock)
1124
1125 タイマ値の内部表現を,1μ秒単位に変換するためのマクロ(または関数).
1126 hw_timer_get_currentで読み出した値を,タイマ割込み発生からの経過時間
1127 (単位: 1μ秒)に変換するために用いる.
1128
1129 (3-5) BOOL BEFORE_IREQ(CLOCK clock)
1130
1131 割込みを禁止した状態で,まずhw_timer_get_currentを呼び出し,続いて
1132 hw_timer_fetch_interruptを呼び出す場合を考える.hw_timer_get_current
1133 を呼び出した直後にタイマが周期に達し,タイマ割込みが要求されると,
1134 hw_timer_get_currentは周期に達する直前のタイマ値(これを,clockとする)
1135 を返し,hw_timer_fetch_interruptがTRUEを返すことになる.この状況でも正
1136 しい現在時刻を得るために,clockがある一定値以上の場合には,
1137 hw_timer_fetch_interruptがTRUEを返しても,割込み発生前の値とみなすこと
1138 にする.BEFORE_IREQは,clockが割込み発生前の値とみなすべき場合にTRUEを,
1139 そうでない場合にFALSEを返すマクロ(または関数)である.
1140
1141 5.3 シリアルインタフェースドライバ用のデータ型や関数など
1142
1143 ターゲット依存部で提供すべきシリアルインタフェースドライバ用のデータ型
1144 や関数などは次の通りである.これらの定義は,別に記述がない限り,
1145 hw_serial.h(またはそこからインクルードされるファイル)に含め,必要な
1146 コンフィギュレーション情報をhw_serial.cfgに記述する.関数の実体が必要
1147 な場合には,適切なファイルを用意する.
1148
1149 シリアルインタフェースドライバの中で,ターゲットのシリアルI/Oデバイス
1150 に依存する部分を,シリアルI/Oデバイスドライバと呼ぶ.シリアルI/Oデバイ
1151 スドライバは,おおよそ,ITRONデバイスドライバ設計ガイドラインのPDICに
1152 相当する.PDICに相当するファイルで,他のシステムにも共通に使える可能性
1153 がある場合には,pdic/simple_sioディレクトリに置く.
1154
1155 (1) TNUM_PORT
1156
1157 シリアルインタフェースドライバがサポートするシリアルポート数を定義する
1158 マクロ.このマクロは,cpu_config.hまたはsys_config.h(またはそれらから
1159 インクルードされるファイル)で定義する.
1160
1161 (2) シリアルI/Oデバイスの割込みハンドラとその登録
1162
1163 シリアルI/Oデバイスの割込みハンドラをターゲット依存部で提供し,それを
1164 カーネルに登録する静的APIをhw_serial.cfgに含める.シリアルI/Oデバイス
1165 の割込ハンドラのベクタ番号は,hw_serial.h(またはそこからインクルード
1166 されるファイル)でマクロ定義し,hw_serial.cfgからhw_serial.hをインクル
1167 ードする方法を標準とする.
1168
1169 (3) void sio_initialize(void)
1170
1171 シリアルI/Oデバイスドライバを初期化するルーチン.この関数は,シリアル
1172 インタフェースドライバのターゲット非依存部の初期化ルーチンから呼び出さ
1173 れる.
1174
1175 (4) SIOPCB
1176
1177 シリアルI/Oポート管理ブロックのデータ型(hw_serial.hには,型宣言だけ含
1178 まれていればよい).
1179
1180 (5) SIO_ERDY_SNDとSIO_ERDY_RCV
1181
1182 送信可能コールバックの識別番号をSIO_ERDY_SNDに,受信通知コールバックの
1183 識別番号をSIO_ERDY_RCVにマクロ定義する.コールバックの禁止/許可を行な
1184 うサービスコール(sio_ena_cbrとsio_dis_cbr)で用いる.
1185
1186 (6) デバイスサービスルーチン
1187
1188 以下のデバイスサービルルーチンは,(少なくとも)シリアルI/Oポートから
1189 の割込みが禁止された状態で呼び出される.また,タスクコンテキスト,非タ
1190 スクコンテキストのいずれで呼び出される場合もある(いずれで呼び出されて
1191 も動作するようにしなければならない).
1192
1193 (6-1) SIOPCB *sio_opn_por(ID siopid, VP_INT exinf)
1194
1195 siopidで指定されるシリアルI/Oポートをオープンする関数.exinfはシリアル
1196 I/Oポートに対する拡張情報で,コールバックを呼ぶ時にポートを区別するた
1197 めに渡す.
1198
1199 (6-2) void sio_cls_por(SIOPCB *siopcb)
1200
1201 siopcbで指定されるシリアルI/Oポートをクローズする関数.
1202
1203 (6-3) BOOL sio_snd_chr(SIOPCB *siopcb, char c)
1204
1205 siopcbで指定されるシリアルI/Oポートに,cで示される文字を送信する関数.
1206 文字を送信レジスタに入れた場合にはTRUEを,前に送信した文字の送信が終わっ
1207 ていないために,文字を送信レジスタに入れられなかった場合にはFALSEを返
1208 す.
1209
1210 (6-4) INT sio_rcv_chr(SIOPCB *siopcb)
1211
1212 siopcbで指定されるシリアルI/Oポートから文字を読む関数.文字を受信して
1213 いた場合,読んだ文字のコードは正の値として返し,文字を受信していない場
1214 合には-1を返す.
1215
1216 (6-5) sio_ena_cbr(SIOPCB *siopcb, UINT cbrtn)
1217
1218 siopcbで指定されるシリアルI/Oポートからの,cbrtnで指定されるコールバッ
1219 クを許可する.cbrtnには,SIO_ERDY_SNDかSIO_ERDY_RCVを指定できる.
1220
1221 (6-6) sio_dis_cbr(SIOPCB *siopcb, UINT cbrtn)
1222
1223 siopcbで指定されるシリアルI/Oポートからの,cbrtnで指定されるコールバッ
1224 クを禁止する.cbrtnには,SIO_ERDY_SNDかSIO_ERDY_RCVを指定できる.
1225
1226 (7) コールバックルーチン
1227
1228 ターゲット依存部は,必要なタイミングで,シリアルインタフェースドライバ
1229 のターゲット非依存部に含まれる以下のコールバックルーチンを呼び出びださ
1230 なければならない.ただし,それぞれのコールバックが禁止されている時は,
1231 コールバックルーチンを呼び出してはならない.
1232
1233 コールバックルーチンは,(少なくとも)シリアルI/Oポートからの割込みが
1234 禁止された状態で,非タスクコンテキストで呼び出す.exinfには,シリアル
1235 I/Oポートのオープン時に指定された拡張情報を渡す.
1236
1237 (7-1) void sio_ierdy_snd(VP_INT exinf)
1238
1239 送信可能コールバックルーチン.シリアルI/Oポートに対して文字が送信でき
1240 る状態になった場合に呼び出す.シリアルインタフェースドライバは,このコ
1241 ールバックルーチンの中で,sio_snd_chrを呼び出して次の文字を送信するか,
1242 送信すべき文字がない場合には送信可能コールバックを禁止する.
1243
1244 (7-2) void sio_ierdy_rcv(VP_INT exinf)
1245
1246 受信通知コールバックルーチン.シリアルI/Oポートから文字を受信した場合
1247 に呼び出す.シリアルインタフェースドライバは,このコールバックルーチン
1248 の中で,必ずsio_rcv_chrを呼び出して受信した文字を取り出す.
1249
1250 5.4 システムログタスク用のための定義
1251
1252 ターゲット依存部で提供すべきシステムログタスクのための定義は次の通りで
1253 ある.これらの定義は,cpu_config.hまたはsys_config.h(またはそれらから
1254 インクルードされるファイル)に含める.
1255
1256 (1) LOGTASK_PORTID
1257
1258 システムログタスクが,システムログを出力するシリアルポートのIDを定義し
1259 たマクロをターゲット依存部で提供する.
1260
1261 (2) システムログタスク関連の定義(オプション)
1262
1263 システムログタスクに関する以下のマクロをターゲット依存部で提供する.こ
1264 れらのマクロをターゲット依存部で定義しない場合には,デフォルトの値が使
1265 われる.
1266
1267 (2-1) LOGTASK_PRIORITY          システムログタスクの初期優先度
1268 (2-2) LOGTASK_STACK_SIZE        システムログタスクのスタックサイズ
1269 (2-3) LOGTASK_INTERVAL          システムログタスクの動作間隔(単位: ミリ秒)
1270
1271
1272 6.ターゲット依存部実装上のヒント
1273
1274 (1) タスクディスパッチャの2通りの実装方針
1275
1276 タスクディスパッチャの実装方針として,コンテキストの保存・復帰とタスク
1277 例外処理ルーチンの起動を一連のルーチンで行う方針(これを方針Aと呼ぶ)
1278 と,コンテキストの保存・実行するタスクの選択・コンテキストの復帰とタス
1279 ク例外処理ルーチンの起動をばらばらのルーチンで行う方針(これを方針Bと
1280 呼ぶ)がある.方針Bは,保存するコンテキスト情報を状況に応じて必要最少
1281 限にすることが容易になるという利点がある.ただし,シミュレーション環境
1282 の場合,実現方法によっては方針Bが採れない可能性も考えられる.
1283
1284 タスク例外処理ルーチンの起動箇所という観点からみた場合,2つの方針には
1285 留意すべき違いがある.以下,例により説明する.タスク1とタスク2の2つの
1286 タスクがあり,タスク1の方が優先度が高いものとする.最初,タスク2が実行
1287 中に割込みハンドラが起動され,その中からタスク1が起動された結果,タス
1288 ク2がタスク1によってプリエンプトされたものとする.ここで,タスク1がタ
1289 スク2に対してタスク例外処理ルーチンの起動を要求した後,待ち状態に入る
1290 サービスコールを発行し,その結果タスク2にディスパッチされる状況を考え
1291 る.この時,タスクディスパッチャは,タスク2に対してタスク例外処理ルー
1292 チンの起動処理を行う必要があるが,方式Aの場合には,タスク1から明示的に
1293 呼ばれたディスパッチャの中でタスク例外処理ルーチンの起動が行われるのに
1294 対して,方針Bの場合には,タスク2のコンテキストを復帰するルーチンへ分岐
1295 した後,コンテキストを復帰する処理に続く処理としてタスク例外処理ルーチ
1296 ンの起動が行われる.
1297
1298 JSPカーネルでは,方針Aを採るか方針Bを採るかをターゲット依存部に任せる
1299 こととする.そのために,タスク例外処理ルーチンの起動をタスクディスパッ
1300 チャに含める仕様としている.
1301
1302 (2) 割込みハンドラの出入口処理
1303
1304 割込みハンドラの出入口処理の内容は,プロセッサの割込みアーキテクチャに
1305 より大きく異なるが,おおよその処理の流れは次の通りである.CPU例外ハン
1306 ドラの出入口処理も,引数を渡すことを除いては,おおよその処理の流れは同
1307 様である.ただし,プロセッサが割込みとCPU例外で異なる扱いをする場合は,
1308 実際の出入口処理はかなり異なったものとなる.
1309
1310         ------------------------------------------------------------
1311         レジスタの保存(主にスクラッチレジスタ)
1312         割込みスタックへ切換え(最も外側のハンドラのみ)
1313
1314         登録された割込みハンドラの呼出し
1315
1316         タスクスタックへ切換え(最も外側のハンドラのみ)
1317         if (最も外側のハンドラ && reqflg) {
1318                 if (enadsp && runtsk != schedtsk) {
1319                         タスクディスパッチ処理
1320                         タスク例外処理ルーチンの起動処理(calltex)
1321                 }
1322                 else  {
1323                         タスク例外処理ルーチンの起動処理(calltex)
1324                 }
1325         }
1326         レジスタの復帰(主にスクラッチレジスタ)
1327         割込み処理からのリターン
1328
1329         ※「ハンドラ」は,割込みハンドラとCPU例外ハンドラの総称.
1330         ※「最も外側のハンドラ」は「戻り先がタスク」と言い換えることが
1331            できる.
1332         ------------------------------------------------------------
1333
1334 この中で,内側のif文がいずれの場合でもタスク例外処理ルーチンの起動処理
1335 を行う必要があることから(ただし,タスク例外処理ルーチンの起動を行う対
1336 象タスクは異なる),内側のif文は次のように最適化できる場合がある.
1337
1338         ------------------------------------------------------------
1339                 if (enadsp && runtsk != schedtsk) {
1340                         タスクディスパッチ処理
1341                 }
1342                 タスク例外処理ルーチンの起動処理(calltex)
1343         ------------------------------------------------------------
1344
1345
1346 7.M68K(68LC040)用のターゲット依存部
1347
1348 (1) 前提
1349
1350 すべてのタスクをスーパーバイザモードで実行することとし,ユーザモードは
1351 用いない.
1352
1353 (2) 実行コンテキストとCPUロック状態
1354
1355 タスクコンテキストはマスタモード,非タスクコンテキストは割込みモードで
1356 実行する.sense_context は,SR 中のマスタ/割込みモードビットを参照す
1357 る方法で実現する.
1358
1359 IPM が 7 の時(NMI を除くすべての割込みが禁止される)かつその時に限り, 
1360 CPUロック状態であるものとする.sense_lock は,SR 中の IPM を参照する方
1361 法で実現する.NMI はカーネルの管理外の割込みなので,CPUロック状態で 
1362 NMI が受け付けられるのは差し支えない.
1363
1364 chg_ipm をサポートするかどうかを,SUPPORT_CHG_IPM を定義するかどうかで
1365 変更できる.タスクコンテキストで IPM を変更する場合には,chg_ipm を使
1366 わなければならない.chg_ipm をサポートしない場合には,タスクコンテキス
1367 トで IPM を変更することはできない.つまり,タスクコンテキストでは,IPM 
1368 は常に 0 になっている.
1369
1370 chg_ipm をサポートする場合でも,chg_ipm を使って IPM を 7 に変更するこ
1371 とは許さない.これは,chg_ipm と loc_cpu/unl_cpu の関係が複雑になるた
1372 めである.また,IPM が 1〜6 の時にも,タスクディスパッチは保留されない. 
1373 IPM は,タスクディスパッチによって,新しく実行状態になったタスクへ引き
1374 継がれる.そのため,タスクが実行中に,別のタスクによって IPM が変更さ
1375 れる場合がある.これは,ディスパッチャを方針Bで実装する場合には素直に
1376 実装できるが,方針Aで実装する場合にはあちこちに IPM の設定処理が入る.
1377 方針Aで実装する場合には,IPM が 1〜6 の時にもタスクディスパッチは保留
1378 されるとする方が楽である.
1379
1380 (3) 割込みハンドラ出入口処理
1381
1382 M68K(M68020以上)では,割込みハンドラの起動によって,使用するスタック
1383 が自動的に割込みスタックへ切り換わるため,割込みスタックへの切換え処理
1384 は必要ない.最も外側のハンドラであるかどうかは,スタック上に積まれた 
1385 SR 中のマスタ/割込みモードビットを参照して判定している.タスクディス
1386 パッチとタスク例外処理ルーチンの起動処理は,ret_int ルーチンに任せてい
1387 る.
1388
1389 reqflg をチェックする前に割込みを禁止するのは,割込みを禁止しないと, 
1390 reqflg をチェックした後に起動された割込みハンドラ内でディスパッチが要
1391 求された場合に,ディスパッチが行われないためである.
1392
1393 interrupt_entry:
1394         movem.l %d0-%d1/%a0-%a1, -(%sp) /* スクラッチレジスタを保存 */
1395         jsr <割込みハンドラ>            /* 割込みハンドラを呼び出す */
1396         movem.l (%sp)+, %d0-%d1/%a0-%a1 /* スクラッチレジスタを復帰 */
1397         btst.b #4, (%sp)                /* 戻り先が割込みモードなら */
1398         jbeq 1f                         /*           すぐにリターン */
1399         ori.w #0x0700, %sr              /* 割込み禁止 */
1400         tst.l reqflg                    /* reqflg が TRUE であれば */
1401         jbne ret_int                    /*              ret_int へ */
1402 1:      rte
1403
1404 (4) CPU例外ハンドラ出入口処理
1405
1406 M68Kでは,CPU例外ハンドラの起動によって割込みモードへの移行はおこらず,
1407 使用するスタックは切り換わらない.そのため,CPU例外ハンドラ内で割込み
1408 モードに切り換えている.また,最も外側のハンドラであるかどうかを判定す
1409 るために,割込みモードに切り換える前の SR をスタック上に保存する.タス
1410 クディスパッチとタスク例外処理ルーチンの起動処理は,ret_exc ルーチンに
1411 任せている.
1412
1413 CPU例外ハンドラへの引数は,例外スタックフレームの先頭番地(すなわち, 
1414 CPU例外ハンドラの出入口処理が呼ばれた直後のスタックポインタ)としてい
1415 る.
1416
1417 reqflg をチェックする前に割込みを禁止するのは,割込みを禁止しないと, 
1418 reqflg をチェックした後に起動された割込みハンドラ内でディスパッチが要
1419 求された場合に,ディスパッチが行われないためである.
1420
1421 exception_entry:
1422         movem.l %d0-%d1/%a0-%a1, -(%sp) /* スクラッチレジスタを保存 */
1423         lea.l 16(%sp), %a0              /* 例外フレームの先頭を A0 に */
1424         move.w %sr, %d0                 /* SR を D0 に */
1425         and.w #~0x1000, %sr             /* 割込みモード */
1426         move.l %d0, -(%sp)              /* 元の SR をスタックに保存 */
1427         move.l %a0, -(%sp)              /* A0 を引数として渡す */
1428         jsr <CPU例外ハンドラ>           /* CPU例外ハンドラを呼び出す */
1429         addq.l #4, %sp                  /* 引数を捨てる */
1430         move.l (%sp)+, %d0
1431         and.w #0x1000, %d0              /* 元が割込みモードなら */
1432         jbeq 1f                         /*       すぐにリターン */
1433         or.w #0x1700, %sr               /* マスタモード・割込み禁止 */
1434         tst.l reqflg                    /* reqflg が TRUE であれば */
1435         jbne ret_exc                    /*              ret_exc へ */
1436 1:      movem.l (%sp)+, %d0-%d1/%a0-%a1 /* スクラッチレジスタを復帰 */
1437         rte
1438
1439 (5) 方針Aのディスパッチャ
1440
1441 以下のコードでは,chg_ipm はサポートしていない.また,採用しなかったコ
1442 ートであるため,動作テストをしていない.
1443
1444 CTXB は「VP msp」のみを含む構造体とする.タスクのコンテキストは,次の
1445 図のようにタスクのスタック上に保存する.スクラッチレジスタ(D0〜D1,A0
1446 〜A1)とその他のレジスタを別々に積むのは,タスク例外処理ルーチンの起動
1447 に都合がよいためである.
1448
1449  *  小  +-----------------------------------+ ← TCB 中に保存されている MSP
1450  *  ↑  |                D2                 |
1451  *      +-----------------------------------+
1452  *                  . . . . . .
1453  *      +-----------------------------------+
1454  *      |                D7                 |
1455  *      +-----------------------------------+
1456  *      |                A2                 |
1457  *      +-----------------------------------+
1458  *                  . . . . . .
1459  *      +-----------------------------------+
1460  *      |                A6                 |
1461  *      +-----------------------------------+
1462  *      |                D0                 |
1463  *      +-----------------------------------+
1464  *      |                D1                 |
1465  *      +-----------------------------------+
1466  *      |                A0                 |
1467  *      +-----------------------------------+
1468  *      |                A1                 |
1469  *      +-----------------+-----------------+
1470  *      |        SR       |   PC (上16bit)  |
1471  *      +-----------------+-----------------+
1472  *  ↓  |   PC (下16bit)  |    例外情報     |
1473  *  大  +-----------------+-----------------+ ← ディスパッチャ起動前の MSP
1474
1475 dispatch は,trap_dispatch を TRAP命令で呼ぶ関数とする.
1476
1477 exit_and_dispatch:
1478         or.w #0x1000, %sr               /* マスタモード */
1479         jbra dispatch_1
1480
1481 trap_dispatch:
1482         movem.l %d0-%d1/%a0-%a1, -(%sp) /* スクラッチレジスタを保存 */
1483         movem.l %d2-%d7/%a2-%a6, -(%sp) /* 残りのレジスタを保存 */
1484         move.l runtsk, %a0              /* コンテキストを保存 */
1485         move.l %sp, TCB_msp(%a0)
1486 dispatch_1:
1487         move.l schedtsk, %a0
1488         move.l %a0, runtsk              /* schedtsk を runtsk に */
1489         jbeq dispatch_3                 /* schedtsk があるか? */
1490         move.l TCB_msp(%a0), %sp        /* コンテキストを復帰 */
1491         movem.l (%sp)+, %d2-%d7/%a2-%a6 /* レジスタを復帰 */
1492         btst.b #TCB_enatex_bit, TCB_enatex(%a0)
1493         jbeq dispatch_2                 /* enatex が FALSE ならリターン */
1494         tst.l TCB_texptn(%a0)           /* texptn が 0 ならリターン */
1495         jbeq dispatch_2
1496         jsr call_texrtn                 /* タスク例外処理ルーチンの呼出し */
1497 dispatch_2:
1498         movem.l (%sp)+, %d0-%d1/%a0-%a1 /* スクラッチレジスタを復帰 */
1499         rte
1500
1501 dispatch_3:
1502         stop #0x2000                    /* 割込み待ち(割込みモード) */
1503         /*
1504          *  ここで割込みモードに切り換えるのは,ここで発生する割込み処理
1505          *  にどのスタックを使うかという問題の解決と,割込みハンドラ内で
1506          *  のタスクディスパッチの防止という2つの意味がある.
1507          */
1508         or.w #0x1700, %sr               /* マスタモード・割込み禁止 */
1509         tst.l reqflg                    /* reqflg が FALSE なら */
1510         jbeq dispatch_3                 /*        dispatch_3 へ */
1511         clr.l reqflg                    /* reqflg をクリア */
1512         jbra dispatch_1
1513
1514 ret_int:
1515         /*
1516          *  ここでは,割込みモード・割込み禁止状態.
1517          */
1518         move.l %a1, -(%sp)              /* A1 を割込みスタックに保存 */
1519         movec.l %msp, %a1               /* タスクスタックを A1 に */
1520         move.l (%sp)+, -(%a1)           /* A1 をタスクスタックに積む */
1521         movem.l %d0-%d1/%a0, -(%a1)     /* スクラッチレジスタを積む */
1522         clr.l reqflg                    /* reqflg をクリア */
1523         move.l runtsk, %a0              /* A0 ← runtsk */
1524         tst.l enadsp                    /* enadsp が FALSE なら */
1525         jbeq ret_int_3                  /*         ret_int_3 へ */
1526         cmp.l schedtsk, %a0             /* runtsk と schedtsk が同じなら */
1527         jbeq ret_int_3                  /*                  ret_int_3 へ */
1528
1529         /* ディスパッチ処理 */
1530         movem.l %d2-%d7/%a2-%a6, -(%a1) /* レジスタを保存 */
1531         move.l %a1, TCB_msp(%a0)        /* タスクスタックを保存 */
1532 ret_int_1:
1533         move.l schedtsk, %a0
1534         move.l %a0, runtsk              /* schedtsk を runtsk に */
1535         jbne ret_int_2                  /* schedtsk があるか? */
1536 ret_int_1x:
1537         stop #0x2000                    /* 割込み待ち(割込みハンドラ内) */
1538         or.w #0x0700, %sr               /* 割込み禁止 */
1539         tst.l reqflg                    /* reqflg が FALSE なら */
1540         jbeq ret_int_1x                 /*        ret_int_1x へ */
1541         clr.l reqflg                    /* reqflg をクリア */
1542         jbra ret_int_1
1543 ret_int_2:
1544         move.l TCB_msp(%a0), %a1        /* タスクスタックを A1 に */
1545         movem.l (%a1)+, %d2-%d7/%a2-%a6 /* レジスタを復帰 */
1546
1547 ret_int_3:
1548         btst.b #TCB_enatex_bit, TCB_enatex(%a0)
1549         jbeq ret_int_4                  /* enatex が FALSE ならリターン */
1550         tst.l TCB_texptn(%a0)           /* texptn が 0 でなければ */
1551         jbne ret_int_5                  /*           ret_int_5 へ */
1552 ret_int_4
1553         movem.l (%a1)+, %d0-%d1/%a0     /* スクラッチレジスタを復帰 */
1554         move.l (%a1)+, -(%sp)           /* A1 を割込みスタックに保存 */
1555         movec.l %a1, %msp               /* A1 をタスクスタックに */
1556         move.l (%sp)+, %a1              /* A1 を割込みスタックから復帰 */
1557         rte
1558
1559 ret_int_5:
1560         move.w 16(%a1), %d0             /* 戻り先の SR を D0 に */
1561         move.l TCB_exinf(%a0), -(%a1)   /* exinf をタスクスタックに */
1562         move.l TCB_texptn(%a0), -(%a1)  /* texptn をタスクスタックに */
1563         move.l #ret_tex, -(%a1)         /* #ret_tex をタスクスタックに */
1564         clr.l TCB_enatex(%a0)           /* runtsk->enatex をクリア */
1565         clr.l TCB_texptn(%a0)           /* runtsk->texptn をクリア */
1566         move.w #例外情報, -(%a1)        /* 例外スタックフレームを作る */
1567         move.l TCB_texrtn(%a0), -(%a1)
1568         move.w %d0, -(%a1)
1569         movec.l %a1, %msp               /* A1 をタスクスタックに */
1570         rte
1571
1572 タスク例外処理ルーチン呼出し時のスタック
1573
1574  *  小  +-----------------------------------+
1575  *  ↑  |             ret_tex               |
1576  *      +-----------------------------------+
1577  *      |              texptn               |
1578  *      +-----------------------------------+
1579  *      |              exinf                |
1580  *      +-----------------------------------+
1581  *      |                D0                 |
1582  *      +-----------------------------------+
1583  *      |                D1                 |
1584  *      +-----------------------------------+
1585  *      |                A0                 |
1586  *      +-----------------------------------+
1587  *      |                A1                 |
1588  *      +-----------------+-----------------+
1589  *      |        SR       |   PC (上16bit)  |
1590  *      +-----------------+-----------------+
1591  *  ↓  |   PC (下16bit)  |    例外情報     |
1592  *  大  +-----------------+-----------------+
1593
1594 ret_tex:
1595         addq.l #8, %sp                  /* 引数エリアを捨てる */
1596         or.w #0x0700, %sr               /* 割込み禁止 */
1597         jsr call_texrtn                 /* タスク例外処理ルーチンの起動 */
1598         movem.l (%sp)+, %d0-%d1/%a0-%a1 /* スクラッチレジスタを復帰 */
1599         rte
1600
1601 (6) 方針B(採用)
1602
1603 ソースコードを参照.
1604
1605
1606 8.ターゲット依存部実装上の注意点
1607
1608 以下は,ターゲット依存部を実装する上でミスしがちな点をリストアップした
1609 ものである.
1610
1611 (1) タスク終了時
1612
1613 ext_tsk を呼ばずにタスクのメイン関数からリターンした場合,ext_tsk を呼
1614 び出したのと同等の処理を行うようにしなければならない.タスク起動時に,
1615 メイン関数からのリターンアドレスを ext_tsk の番地に設定しておく方法を
1616 推奨する.
1617
1618 (2) タスクコンテキストでの割込みマスクの変更
1619
1620 chg_iXX をサポートする場合,タスク切替えの際に,chg_iXX によって設定し
1621 た割込みマスクの値(タスクコンテキストにおける割込みマスクの値)を新し
1622 いタスクに引き継ぐことを推奨する.特に,割込みの出口でタスク切替えを行
1623 う箇所は注意が必要である.具体的には,以前に同じタスクが動いていた時の
1624 割込みマスクがスタックに積まれている場合に,これをそのまま書き戻しては
1625 ならない.
1626
1627 (3) タスク例外処理の実行コンテキスト
1628
1629 タスク例外処理ルーチンはタスクコンテキストで実行されるため,タスク例外
1630 処理ルーチン実行時にはスタックポインタがタスクスタックを指している必要
1631 がある(特に割込みの出口処理で注意すること) .
1632
1633 (4) CPU例外ハンドラ
1634
1635 CPU例外ハンドラ実行時は,割込みマスクの値がCPU例外発生直前と同じになる
1636 ようにすること.
1637
1638 (5) 実行すべきタスクがない場合の処理
1639
1640 実行すべきタスクがない(schedtsk が NULL)場合に,プロセッサを待ちモー
1641 ド(スリープモード)に移行させる処理と,割込みを許可する処理とは,不可
1642 分に行なう必要がある.これを不可分に行なわない場合,割込みを許可した直
1643 後に割込みが入り,その中でタスクが実行可能状態になると,実行すべきタス
1644 クがあるにもかかわらずプロセッサが待ちモードになってしまう.
1645
1646 また,実行すべきタスクがなく,割込みを許可して割込みを待つ間は,runtsk 
1647 を NULL に設定しなければならない.このように設定しないと,割込みハンド
1648 ラから iget_tid を呼び出した際の動作が仕様に合致しなくなる(μITRON4.0 
1649 仕様では,実行状態のタスクがない場合に,iget_tid は TSK_NONE を返すこ
1650 とになっており,iget_tid のコードは,runtsk が NULL の時に TSK_NONE を
1651 返すようになっている).
1652
1653 m68k の実装は(config/m68k/cpu_support.S より),
1654
1655 dispatcher:
1656         move.l schedtsk, %a0
1657         move.l %a0, runtsk              /* schedtsk を runtsk に */
1658         jbeq dispatcher_1               /* runtsk があるか? */
1659
1660 となっており,schedtsk が NULL の時に,runtsk を NULL にしてから,割込
1661 み待ちに入る.しかしながら,この処理が抜けていると,schedtsk が NULL 
1662 の時には,runtsk をすぐに更新しない.そのため,実行状態のタスクがない
1663 場合に iget_tid を呼ぶと,前に実行されていたタスクのID が返る.
1664  
1665 以上