2 = JSPカーネル ターゲット依存部 ポーティングガイド =
4 (Release 1.4.3対応,最終更新: 22-Apr-2007)
6 ------------------------------------------------------------------------
8 Toyohashi Open Platform for Embedded Real-Time Systems/
9 Just Standard Profile Kernel
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
16 上記著作権者は,以下の (1)〜(4) の条件か,Free Software Foundation
17 によって公表されている GNU General Public License の Version 2 に記
18 述されている条件を満たす場合に限り,本ソフトウェア(本ソフトウェア
19 を改変したものを含む.以下同じ)を使用・複製・改変・再配布(以下,
21 (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
22 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
24 (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
25 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
26 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
28 (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
29 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
31 (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
32 作権表示,この利用条件および下記の無保証規定を掲載すること.
33 (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
35 (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
36 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
38 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
39 よびTOPPERSプロジェクトは,本ソフトウェアに関して,その適用可能性も
40 含めて,いかなる保証も行わない.また,本ソフトウェアの利用により直
41 接的または間接的に生じたいかなる損害に関しても,その責任を負わない.
43 @(#) $Id: config.txt,v 1.1 2009/01/31 05:27:37 suikan Exp $
44 ------------------------------------------------------------------------
47 このドキュメントでは,JSPカーネルのターゲット依存部で提供すべきデータ
50 JSPカーネルのターゲット依存部は,依存部の再利用性を考慮し,プロセッサ
51 依存部,システム依存部,開発環境依存部に分離している.開発環境依存部に
52 関しては,おおよその役割分担を決まっているが,プロセッサ依存部とシステ
53 ム依存部については,役割分担が明確なわけではない.以下のデータ型や関数
54 の多くは,どの依存部で定義してもかまわない.シミュレーション環境などの
55 極端なケースでは,システム依存部を全く使わないことも考えられる.
57 JSPカーネルのデバイスドライバ等は,トロン協会において検討されているデ
58 バイスドライバ設計ガイドラインに沿う形で実装している.デバイスドライバ
59 設計ガイドラインWGの中間報告は,以下のURLからダウンロードすることがで
61 http://www.ertl.jp/ITRON/GUIDE/device-j.html
66 JSPカーネルは,GNU開発環境を標準としており,コンフィギュレータや開発支
67 援ユーティリティは,主にGNU開発環境と組み合わせて動作するように実装さ
68 れている.そこで以下では,GNU開発環境を用いる場合を中心に説明する.そ
69 れ以外の開発環境を用いる場合には,開発支援ユーティリティの改造が必要に
70 なったり,一部のユーティリティが使用できないケースがある.
74 新しいターゲット依存部を作成する時は,プロセッサ略称とシステム略称を定
75 める.また,GNU以外の開発環境を用いる場合には,開発環境略称を定める.
76 これらの略称に用いる文字は,英文字,数字および "_" に限定する.
78 (2) ターゲット依存部のファイルを置くためのディレクトリ
80 ターゲット依存部のファイルを置くためのディレクトリを,config の下に作
81 成する.ディレクトリ名は,ターゲット略称から以下のように決定する.ただ
82 し,ディレクトリ名に含まれる英文字はすべて小文字とする.すなわち,ディ
83 レクトリ名には,英小文字,数字および "_" のみを使うことができる.
85 GNU開発環境を用いる場合には,config の下にプロセッサ略称を用いてプロセッ
86 サ依存部のファイルを置くためのディレクトリ(プロセッサ依存部ディレクト
87 リ)を,さらにその下にシステム略称を用いてシステム依存部のファイルを置
88 くためのディレクトリ(システム依存部ディレクトリ)を作成する.
90 GNU以外の開発環境を用いる場合には,config の下にプロセッサ略称と開発環
91 境略称を "-" で連結した名称(例えば,"sh3-hitachi")で,プロセッサ依存
92 部ディレクトリを作成する.さらにその下に,システム略称を用いてシステム
93 依存部ディレクトリを作成する.これらのディレクトリには,GNU開発環境用
94 のディレクトリに置かれているファイルと異なるファイルのみを置く.ファイ
95 ルが置かれていない場合には,GNU開発環境用のディレクトリを参照する.た
96 だし,Makefile.config に関しては,GNU開発環境用のディレクトリを参照し
97 ないため,同じ内容であっても用意しなければならない.
101 プロセッサ依存部ディレクトリおよびシステム依存部ディレクトリの下に,そ
102 れぞれ,システム構築方法を設定するための Makefile.config ファイルを用
103 意する.これらのファイルは,Makefile からインクルードされる.
105 プロセッサ依存部およびシステム依存部の Makefile.config で定義すべき変
106 数には,開発環境のコマンド名を設定するもの,コンパイルオプションを設定
107 するもの,その他のものがある.ここでは,その他の変数とその定義の方法に
110 (3-1) TEXT_START_ADDRESS テキストセクションの先頭番地
111 (3-2) DATA_START_ADDRESS データセクションの先頭番地
113 各セクションの先頭番地の指定が必要な場合には,これらの変数に先頭番地を
116 (3-3) LDSCRIPT リンカスクリプトのファイル名
118 専用のリンカスクリプトを用いる場合には,この変数にリンカスクリプトのファ
119 イル名を定義する.ファイル名は,config ディレクトリからの相対パスで指
126 GNU開発環境を configure する場合に指定するターゲット名で,コンパイラ等
127 のコマンド名の先頭に付与される文字列(最後の "-" は不要)に定義する.
128 例えば,TARGET が m68k-unknown-elf に定義された場合には,コンパイラと
129 して m68k-unknown-elf-gcc が使われる.この変数が定義されない場合には,
130 単なる gcc が使われる.GNU以外の開発環境を用いる場合には,定義する必要
133 (4-2) CC Cコンパイラドライバの名称
134 (4-3) CXX C++コンパイラドライバの名称
139 (4-8) RANLIB ranlibプログラムの名称
140 (4-9) OBJCOPY objcopyプログラムの名称
141 (4-10) OBJDUMP objdumpプログラムの名称
143 GNU以外の開発環境を用いる場合に,それぞれのコマンドの名称に定義する.
144 対応するコマンドがない場合や,コマンドパラメータが異なる場合には,
145 Makefile 中のそのコマンドを呼び出している部分を変更する必要がある.GNU
146 開発環境では,これらは TARGET を用いて定義されるので,定義する必要はな
151 (5-1) CDEFS マクロ定義オプション(-D)
152 (5-2) INCLUDES インクルードファイルのディレクトリ指定オプション(-I)
153 (5-3) COPTS コンパイラに対するその他のオプション
154 (5-4) LDFLAGS リンカに対するオプション
155 (5-5) LIBS ライブラリリンク指定のためのオプション
157 ターゲットに依存して,すべてのソースファイルに共通するコンパイルオプショ
158 ンの追加が必要な場合には,オプションの種類毎に上に示した変数に定義する.
160 システム依存部の Makefile.config でこれらの変数を定義する時は,":=" を
161 用いて,それまでの定義に追加する形で行う.例えば,プロセッサ依存部で
162 「-Wall -g -O2 -m68020-40」というオプションを追加したい場合には,以下
163 の記述をプロセッサ依存部の Makefile.config に含める.
165 COPTS := $(COPTS) -Wall -g -O2 -m68020-40
167 それに対して,システム依存部の Makefile.config は Makefile の最初でイ
168 ンクルードされるため,このような配慮は必要ないが,変更に強くするために
171 ほとんどの場合に,プロセッサ依存部の Makefile.config には以下の記述を
175 INCLUDES := -I$(SRCDIR)/config/$(CPU)
178 INCLUDES := -I$(SRCDIR)/config/$(CPU)-$(TOOL) -I$(SRCDIR)/config/$(CPU)
180 また,システム依存部の Makefile.config には以下の記述を含める必要があ
184 INCLUDES := $(INCLUDES) -I$(SRCDIR)/config/$(CPU)/$(SYS)
187 INCLUDES := $(INCLUDES) -I$(SRCDIR)/config/$(CPU)-$(TOOL)/$(SYS) \
188 -I$(SRCDIR)/config/$(CPU)/$(SYS)
190 また,アセンブリ言語レベルの識別名が,C言語レベルの識別名の先頭に "_"
191 が付いたものになる場合には,いずれかの Makefile.config で CDEFS に
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 システムサービスに対するライブラリリンク指定
200 システムサービス(システムログタスクやデバイスドライバなど)のソースが
201 置かれたディレクトリ,それを構成するオブジェクトファイルのリスト,それ
202 らをコンパイルする際に適用するコンパイルオプション,その構成に必要なラ
203 イブラリリンク指定を行う場合には,上に示した変数に定義する.
205 システム依存部の Makefile.config でこれらの変数を定義する時は,CDEFS
208 (5-11) KERNEL_DIR カーネルのソースが置かれたディレクトリ
209 (5-12) KERNEL_ASMOBJS アセンブラで記述されたカーネルのオブジェクト
210 (5-13) KERNEL_COBJS C言語で記述されたカーネルのオブジェクト
211 (5-14) KERNEL_CFLAGS カーネルに対するコンパイルオプション
213 カーネルのソースが置かれたディレクトリ,それを構成するオブジェクトファ
214 イルのリスト,それらをコンパイルする際に適用するコンパイルオプションを
215 指定する場合には,上に示した変数に定義する.
217 システム依存部の Makefile.config でこれらの変数を定義する時は,CDEFS
220 ほとんどの場合に,プロセッサ依存部の Makefile.config には以下の記述を
224 KERNEL_DIR := $(KERNEL_DIR):$(SRCDIR)/config/$(CPU)
225 KERNEL_ASMOBJS := $(KERNEL_ASMOBJS) cpu_support.o
226 KERNEL_COBJS := $(KERNEL_COBJS) cpu_config.o
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
234 また,システム依存部ディレクトリの Makefile.config には以下の記述を含
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
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
250 アセンブリ言語で記述されるプログラムから,C言語の構造体にアクセスする
251 場合には,構造体の各フィールドのオフセットを参照することが必要である.
252 JSPカーネルでは,必要なオフセット値をファイル(標準では offset.h)に出
253 力するための仕組みとして,makeoffset.c と genoffset を用意している.
254 makeoffset.c は,どのオフセット値をファイルに出力するかを指定するもの
255 で,ターゲット依存部で用意する必要がある.genoffset は,現時点ではGNU
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 義するビット位置やビットマスクは,アクセスするサイズやエンディアンを指
267 GNU開発環境以外を用いる場合など,この仕組みでオフセットファイルを生成
268 できない時には,offset.h をターゲット依存部で用意し,Makefile.config
269 で OMIT_MAKEOFFSET をヌルストリング以外に定義する.
271 makeoffset.c と genoffset に関するマニュアルは,現時点では用意できてい
272 ない.使い方がわからない場合や,機能が足りない場合には,相談されたい.
276 ターゲットによっては,ロードモジュールの先頭と最後にリンクすべきプログ
277 ラムを,ターゲット依存部で用意する必要がある.多くの場合,スタートアッ
278 プモジュールをロードモジュールの先頭にリンクする必要がある.
280 ロードモジュールの先頭にリンクすべきプログラムがある場合には,
281 Makefile.config において,そのオブジェクトファイル名を START_OBJS に定
282 義し,それに対するコンパイルルールと依存関係作成ルールを定義しなければ
283 ならない.ロードモジュールの最後にリンクすべきプログラムがある場合には,
284 そのオブジェクトファイル名を END_OBJS に定義し,それに対するコンパイル
285 ルールと依存関係作成ルールを定義しなければならない.
287 例えば,スタートアップモジュールのソースファイルが start.S の場合には,
288 Makefile.config に次のような記述を入れるとよい.
290 # スタートアップモジュールのオブジェクトファイル名
293 # スタートアップモジュールのコンパイルルール
294 $(START_OBJS): %.o: %.S
295 $(CC) -c $(CFLAGS) $(KERNEL_CFLAGS) $<
297 # スタートアップモジュールの依存関係作成ルール
298 $(START_OBJS:.o=.d): %.d: %.S
299 @$(PERL) $(SRCDIR)/utils/makedep -C $(CC) \
300 -O "$(CFLAGS) $(KERNEL_CFLAGS)" $< >> Makefile.depend
302 また,コンパイラに標準の crtbegin.o と crtend.o を用いる場合には,
303 Makefile.config に次のような記述を入れるとよい.
306 START_OBJS = $(shell $(CC) -print-file-name=crtbegin.o)
307 END_OBJS = $(shell $(CC) -print-file-name=crtend.o)
310 $(START_OBJS:.o=.d): %.d:
311 $(END_OBJS:.o=.d): %.d:
313 この場合,これらのファイルをコンパイルすることはないため,コンパイルルー
314 ルは不要である.また,依存関係作成ルールはダミーでよい(依存関係作成ルー
317 なお,カーネル用のスタートアップモジュールからは,main 関数ではなく,
318 kernel_start 関数を起動する必要がある.
322 開発環境に標準のリンカスクリプトが使用できない場合には,ターゲット依存
326 2.アプリケーション用のインクルードファイル
328 ターゲット依存部で提供すべきアプリケーション用の定義は次の通りである.
329 これらの定義の中で,(1) および (2) は tool_defs.h に含めなければならな
330 い.その他の定義は,cpu_defs.h または sys_defs.h(またはそれらからイン
335 コンパイラ依存のデータ型を以下のシンボルに定義する.これらの定義は,
336 typedef ではなく,#define によりマクロ定義しなければならない.
338 (1-1) _int8_ 8ビットの整数型
339 (1-2) _int16_ 16ビットの整数型
340 (1-3) _int32_ 32ビットの整数型
341 (1-4) _int64_ 64ビットの整数型
343 各サイズの整数型を,これらのシンボルにマクロ定義する._int32_ 以外は,
344 コンパイラがサポートしていない場合には定義する必要がない._int32_ の定
349 BOOL は,標準では int に型定義されるが,それで不都合な場合には,適切な
352 (1-6) _vp_int_ VP_INTの型
354 VP_INT は,標準では VP に型定義されるが,それで不都合な場合(例えば,
355 ポインタが16ビットで,int が32ビットの場合)には,適切な型を _vp_int_
358 (1-7) _intptr_ ポインタを格納できる整数型
360 _intptr_ は,フォーマット出力において,int型もポインタ型も格納できる整
361 数型として使用する.これを定義しない場合,long が使われる.
363 (2) コンパイラの拡張機能のためのマクロ定義
366 (2-2) Inline ファイル内のみに有効なインライン指定
367 (2-3) asm インラインアセンブラ(最適化を許す)
368 (2-4) Asm インラインアセンブラ(最適化を抑止)
370 これらの中で,asm と Asm は,ターゲット依存部で用いていなければ定義す
375 (3-1) TIC_NUME タイムティックの周期の分子(単位: 1ミリ秒)
376 (3-2) TIC_DENO タイムティックの周期の分母(単位: 1ミリ秒)
378 (4) 割込みハンドラ/CPU例外ハンドラ関連の定義
380 (4-1) INHNO 割込みハンドラ番号のデータ型
381 (4-2) EXCNO CPU例外ハンドラ番号のデータ型
383 (5) 割込みマスクと割込みマスクの変更/参照関連の定義(オプション)
385 chg_ixx,get_ixx をターゲット依存にサポートする場合には,以下の定義お
386 よび宣言をターゲット依存部で提供する.xx,xxxx,XXXX は,ターゲット毎
387 に適切な文字列に定める.xxxx および XXXX は,4文字でなくてもよい.
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 のプロトタイプ宣言
393 (6) 割込み番号と割込みの禁止/許可関連の定義(オプション)
395 dis_int,ena_int をターゲット依存にサポートする場合には,以下の定義お
398 (6-1) INTNO 割込み番号のデータ型
399 (6-2) ER dis_int(INTNO intno) dis_int のプロトタイプ宣言
400 (6-3) ER ena_int(INTNO intno) ena_int のプロトタイプ宣言
402 (7) 性能評価用システム時刻関連の定義(オプション)
404 JSPカーネルは,研究への利用を主目的の一つとしていることから,ターゲッ
405 ト依存に,性能評価用のサービスコール vxget_tim をサポート可能としてい
406 る.vxget_tim をサポートする場合には,以下の定義および宣言をターゲット
409 (7-1) SYSUTIM 性能評価用システム時刻のデータ型
410 (7-2) ER vxget_tim(SYSUTIM *p_sysutim) vxget_tim のプロトタイプ宣言
414 cpu_defs.h ではプロセッサ略称(cpu_defs.h の置かれているディレクトリ名
415 を大文字にしたもの),sys_defs.h ではシステム略称(sys_defs.h の置かれ
416 ているディレクトリ名を大文字にしたもの)をマクロ定義する.
422 プロセッサがビッグエンディアンの場合には SIL_ENDIAN_BIG(=1),リトル
423 エンディアンの場合には SIL_ENDIAN_LITTLE(=0)にマクロ定義する.
427 (10-1) kernel_abort(void)
429 assertマクロにおけるアサーションの失敗や,サービスコールが致命的なエラー
430 を返した場合に,システムを停止させる関数またはマクロ.kernel_exit を呼
431 び出す方法も考えられるが,デバッグを容易にするためには,インライン関数
432 かマクロで定義し,その場でシステムを停止させる処理に定義するのが望まし
433 い(kernel_exit を呼び出すと,エラーが発生した時点の状態から変化してし
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 に記述する.
448 ヘッダファイルをインクルードする記述は,以下のルールに従うのを原則とす
451 ANSI Cの標準インクルードファイルは,#include <…> でインクルードする.
452 また,Makefile または Makefile.config で INCLUDES に -Iオプションで指
453 定したディレクトリにあるファイルは,#include <…> でインクルードする.
454 カーネルを構成するファイルからのインクルードに対しては,以下のディレク
455 トリにあるファイルがこれに該当する(ターゲットにも依存).
458 jsp/config/$(CPU)/$(SYS)
459 jsp/config/$(CPU)-$(TOOL)
460 jsp/config/$(CPU)-$(TOOL)/$(SYS)
463 その他のインクルードファイルは #include "…" でインクルードする.カー
464 ネルを構成するファイルからのインクルードに対しては,以下のディレクトリ
465 にあるファイルがこれに該当する(ターゲットにも依存).
469 (1) タスクコンテキストブロックのデータ型
473 ターゲット依存のタスクコンテキストを保存するために,TCB 中に持つことが
478 (2-1) BOOL sense_context(void)
480 現在の実行コンテキストが,タスクコンテキストの場合は FALSE,非タスクコ
481 ンテキストの場合は TRUE を返す関数.
483 (2-2) BOOL sense_lock(void)
485 現在のシステム状態が,CPUロック状態の場合は TRUE,CPUロック解除状態の
488 (2-3) BOOL t_sense_lock(void)
490 タスクコンテキストにおいて,現在のシステム状態が,CPUロック状態の場合
491 は TRUE,CPUロック解除状態の時は FALSE を返す関数.この関数が,非タス
494 (2-4) BOOL i_sense_lock(void)
496 非タスクコンテキストにおいて,現在のシステム状態が,CPUロック状態の場
497 合は TRUE,CPUロック解除状態の時は FALSE を返す関数.この関数が,タス
500 ※ 原理的には,sense_lock が提供されていれば t_sense_lock と
501 i_sense_lock は必要なく,逆に t_sense_lock と i_sense_lock が提供され
502 ていれば sense_lock を実現することはできるが,ターゲットに依存せずに高
503 い実行効率を実現するために,ターゲット依存部が3つの関数を提供すること
508 (3-1) void t_lock_cpu(void)
510 タスクコンテキストにおいて,CPUロック解除状態から,CPUロック状態に遷移
511 させる関数.この関数が,CPUロック状態で呼ばれることはない.また,非タ
514 (3-2) void t_unlock_cpu(void)
516 タスクコンテキストにおいて,CPUロック状態から,CPUロック解除状態に遷移
517 させる関数.この関数が,CPUロック解除状態で呼ばれることはない.また,
518 非タスクコンテキストから呼ばれることもない.
520 (3-3) void i_lock_cpu(void)
522 非タスクコンテキストにおいて,CPUロック解除状態から,CPUロック状態に遷
523 移させる関数.この関数が,CPUロック状態で呼ばれることはない.また,タ
526 (3-4) void i_unlock_cpu(void)
528 非タスクコンテキストにおいて,CPUロック状態から,CPUロック解除状態に遷
529 移させる関数.この関数が,CPUロック解除状態で呼ばれることはない.また,
530 タスクコンテキストから呼ばれることもない.
534 (4-1) void dispatch(void)
536 タスクディスパッチャ(以下,単にディスパッチャと言う)を明示的に呼ぶた
537 めの関数.タスクコンテキストから呼ばれたサービスコール処理から,CPUロッ
540 この関数が呼ばれると,関数を呼んだタスクのコンテキストを保存し, 実行
541 できるタスクの中で最高優先順位のタスク(schedtsk)のコンテキストを復帰
542 して実行状態とする.実行できるタスクがない場合(schedtsk が NULL の場
543 合)には,割込みを許可して,実行できるタスクができるまで待つ.ここで,
544 実行できるタスクができるのを待つ間に起動された割込みハンドラの出口で,
545 ディスパッチャが呼ばれないように対策することが必要である.具体的には,
546 実行できるタスクができるのを待つ間,一時的に非タスクコンテキストに切り
547 換えるか,ディスパッチを保留するようにする.
549 新たに実行状態になったタスクが,タスク例外処理ルーチンの起動条件を満た
550 していれば,タスク例外処理ルーチンを起動する.また,この関数を呼び出し
551 たタスクが次に実行状態になった時,タスク例外処理ルーチンの起動条件を満
552 たしていれば,タスク例外処理ルーチンの起動を行う.タスク例外処理ルーチ
553 ンの起動には,ターゲット非依存部が提供する calltex または call_texrtn
556 (4-2) void exit_and_dispatch(void)
558 現在実行中のコンテキストを捨て,ディスパッチャを呼び出すための関数.タ
559 スクコンテキストから呼ばれたサービスコール(具体的には,ext_tsk)処理
560 またはカーネルの初期化処理から,CPUロック状態で呼ばれる.
562 この関数が呼ばれると,関数を呼んだタスクのコンテキストを保存せず,実行
563 できるタスクの中で最高優先順位のタスク(schedtsk)のコンテキストを復帰
564 して実行状態とする.実行できるタスクがない場合(schedtsk が NULL の場
565 合)の処理は,dispatch と同様である.
567 新たに実行状態になったタスクが,タスク例外処理ルーチンの起動条件を満た
568 していれば,タスク例外処理ルーチンを起動する.
570 この関数は,カーネルの初期化処理からも呼ばれるために,非タスクコンテキ
571 ストからも呼ばれても正しく処理できることが必要である.なお,この関数か
574 (5) 割込みハンドラ/CPU例外ハンドラの出入口処理
576 (5-1) INTHDR_ENTRY(inthdr)
577 (5-2) INT_ENTRY(inthdr)
579 INTHDR_ENTRY(inthdr) は起動番地が inthdr の割込みハンドラを呼び出す出
580 入口処理ルーチンを生成するマクロ,INT_ENTRY(inthdr) は生成する出入口処
581 理ルーチンの先頭のラベルを得るためのマクロである.INT_ENTRY(inthdr) で
582 得られるラベルは,割込みハンドラ初期化ブロックに出入口処理ルーチンの先
583 頭番地を登録するために使われる.出入口処理ルーチンを生成する必要がない
584 場合には,INTHDR_ENTRY(inthdr) を単に extern 宣言に展開すればよい.
586 割込みハンドラの出入口処理は,実行コンテキストを非タスクコンテキストに
587 切り換え,スクラッチレジスタを保存して,割込みハンドラを呼び出す.割込
588 みハンドラから戻ると,元の実行コンテキストに戻すとともに,必要に応じて
589 ディスパッチとタスク例外処理ルーチンの起動処理を行う.ディスパッチとタ
590 スク例外処理ルーチンの起動処理は,具体的には次のように行う.
592 (a) 以下の処理は,割込みハンドラがタスクコンテキスト実行中に起動された
593 場合で,reqflg が TRUE の時のみ行う.
595 (b) enadsp が TRUE で,実行状態のタスク(runtsk)と実行できるタスクの
596 中で最高優先順位のタスク(schedtsk)が一致していない場合には,前者のタ
597 スクのコンテキストを保存し,後者のタスクのコンテキストを復帰して実行状
598 態とする.実行できるタスクがない場合(schedtsk が NULL の場合)には,
599 割込みを許可して,実行できるタスクができるまで待つ.ここでも,実行でき
600 るタスクができるのを待つ間に起動された割込みハンドラの出口で,タスクディ
601 スパッチャが呼ばれないようにすることが必要であるが,出入口処理を非タス
602 クコンテキストで実行していれば,特に対策する必要はない.
604 (c) 実行状態のタスク((b) でタスクディスパッチを行った場合は,新たに実
605 行状態となったタスク)がタスク例外処理ルーチンの起動条件を満たしていれ
606 ば,タスク例外処理ルーチンを起動する.また,(b) でタスクディスパッチを
607 行った場合は,それまで実行状態であったタスクが次に実行状態になった時,
608 タスク例外処理ルーチンの起動条件を満たしていれば,タスク例外処理ルーチ
609 ンの起動を行う.タスク例外処理ルーチンの起動には,ターゲット非依存部が
610 提供する calltex または call_texrtn を用いることができる.
612 このマクロで生成するルーチンでは,上記の処理の一部のみを行い,残りの処
613 理は別に用意したルーチンに任せてもよい.具体的には,タスクディスパッチ
614 とタスク例外処理ルーチンの起動処理は,別にルーチンとして用意するのが適
617 (5-3) EXCHDR_ENTRY(exchdr)
618 (5-4) EXC_ENTRY(exchdr)
620 EXCHDR_ENTRY(exchdr) は起動番地が exchdr のCPU例外ハンドラを呼び出す出
621 入口処理ルーチンを生成するマクロ,EXC_ENTRY(exchdr) は生成する出入口処
622 理ルーチンの先頭のラベルを得るためのマクロである.EXC_ENTRY(exchdr) で
623 得られるラベルは,CPU例外ハンドラ初期化ブロックに出入口処理ルーチンの
624 先頭番地を登録するために使われる.出入口処理ルーチンを生成する必要がな
625 い場合には,EXCHDR_ENTRY(exchdr) を単に extern 宣言に展開すればよい.
627 CPU例外ハンドラの出入口処理は,実行コンテキストを非タスクコンテキスト
628 に切り換え,スクラッチレジスタを保存して,CPU例外ハンドラを呼び出す.
629 CPU例外ハンドラには,VP型のパラメータ p_excinf を渡す.このパラメータ
630 は,CPU例外に関する情報を保存したスタック領域へのポインタであることを
631 想定しているが,具体的にはターゲット毎に定める.
633 CPU例外ハンドラから戻ると,元の実行コンテキストに戻すとともに,必要に
634 応じてタスクディスパッチとタスク例外処理ルーチンの起動処理を行う.タス
635 クディスパッチとタスク例外処理ルーチンの起動処理は,割込みハンドラの出
636 入口処理の場合と同様である(上記の (a)〜(c)).
638 (6) タスクコンテキスト設定処理(cpu_context.h)
640 ターゲット依存のタスクコンテキストを設定するために create_context と
641 activate_context の2つの関数を用意する.2つの関数を呼び出すことで,タ
642 スクのコンテキスト(具体的には,タスクコンテキストブロックの内容とタス
643 クのスタック領域)をタスクが起動できる状態に設定する.2つの関数は呼ば
644 れるタイミングが異なるだけで明確な役割分担はなく,どのような処理はどち
645 らの関数で行わなければならないという制約はない.
647 これらの関数の宣言およびマクロの定義は,cpu_context.h に含める.これは,
648 cpu_config.h を処理する時点では TCB が定義されていないためである.
650 (6-1) void create_context(TCB *tcb)
652 タスクが休止状態に移行する時に呼ばれる.具体的には,タスクの生成時
653 (JSPカーネルでは,CRE_TSK でタスクを生成するため,タスク管理モジュー
654 ルの初期化)とタスクの終了時(ext_tsk,ter_tsk)に呼ばれる.
656 (6-2) void activate_context(TCB *tcb)
658 タスクが実行できる状態に移行する時に呼ばれる.具体的には,act_tsk でタ
659 スクを起動する時,タスクの終了時(ext_tsk,ter_tsk)に起動要求のキュー
660 イングにより再起動する時,TA_ACT 属性を指定してタスクを生成した時(タ
663 (6-3) ACTIVATED_STACK_SIZE(オプション)
665 ext_tsk がスタック上に確保するダミー領域のサイズを定義するためのマクロ.
666 ダミー領域が必要ない場合は,このマクロを定義する必要はない.
668 ext_tsk は,自タスクを終了させた後,自タスクに対して create_context を
669 呼ぶ.また,タスクの起動要求がキューイングされていた場合には,自タスク
670 に対して activate_context も呼ぶ.create_context と activate_context
671 は,対象タスクのスタック領域を書き換える場合があるが,これが ext_tsk
672 (およびそこから呼ばれる関数)が使用しているスタック領域と重なった場合,
673 自分の使用しているスタック領域を自分で破壊する結果になる.
675 ACTIVATE_STACK_SIZE を,create_context と activate_context が書き換え
676 るスタック領域のサイズ(厳密には,スタックの底から何バイトめまでを書き
677 換えるか)にマクロ定義しておくと,ext_tsk 内でスタック上に定義したサイ
678 ズのダミー領域を確保し,自分の使用しているスタック領域を破壊するのを防
681 なお,これを実現するために,処理系依存の機能である alloca を用いている.
682 gcc は alloca をサポートしているが,他のコンパイラを用いる場合には,
683 alloca をサポートしているか確認が必要である.また,alloca を用いる場合
684 にインクルードファイルが必要な場合には,tool_config.h からインクルード
689 (7-1) void cpu_initialize(void)
691 プロセッサ依存の初期化処理.カーネルの初期化処理で,カーネル内の各モジュ
694 (7-2) void sys_initialize(void)
696 システム依存の初期化処理.カーネルの初期化処理で,cpu_initialize に続
699 (7-3) void tool_initialize(void)
701 開発環境依存の初期化処理.カーネルの初期化処理で,sys_initialize に続
704 上の3つの関数は,カーネル起動処理(kernel_start 関数)の最初でこの順に
705 呼び出される.3つの関数を呼び出した後の時点で,CPUロック状態になってい
708 (7-4) void cpu_terminate(void);
710 プロセッサ依存の終了時処理.カーネルの終了処理で呼ばれる.
714 システムの終了処理.カーネルの終了処理で,cpu_terminate に続いて呼ばれ
715 る.この関数からはリターンしない.ROMモニタを持つシステムでは,ROMモニ
718 (7-6) call_atexit(void)
720 開発環境依存の終了処理.必要に応じて,atexit によって登録された関数の
721 実行や C++ におけるデストラクタの実行を行う.
723 (8) 割込みハンドラ/CPU例外ハンドラの定義
725 (8-1) void define_inh(INHNO inhno, FP inthdr)
727 割込みハンドラ番号 inhno の起動番地を inthdr に設定する.割込み管理機
730 (8-2) void define_exc(EXCNO excno, FP exchdr)
732 CPU例外ハンドラ番号 excno の起動番地を exchdr に設定する.CPU例外ハン
735 (9) CPU例外発生時点のシステム状態の参照
737 (9-1) BOOL exc_sense_context(VP p_excinf)
739 CPU例外が発生したコンテキストが,タスクコンテキストの場合は FALSE,非
740 タスクコンテキストの場合は TRUE を返す関数.CPU例外ハンドラから呼ばれ
741 たサービスコール処理から呼ばれる.p_excinf には,CPU例外ハンドラへの引
744 (9-2) BOOL exc_sense_lock(VP p_excinf)
746 CPU例外が発生したコンテキストが,CPUロック状態の場合は TRUE,CPUロック
747 解除状態の時は FALSE を返す関数.CPU例外ハンドラから呼ばれたサービスコ
748 ール処理から呼ばれる.p_excinf には,CPU例外ハンドラへの引数がそのまま
751 (10) TCB 中のフィールドのビット幅の定義(オプション)
753 TCB 中のフィールドの配置は性能に大きく影響すると思われるため,ターゲッ
754 ト依存にフィールドのビット幅を変更できるようにしている.具体的には,以
755 下の2つのフィールドのビット幅を変更できる.これらのマクロを定義しない
758 (10-1) TBIT_TCB_TSTAT tstat(タスク状態)のビット幅
759 (10-2) TBIT_TCB_PRIORITY priority(優先度)フィールドのビット幅
761 32ビットプロセッサの場合には,これらを 8 に定義するのが効率的である.
763 (11) ビットマップサーチにビットサーチ命令を使うための定義(オプション)
765 プロセッサがビットサーチ命令を持つ場合,レディキューのビットマップサー
766 チにその命令を用いた方が効率がよい.その場合,以下の関数およびマクロを
769 (11-1) CPU_BITMAP_SEARCH
771 プロセッサのビットサーチ命令を用いる場合,このマクロを定義する.このマ
772 クロを定義することにより,ターゲット非依存部から bitmap_search が取り
775 (11-2) UINT bitmap_search(UINT bitmap)
777 ビットサーチを行う関数.bitmap 内の 1 のビットの内,最も下位のものをサ
778 ーチし,そのビット番号を返す.ビット番号は,最下位ビット(LSB)を 0 と
779 する.bitmap の下位16ビットに,必ず 1 のビットがある(すなわち,bitmap
780 に 0 が指定されることはない)ことを仮定してよい.
782 標準ライブラリにビットサーチ命令を用いた ffs がある場合,ffs を用いて
783 bitmap_search を次のように定義すればよい.
784 #define bitmap_search(bitmap) (ffs(bitmap) - 1)
786 プロセッサの持つビットサーチ命令が,最も上位の 1 のビットをサーチする
787 ものである場合には,次のマクロを定義して,ビットの割付けを変更すること
790 (11-3) UINT PRIMAP_BIT(pri)
792 タスク優先度の内部表現(最高優先度を 0 とする)を,それに対応するビッ
793 トマップに変換する.デフォルトの定義は次の通り.
794 #define PRIMAP_BIT(pri) (1 << (pri))
796 (12) ターゲット依存のサービスコール(オプション)
798 以下のサービスコールをターゲット依存にサポートする場合には,その処理ル
806 (13) 性能評価用システム時刻関連の定義(オプション)
808 (13-1) SUPPORT_VXGET_TIM
810 ターゲット非依存部の vxget_timサービスコール処理を用いる場合に,このマ
815 ターゲット依存のタイマモジュールのインクルードファイル.ターゲット非依
816 存部の vxget_timサービスコール処理を用いる場合,ターゲット依存のタイマ
817 モジュールが必要になる.そのためのインクルードファイルである
818 hw_timer.h は,システムサービスのシステムクロックドライバで用いるもの
821 (14) カーネルの内部識別名のリネームとその解除(cpu_rename.h,
822 cpu_unrename.h,sys_rename.h,sys_unrename.h)
824 ターゲット依存部で用いている識別名(モジュール内に閉じた識別名を除く)
825 を,μITRON4.0仕様に従って _kernel_ で始まるものにリネームする必要があ
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」を
836 また,cpu_config.h の先頭から cpu_rename.h を,sys_config.h の先頭から
837 sys_rename.h をインクルードする.
839 genrename が生成するファイルは次のような内容である.xxx_rename.def に
840 xxxx という識別子が含まれている場合,xxx_rename.h には次のようなマクロ
843 #define xxxx _kernel_xxxx
845 #define _xxxx __kernel_xxxx
846 #endif /* LABEL_ASM */
848 ここで,LABEL_ASM は,アセンブリ言語レベルの識別名が,C言語レベルの識
849 別名の先頭に "_" が付いたものになる場合に定義すべきマクロである(定義
850 の方法については「システム構築方法の設定」を参照).
852 また,xxx_unrename.h には次のようなマクロ定義解除が生成される.
857 #endif /* LABEL_ASM */
859 (15) トレースログのためのマクロ定義(tool_config.h)
861 カーネルのトレースログの取得は,開発環境依存部でトレースログのためのマ
862 クロを定義することによって行う.トレースログのためのマクロは約150種類
863 あり,取得したいログ情報に対応するマクロを定義する.トレースログを取得
864 しない場合には,これらのマクロを空に定義すればよい.
872 (16-2) void sys_putc(char c)
874 ターゲットシステムの低レベルの文字出力ルーチン.ROMモニタを持つシステ
875 ムでは,ROMモニタ呼び出しで実現することを想定している.
877 (16-3) OMIT_CALLTEX(オプション)
879 ターゲット非依存部が calltex を提供する必要がない場合に,このマクロを
880 定義する.詳しくは,「タスク例外処理ルーチンの起動関数とその中で参照す
881 る TCB のフィールド」の節を参照のこと.
883 (16-4) LABEL_ALIAS(new_label, defined_label)(オプション,tool_config.h)
885 new_label を defined_label と同じアドレスに定義するためのマクロ.この
886 ようなマクロを実現できない場合には,定義を省略することができる.このマ
887 クロ定義は,tool_config.h の中で行うのを標準とする.
889 (16-5) COPYRIGHT_CPU(オプション)
890 (16-6) COPYRIGHT_SYS(オプション)
892 カーネル起動時のメッセージに,それぞれプロセッサ依存部およびシステム依
895 (16-7) __STK_UNIT(オプション)
896 (16-8) __MPF_UNIT(オプション)
898 標準では,スタック領域と固定長メモリプール領域は,VP型のサイズにアライ
899 ンする.これを,より大きい単位でアラインさせる必要がある場合には,
900 __STK_UNIT と __MPF_UNIT を,それぞれアラインさせる単位のデータ型に定
901 義する.ただし,__STK_UNIT および __MPF_UNIT のサイズは,2の巾乗でなけ
904 (16-9) __EMPTY_LABEL(x, y)(オプション,tool_config.h)
906 型 x のサイズ 0 の配列 y を定義するためのマクロ.サイズ 0 の配列を定義
907 できるコンパイラ(GNU開発環境はこれに該当)では定義を省略することがで
908 きる.このマクロ定義は,tool_config.h の中で行うのを標準とする.
911 4.ターゲット依存部が用いることができるターゲット非依存部の変数・関数
917 実行状態のタスク(=プロセッサがコンテキストを持っているタスク)の TCB
918 を指すポインタ.実行状態のタスクがない場合は NULL にする.サービスコー
919 ルの処理中で,自タスク(サービスコールを呼び出したタスク)に関する情報
920 を参照する場合は runtsk を使う.カーネルの初期化処理以外で,この変数を
921 書き換えるのは,タスクディスパッチャ(すなわち,ターゲット依存部)のみ
926 実行できるタスクの中で最高優先順位のタスクの TCB を指すポインタ.実行
927 できるタスクがない場合は NULL となる.ディスパッチ禁止状態など,ディス
928 パッチが保留されている間は,runtsk と一致しているとは限らない.この変
929 数を書き換えるのはスケジューラのみで,ターゲット依存部はこの変数を書き
934 割込みハンドラ/CPU例外ハンドラの出口処理に,タスクディスパッチまたは
935 タスク例外処理ルーチンの起動を要求することを示すフラグ.この変数はサー
936 ビスコール処理(ターゲット非依存部)でセットし,割込みハンドラ/CPU例
937 外ハンドラの出口処理(ターゲット依存部)で参照/クリアする.
941 タスクディスパッチ許可状態である(すなわち,タスクディスパッチ禁止状態
942 でない)ことを示すフラグ.この変数はサービスコール(dis_dsp,ena_dsp,
943 ターゲット依存に chg_ixx)処理の中で書き換える.
945 また,タスクディスパッチャ(ターゲット依存部)の中で,実行できるタスク
946 ができるのを待つ間に起動された割込みハンドラの出口でタスクディスパッチャ
947 が呼ばれないようにするために,この変数を一時的に FALSE に設定すること
950 (2) タスク例外処理ルーチンの起動関数とその中で参照する TCB のフィールド
952 (2-1) void calltex(void)
953 (2-2) void call_texrtn(void)
955 タスク例外処理ルーチンの起動を行う関数.calltex は,実行状態のタスクが
956 タスク例外処理ルーチンの起動条件を満たしていれば,call_texrtn を呼び出
957 す.call_texrtn は,タスク例外処理ルーチンの呼び出しを行う.タスク例外
958 処理ルーチンを呼び出す時は,一時的にCPUロックを解除する.
960 これらの関数は,ディスパッチャや割込みハンドラ/CPU例外ハンドラの出口
961 処理から,CPUロック状態で呼ばれることを想定している.calltex を呼び出
962 すのが最も簡単であるが,実行効率を上げるためには,起動条件のチェックを
963 アセンブリ言語で記述し,call_texrtn を呼び出した方がよい.チェックすべ
964 き起動条件については,ターゲット非依存部の calltex のソースコードを参
965 照すること.またその場合には,OMIT_CALLTEX をマクロ定義することで,タ
966 ーゲット非依存部から calltex が取り除かれる.
971 call_texrtn を呼び出すために,起動条件のチェックをアセンブリ言語で記述
972 する場合には,TCB 内のこれらのフィールドを参照する必要がある.
976 異常事象を通知するために,システムログ機能へのログ出力関数を用いること
977 ができる.システムログ機能については,ユーザズマニュアルを参照すること.
980 5.システムサービス用のデータ型や関数など
982 5.1 システムインタフェースレイヤ(SIL)のための定義
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に記述する.
992 (1-1) void sil_dly_nse(UINT dlytim)
994 dlytimで指定される時間(単位: 1ナノ秒)待つ関数をターゲット依存部で提
997 実現方法はターゲット依存であるが,以下の関数をアセンブリ言語で記述した
998 ものを,プロセッサ依存部に含めるのを標準的な方法とする.アセンブリ言語
999 で記述するのは,コンパイラの最適化に依存しないようにするためである.ま
1000 たこの関数は,できる限りメモリアクセスを行わないように実装すべきである.
1002 void sil_dly_nse(UINT dlytim)
1004 if (dlytim > SIL_DLY_TIM1) {
1005 dlytim -= SIL_DLY_TIM1;
1006 while (dlytim > SIL_DLY_TIM2) {
1007 dlytim -= SIL_DLY_TIM2;
1012 (1-2) SIL_DLY_TIM1(オプション)
1013 (1-3) SIL_DLY_TIM2(オプション)
1015 sil_dly_nseを上記の標準的な方法で実現した場合,この2つの定数をシステム
1016 依存部でマクロ定義する.なお,この2つの定数の決定を助けるプログラムを
1017 用意している.希望される方は,相談されたい.
1019 (2) 割込みロック状態の制御関連(オプション)
1025 ターゲット依存で割込みロック状態の制御方法を変更したい場合には,これら
1026 のマクロにその方法を定義する.これらマクロを定義しない場合には, ター
1027 ゲット非依存部において,カーネルのCPUロックの機能を用いて割込みロック
1034 リトルエンディアンプロセッサではSIL_ENDIAN_LITTLE(=0),ビッグエンディ
1035 アンプロセッサではSIL_ENDIAN_BIG(=1)にマクロ定義する.
1037 (4) エンディアンの反転(オプション)
1039 (4-1) VH SIL_REV_ENDIAN_H(VH data)
1040 (4-2) VW SIL_REV_ENDIAN_W(VW data)
1042 エンディアンの反転を効率よく実現する方法がある場合には,これらのマクロ
1043 にその方法を定義する.これらのマクロを定義しない場合には,標準的な方法
1046 (5) エンディアン反転付きのメモリ空間アクセス(オプション)
1048 エンディアンを反転してメモリを読出し/書込みする効率的な方法がある場合,
1049 該当するメモリ空間アクセス関数をターゲット依存部で用意し,ターゲット非
1050 依存部の標準的な定義を無効にするためのマクロを定義する.
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
1057 リトルエンディアンプロセッサでは,これらのメモリ空間アクセス関数をター
1058 ゲット依存部で用意し,右に示すマクロを定義する.
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
1065 ビッグエンディアンプロセッサでは,これらのメモリ空間アクセス関数をター
1066 ゲット依存部で用意し,右に示すマクロを定義する.
1068 (6) 標準のアクセス関数の無効化(オプション)
1070 (6-1) OMIT_SIL_ACCESS
1072 シミュレーション環境などで,すべてのメモリ空間アクセス関数をターゲット
1073 依存部で用意する場合には,ターゲット非依存部の標準的な定義を無効にする
1076 5.2 システムクロックドライバ用のデータ型や関数など
1078 ターゲット依存部で提供すべきシステムクロックドライバ用のデータ型や関数
1079 などは次の通りである.これらの定義は,hw_timer.h(またはそれらからイン
1080 クルードされるファイル)に含める.関数の実体が必要な場合には,適切なファ
1085 タイマ割込みハンドラのベクタ番号を定義したマクロを,ターゲット依存部で
1090 (2-1) void hw_timer_initialize(void)
1092 タイマを初期化し,タイマ割込みを周期的に発生させる関数を,ターゲット依
1093 存部で提供する.タイマ割込みの周期は,TIC_NUMEとTIC_DENOで指定された時
1096 (2-2) void hw_timer_int_clear(void)
1098 タイマ割込み要求をクリアする関数を,ターゲット依存部で提供する.
1100 (2-3) void hw_timer_terminate(void)
1102 タイマの動作を停止させ,タイマ割込みを発生しないようにする関数を,ター
1105 (3) 性能評価用システム時刻参照機能関連(オプション)
1107 ターゲット非依存部のvxget_timサービスコール処理を用いる場合に,以下の
1108 データ型や関数などをターゲット依存部で提供する.
1114 (3-2) CLOCK hw_timer_get_current(void)
1116 タイマの現在値を読み出し,内部表現で返す関数.
1118 (3-3) BOOL hw_timer_fetch_interrupt(void)
1120 タイマ割込み要求をチェックする関数.タイマ割込みが要求されている場合に
1121 TRUE,要求されていない場合にFALSEを返す.
1123 (3-4) UINT TO_USEC(CLOCK clock)
1125 タイマ値の内部表現を,1μ秒単位に変換するためのマクロ(または関数).
1126 hw_timer_get_currentで読み出した値を,タイマ割込み発生からの経過時間
1127 (単位: 1μ秒)に変換するために用いる.
1129 (3-5) BOOL BEFORE_IREQ(CLOCK clock)
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を返すマクロ(または関数)である.
1141 5.3 シリアルインタフェースドライバ用のデータ型や関数など
1143 ターゲット依存部で提供すべきシリアルインタフェースドライバ用のデータ型
1144 や関数などは次の通りである.これらの定義は,別に記述がない限り,
1145 hw_serial.h(またはそこからインクルードされるファイル)に含め,必要な
1146 コンフィギュレーション情報をhw_serial.cfgに記述する.関数の実体が必要
1149 シリアルインタフェースドライバの中で,ターゲットのシリアルI/Oデバイス
1150 に依存する部分を,シリアルI/Oデバイスドライバと呼ぶ.シリアルI/Oデバイ
1151 スドライバは,おおよそ,ITRONデバイスドライバ設計ガイドラインのPDICに
1152 相当する.PDICに相当するファイルで,他のシステムにも共通に使える可能性
1153 がある場合には,pdic/simple_sioディレクトリに置く.
1157 シリアルインタフェースドライバがサポートするシリアルポート数を定義する
1158 マクロ.このマクロは,cpu_config.hまたはsys_config.h(またはそれらから
1159 インクルードされるファイル)で定義する.
1161 (2) シリアルI/Oデバイスの割込みハンドラとその登録
1163 シリアルI/Oデバイスの割込みハンドラをターゲット依存部で提供し,それを
1164 カーネルに登録する静的APIをhw_serial.cfgに含める.シリアルI/Oデバイス
1165 の割込ハンドラのベクタ番号は,hw_serial.h(またはそこからインクルード
1166 されるファイル)でマクロ定義し,hw_serial.cfgからhw_serial.hをインクル
1169 (3) void sio_initialize(void)
1171 シリアルI/Oデバイスドライバを初期化するルーチン.この関数は,シリアル
1172 インタフェースドライバのターゲット非依存部の初期化ルーチンから呼び出さ
1177 シリアルI/Oポート管理ブロックのデータ型(hw_serial.hには,型宣言だけ含
1180 (5) SIO_ERDY_SNDとSIO_ERDY_RCV
1182 送信可能コールバックの識別番号をSIO_ERDY_SNDに,受信通知コールバックの
1183 識別番号をSIO_ERDY_RCVにマクロ定義する.コールバックの禁止/許可を行な
1184 うサービスコール(sio_ena_cbrとsio_dis_cbr)で用いる.
1188 以下のデバイスサービルルーチンは,(少なくとも)シリアルI/Oポートから
1189 の割込みが禁止された状態で呼び出される.また,タスクコンテキスト,非タ
1190 スクコンテキストのいずれで呼び出される場合もある(いずれで呼び出されて
1193 (6-1) SIOPCB *sio_opn_por(ID siopid, VP_INT exinf)
1195 siopidで指定されるシリアルI/Oポートをオープンする関数.exinfはシリアル
1196 I/Oポートに対する拡張情報で,コールバックを呼ぶ時にポートを区別するた
1199 (6-2) void sio_cls_por(SIOPCB *siopcb)
1201 siopcbで指定されるシリアルI/Oポートをクローズする関数.
1203 (6-3) BOOL sio_snd_chr(SIOPCB *siopcb, char c)
1205 siopcbで指定されるシリアルI/Oポートに,cで示される文字を送信する関数.
1206 文字を送信レジスタに入れた場合にはTRUEを,前に送信した文字の送信が終わっ
1207 ていないために,文字を送信レジスタに入れられなかった場合にはFALSEを返
1210 (6-4) INT sio_rcv_chr(SIOPCB *siopcb)
1212 siopcbで指定されるシリアルI/Oポートから文字を読む関数.文字を受信して
1213 いた場合,読んだ文字のコードは正の値として返し,文字を受信していない場
1216 (6-5) sio_ena_cbr(SIOPCB *siopcb, UINT cbrtn)
1218 siopcbで指定されるシリアルI/Oポートからの,cbrtnで指定されるコールバッ
1219 クを許可する.cbrtnには,SIO_ERDY_SNDかSIO_ERDY_RCVを指定できる.
1221 (6-6) sio_dis_cbr(SIOPCB *siopcb, UINT cbrtn)
1223 siopcbで指定されるシリアルI/Oポートからの,cbrtnで指定されるコールバッ
1224 クを禁止する.cbrtnには,SIO_ERDY_SNDかSIO_ERDY_RCVを指定できる.
1228 ターゲット依存部は,必要なタイミングで,シリアルインタフェースドライバ
1229 のターゲット非依存部に含まれる以下のコールバックルーチンを呼び出びださ
1230 なければならない.ただし,それぞれのコールバックが禁止されている時は,
1231 コールバックルーチンを呼び出してはならない.
1233 コールバックルーチンは,(少なくとも)シリアルI/Oポートからの割込みが
1234 禁止された状態で,非タスクコンテキストで呼び出す.exinfには,シリアル
1235 I/Oポートのオープン時に指定された拡張情報を渡す.
1237 (7-1) void sio_ierdy_snd(VP_INT exinf)
1239 送信可能コールバックルーチン.シリアルI/Oポートに対して文字が送信でき
1240 る状態になった場合に呼び出す.シリアルインタフェースドライバは,このコ
1241 ールバックルーチンの中で,sio_snd_chrを呼び出して次の文字を送信するか,
1242 送信すべき文字がない場合には送信可能コールバックを禁止する.
1244 (7-2) void sio_ierdy_rcv(VP_INT exinf)
1246 受信通知コールバックルーチン.シリアルI/Oポートから文字を受信した場合
1247 に呼び出す.シリアルインタフェースドライバは,このコールバックルーチン
1248 の中で,必ずsio_rcv_chrを呼び出して受信した文字を取り出す.
1250 5.4 システムログタスク用のための定義
1252 ターゲット依存部で提供すべきシステムログタスクのための定義は次の通りで
1253 ある.これらの定義は,cpu_config.hまたはsys_config.h(またはそれらから
1258 システムログタスクが,システムログを出力するシリアルポートのIDを定義し
1261 (2) システムログタスク関連の定義(オプション)
1263 システムログタスクに関する以下のマクロをターゲット依存部で提供する.こ
1264 れらのマクロをターゲット依存部で定義しない場合には,デフォルトの値が使
1267 (2-1) LOGTASK_PRIORITY システムログタスクの初期優先度
1268 (2-2) LOGTASK_STACK_SIZE システムログタスクのスタックサイズ
1269 (2-3) LOGTASK_INTERVAL システムログタスクの動作間隔(単位: ミリ秒)
1274 (1) タスクディスパッチャの2通りの実装方針
1276 タスクディスパッチャの実装方針として,コンテキストの保存・復帰とタスク
1277 例外処理ルーチンの起動を一連のルーチンで行う方針(これを方針Aと呼ぶ)
1278 と,コンテキストの保存・実行するタスクの選択・コンテキストの復帰とタス
1279 ク例外処理ルーチンの起動をばらばらのルーチンで行う方針(これを方針Bと
1280 呼ぶ)がある.方針Bは,保存するコンテキスト情報を状況に応じて必要最少
1281 限にすることが容易になるという利点がある.ただし,シミュレーション環境
1282 の場合,実現方法によっては方針Bが採れない可能性も考えられる.
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 した後,コンテキストを復帰する処理に続く処理としてタスク例外処理ルーチ
1298 JSPカーネルでは,方針Aを採るか方針Bを採るかをターゲット依存部に任せる
1299 こととする.そのために,タスク例外処理ルーチンの起動をタスクディスパッ
1304 割込みハンドラの出入口処理の内容は,プロセッサの割込みアーキテクチャに
1305 より大きく異なるが,おおよその処理の流れは次の通りである.CPU例外ハン
1306 ドラの出入口処理も,引数を渡すことを除いては,おおよその処理の流れは同
1307 様である.ただし,プロセッサが割込みとCPU例外で異なる扱いをする場合は,
1308 実際の出入口処理はかなり異なったものとなる.
1310 ------------------------------------------------------------
1311 レジスタの保存(主にスクラッチレジスタ)
1312 割込みスタックへ切換え(最も外側のハンドラのみ)
1316 タスクスタックへ切換え(最も外側のハンドラのみ)
1317 if (最も外側のハンドラ && reqflg) {
1318 if (enadsp && runtsk != schedtsk) {
1320 タスク例外処理ルーチンの起動処理(calltex)
1323 タスク例外処理ルーチンの起動処理(calltex)
1326 レジスタの復帰(主にスクラッチレジスタ)
1329 ※「ハンドラ」は,割込みハンドラとCPU例外ハンドラの総称.
1330 ※「最も外側のハンドラ」は「戻り先がタスク」と言い換えることが
1332 ------------------------------------------------------------
1334 この中で,内側のif文がいずれの場合でもタスク例外処理ルーチンの起動処理
1335 を行う必要があることから(ただし,タスク例外処理ルーチンの起動を行う対
1336 象タスクは異なる),内側のif文は次のように最適化できる場合がある.
1338 ------------------------------------------------------------
1339 if (enadsp && runtsk != schedtsk) {
1342 タスク例外処理ルーチンの起動処理(calltex)
1343 ------------------------------------------------------------
1346 7.M68K(68LC040)用のターゲット依存部
1350 すべてのタスクをスーパーバイザモードで実行することとし,ユーザモードは
1353 (2) 実行コンテキストとCPUロック状態
1355 タスクコンテキストはマスタモード,非タスクコンテキストは割込みモードで
1356 実行する.sense_context は,SR 中のマスタ/割込みモードビットを参照す
1359 IPM が 7 の時(NMI を除くすべての割込みが禁止される)かつその時に限り,
1360 CPUロック状態であるものとする.sense_lock は,SR 中の IPM を参照する方
1361 法で実現する.NMI はカーネルの管理外の割込みなので,CPUロック状態で
1362 NMI が受け付けられるのは差し支えない.
1364 chg_ipm をサポートするかどうかを,SUPPORT_CHG_IPM を定義するかどうかで
1365 変更できる.タスクコンテキストで IPM を変更する場合には,chg_ipm を使
1366 わなければならない.chg_ipm をサポートしない場合には,タスクコンテキス
1367 トで IPM を変更することはできない.つまり,タスクコンテキストでは,IPM
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 の時にもタスクディスパッチは保留
1382 M68K(M68020以上)では,割込みハンドラの起動によって,使用するスタック
1383 が自動的に割込みスタックへ切り換わるため,割込みスタックへの切換え処理
1384 は必要ない.最も外側のハンドラであるかどうかは,スタック上に積まれた
1385 SR 中のマスタ/割込みモードビットを参照して判定している.タスクディス
1386 パッチとタスク例外処理ルーチンの起動処理は,ret_int ルーチンに任せてい
1389 reqflg をチェックする前に割込みを禁止するのは,割込みを禁止しないと,
1390 reqflg をチェックした後に起動された割込みハンドラ内でディスパッチが要
1391 求された場合に,ディスパッチが行われないためである.
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 へ */
1406 M68Kでは,CPU例外ハンドラの起動によって割込みモードへの移行はおこらず,
1407 使用するスタックは切り換わらない.そのため,CPU例外ハンドラ内で割込み
1408 モードに切り換えている.また,最も外側のハンドラであるかどうかを判定す
1409 るために,割込みモードに切り換える前の SR をスタック上に保存する.タス
1410 クディスパッチとタスク例外処理ルーチンの起動処理は,ret_exc ルーチンに
1413 CPU例外ハンドラへの引数は,例外スタックフレームの先頭番地(すなわち,
1414 CPU例外ハンドラの出入口処理が呼ばれた直後のスタックポインタ)としてい
1417 reqflg をチェックする前に割込みを禁止するのは,割込みを禁止しないと,
1418 reqflg をチェックした後に起動された割込みハンドラ内でディスパッチが要
1419 求された場合に,ディスパッチが行われないためである.
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 /* 引数を捨てる */
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 /* スクラッチレジスタを復帰 */
1441 以下のコードでは,chg_ipm はサポートしていない.また,採用しなかったコ
1442 ートであるため,動作テストをしていない.
1444 CTXB は「VP msp」のみを含む構造体とする.タスクのコンテキストは,次の
1445 図のようにタスクのスタック上に保存する.スクラッチレジスタ(D0〜D1,A0
1446 〜A1)とその他のレジスタを別々に積むのは,タスク例外処理ルーチンの起動
1449 * 小 +-----------------------------------+ ← TCB 中に保存されている MSP
1451 * +-----------------------------------+
1453 * +-----------------------------------+
1455 * +-----------------------------------+
1457 * +-----------------------------------+
1459 * +-----------------------------------+
1461 * +-----------------------------------+
1463 * +-----------------------------------+
1465 * +-----------------------------------+
1467 * +-----------------------------------+
1469 * +-----------------+-----------------+
1470 * | SR | PC (上16bit) |
1471 * +-----------------+-----------------+
1472 * ↓ | PC (下16bit) | 例外情報 |
1473 * 大 +-----------------+-----------------+ ← ディスパッチャ起動前の MSP
1475 dispatch は,trap_dispatch を TRAP命令で呼ぶ関数とする.
1478 or.w #0x1000, %sr /* マスタモード */
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)
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 ならリターン */
1496 jsr call_texrtn /* タスク例外処理ルーチンの呼出し */
1498 movem.l (%sp)+, %d0-%d1/%a0-%a1 /* スクラッチレジスタを復帰 */
1502 stop #0x2000 /* 割込み待ち(割込みモード) */
1504 * ここで割込みモードに切り換えるのは,ここで発生する割込み処理
1505 * にどのスタックを使うかという問題の解決と,割込みハンドラ内で
1506 * のタスクディスパッチの防止という2つの意味がある.
1508 or.w #0x1700, %sr /* マスタモード・割込み禁止 */
1509 tst.l reqflg /* reqflg が FALSE なら */
1510 jbeq dispatch_3 /* dispatch_3 へ */
1511 clr.l reqflg /* reqflg をクリア */
1516 * ここでは,割込みモード・割込み禁止状態.
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 へ */
1530 movem.l %d2-%d7/%a2-%a6, -(%a1) /* レジスタを保存 */
1531 move.l %a1, TCB_msp(%a0) /* タスクスタックを保存 */
1533 move.l schedtsk, %a0
1534 move.l %a0, runtsk /* schedtsk を runtsk に */
1535 jbne ret_int_2 /* schedtsk があるか? */
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 をクリア */
1544 move.l TCB_msp(%a0), %a1 /* タスクスタックを A1 に */
1545 movem.l (%a1)+, %d2-%d7/%a2-%a6 /* レジスタを復帰 */
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 へ */
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 を割込みスタックから復帰 */
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)
1569 movec.l %a1, %msp /* A1 をタスクスタックに */
1572 タスク例外処理ルーチン呼出し時のスタック
1574 * 小 +-----------------------------------+
1576 * +-----------------------------------+
1578 * +-----------------------------------+
1580 * +-----------------------------------+
1582 * +-----------------------------------+
1584 * +-----------------------------------+
1586 * +-----------------------------------+
1588 * +-----------------+-----------------+
1589 * | SR | PC (上16bit) |
1590 * +-----------------+-----------------+
1591 * ↓ | PC (下16bit) | 例外情報 |
1592 * 大 +-----------------+-----------------+
1595 addq.l #8, %sp /* 引数エリアを捨てる */
1596 or.w #0x0700, %sr /* 割込み禁止 */
1597 jsr call_texrtn /* タスク例外処理ルーチンの起動 */
1598 movem.l (%sp)+, %d0-%d1/%a0-%a1 /* スクラッチレジスタを復帰 */
1608 以下は,ターゲット依存部を実装する上でミスしがちな点をリストアップした
1613 ext_tsk を呼ばずにタスクのメイン関数からリターンした場合,ext_tsk を呼
1614 び出したのと同等の処理を行うようにしなければならない.タスク起動時に,
1615 メイン関数からのリターンアドレスを ext_tsk の番地に設定しておく方法を
1618 (2) タスクコンテキストでの割込みマスクの変更
1620 chg_iXX をサポートする場合,タスク切替えの際に,chg_iXX によって設定し
1621 た割込みマスクの値(タスクコンテキストにおける割込みマスクの値)を新し
1622 いタスクに引き継ぐことを推奨する.特に,割込みの出口でタスク切替えを行
1623 う箇所は注意が必要である.具体的には,以前に同じタスクが動いていた時の
1624 割込みマスクがスタックに積まれている場合に,これをそのまま書き戻しては
1627 (3) タスク例外処理の実行コンテキスト
1629 タスク例外処理ルーチンはタスクコンテキストで実行されるため,タスク例外
1630 処理ルーチン実行時にはスタックポインタがタスクスタックを指している必要
1631 がある(特に割込みの出口処理で注意すること) .
1635 CPU例外ハンドラ実行時は,割込みマスクの値がCPU例外発生直前と同じになる
1638 (5) 実行すべきタスクがない場合の処理
1640 実行すべきタスクがない(schedtsk が NULL)場合に,プロセッサを待ちモー
1641 ド(スリープモード)に移行させる処理と,割込みを許可する処理とは,不可
1642 分に行なう必要がある.これを不可分に行なわない場合,割込みを許可した直
1643 後に割込みが入り,その中でタスクが実行可能状態になると,実行すべきタス
1644 クがあるにもかかわらずプロセッサが待ちモードになってしまう.
1646 また,実行すべきタスクがなく,割込みを許可して割込みを待つ間は,runtsk
1647 を NULL に設定しなければならない.このように設定しないと,割込みハンド
1648 ラから iget_tid を呼び出した際の動作が仕様に合致しなくなる(μITRON4.0
1649 仕様では,実行状態のタスクがない場合に,iget_tid は TSK_NONE を返すこ
1650 とになっており,iget_tid のコードは,runtsk が NULL の時に TSK_NONE を
1653 m68k の実装は(config/m68k/cpu_support.S より),
1656 move.l schedtsk, %a0
1657 move.l %a0, runtsk /* schedtsk を runtsk に */
1658 jbeq dispatcher_1 /* runtsk があるか? */
1660 となっており,schedtsk が NULL の時に,runtsk を NULL にしてから,割込
1661 み待ちに入る.しかしながら,この処理が抜けていると,schedtsk が NULL
1662 の時には,runtsk をすぐに更新しない.そのため,実行状態のタスクがない
1663 場合に iget_tid を呼ぶと,前に実行されていたタスクのID が返る.