i8086/MS-DOS リアルタイム・マルチタスクOS 1. 1 …i8086/MS-DOS...
Transcript of i8086/MS-DOS リアルタイム・マルチタスクOS 1. 1 …i8086/MS-DOS...
i8086/MS-DOS リアルタイム・マルチタスクOS
i
1. 概 要 ......................................................................................................................................................................................................12. リアルタイムOS(カーネル) KrtKNLIF.H , KrtKNL.ASM .........................................................................................2
2.1. タスク個数等の資源数 .....................................................................................................................................................................32.2. セグメント名称 ................................................................................................................................................................................32.3. タスクのスケジューリング .............................................................................................................................................................32.4. メールデータ ...................................................................................................................................................................................32.5. 割り込み処理からのシステムコール ..............................................................................................................................................42.6. 多重割り込み制御 ............................................................................................................................................................................52.7. エラーコード ...................................................................................................................................................................................62.8. 関数仕様 ...........................................................................................................................................................................................7
2.8.1. OSの起動 - os_start .........................................................................................................................72.8.2. タスクの生成 - cre_tsk...........................................................................................................................82.8.3. タスクの起動 - sta_tsk / ista_tsk ..........................................................................................................82.8.4. 自タスクの終了 - ext_tsk ..........................................................................................................................82.8.5. タスクの起床 - wup_tsk / iwup_tsk ......................................................................................................92.8.6. 自タスクをウェイト - slp_tsk...........................................................................................................................92.8.7. 自タスクを一定時間ウェイト - wai_tsk..........................................................................................................................92.8.8. 自タスクへの起床要求解除 - can_wup ......................................................................................................................102.8.9. 自タスクIDの取得 - get_tskid .....................................................................................................................102.8.10. TCBアドレスの取得 - get_tcbaddr.................................................................................................................102.8.11. セマフォ初期化 - cre_sem .......................................................................................................................112.8.12. セマフォ設定(資源の獲得) - wai_sem ......................................................................................................................112.8.13. セマフォ解除(資源の返却) - sig_sem / isig_sem .....................................................................................................112.8.14. セマフォ設定(資源の獲得,タスク毎ネスト制御) - wai_sem2 ...............................................................................122.8.15. セマフォ解除(資源の返却,タスク毎ネスト制御) - sig_sem 2 ...............................................................................122.8.16. メール送信 - snd_msg / isnd_msg ...................................................................................................132.8.17. メール受信 - rcv_msg.......................................................................................................................132.8.18. メール到着チェック - pol_msg .......................................................................................................................132.8.19. 先頭メールアドレス取得 - get_mbqptr .................................................................................................................142.8.20. メールキュー情報退避 - unl_msg ......................................................................................................................142.8.21. メールキュー情報回復 - lnk_msg / ilnk_msg .................................................................................................142.8.22. システムタイマ処理 - systic ...........................................................................................................................152.8.23. 割り込み終了処理 - _ret_int .......................................................................................................................152.8.24. 最大資源数取得 - get_XXXnum ..................................................................................................................15
3. キュー管理モジュール KrtQUE.h , KrtQue.c ................................................................................................163.1. エラーコード .................................................................................................................................................................................163.2. エラーハンドラの登録 ...................................................................................................................................................................163.3. 関数仕様 .........................................................................................................................................................................................17
3.3.1. 起動時初期設定 - que_inz........................................................................................................................173.3.2. エンキュー - que_enq.......................................................................................................................173.3.3. 割込処理からのエンキュー - ique_enq......................................................................................................................173.3.4. デキュー - que_deq.......................................................................................................................173.3.5. キューデータ到着チェック - que_pol........................................................................................................................183.3.6. 空きキューブロック数取得 - que_freesize ................................................................................................................18
i8086/MS-DOS リアルタイム・マルチタスクOS
ii
4. リアルタイムOSのPCハンドリング KrtPCIIF.H , KrtPCI.ASM .......................................................................................194.1. 適用機種 .........................................................................................................................................................................................194.2. タイマ割り込みのハンドリング ....................................................................................................................................................194.3. キー割り込みのハンドリング .......................................................................................................................................................204.4. RS-232C割り込みのハンドリング .....................................................................................................................................214.5. マウス割り込みのハンドリング ....................................................................................................................................................224.6. ハードウェア割り込みの一時停止 ................................................................................................................................................234.7. 多重割り込み制御 ..........................................................................................................................................................................234.8. DOSファンクションコールのハンドリング .............................................................................................................................234.9. Ctrl-Break割り込みのハンドリング ..........................................................................................................................234.10. 致命的なエラー割り込みのハンドリング .....................................................................................................................................244.11. プログラムの終了 ..........................................................................................................................................................................244.12. タスク生成時の注意 ......................................................................................................................................................................244.13. 関数仕様 .........................................................................................................................................................................................25
4.13.1. PC割り込みベクタ退避 - pci_save_vec.............................................................................................254.13.2. マウス初期設定 - pci_initmus ..............................................................................................254.13.3. パソコン種別の初期化 - pci_ini_pckind..........................................................................................254.13.4. PCハンドリング初期設定 - pci_inz ......................................................................................................264.13.5. RS-232C割り込み処理関数の登録 - pci_set232c ...............................................................................................264.13.6. マウス割り込み処理関数の登録 - pci_setmus ...............................................................................................264.13.7. パソコン種別の取得 - pci_get_pckind .........................................................................................274.13.8. 遅延起床タスクの設定 - pci_delayed_wup .....................................................................................274.13.9. プログラムの終了時処理 - pci_end .....................................................................................................27
5. RS-232CのPCハンドリング KrtPCIIF.h, KrtPCIS.c ...............................................................................................285.1. RS―232Cステータス ...........................................................................................................................................................285.2. 関数仕様 .........................................................................................................................................................................................29
5.2.1. 232Cハードウェア初期設定 - pcs_hw_inz..............................................................................................................295.2.2. OSインタフェース初期設定 - pcs_if_inz ................................................................................................................305.2.3. データブロック送信 - pcs_snd .......................................................................................................................315.2.4. 物理アクセス関数 ...................................................................................................................................................................31
6. サンプルプログラム ..............................................................................................................................................................................326.1. サンプルプログラム1 ...................................................................................................................................................................326.2. サンプルプログラム2...................................................................................................................................................................35
7. アセンブラマクロ SpMacMSC.inc ..........................................................................................................387.1. 単純マクロ .....................................................................................................................................................................................387.2. 構造化プログラミングマクロ .......................................................................................................................................................38
7.2.1. 初期設定 - $_init ............................................................................................387.2.2. 二分岐ブロック - $_if ~ $_else ~ $_endif.........................................................397.2.3. 繰り返し(前条件)ブロック - $_while ~ $_enddo ......................................................................397.2.4. 繰り返し(後条件)ブロック - $_do ~ $_until ...........................................................................397.2.5. 選択ブロック - $_switch ~ $_case ~ $_endswitch ..........................................407.2.6. ブロックからの抜け出し - $_break ..........................................................................................407.2.7. 条件指定..................................................................................................................................................................................417.2.8. ブロック間のオブジェクトが128バイト以上となる場合 ................................................................................................417.2.9. 記述例 .....................................................................................................................................................................................42
i8086/MS-DOS リアルタイム・マルチタスクOS
1
1. 概 要
このコンポーネント(以下、KRT という)は、インテル8086(および互換CPU)で動作可能なリアルタイムOSと、リアルタ
イムOSをMS-DOS上で利用するためのハンドリングモジュールで構成します。
フォルダ構成
KRTのフォルダ構成は、以下のとおりです。
KRT ---+--- DOC - 本DOCファイル
|
+--- MOUSE - MOUSE.COM(マウスを使用する場合は、本フォルダ下の MOUSE.COM をあらかじめ実行しておきます)
|
+--- SRC - ソースプログラム
ソースファイル
KRTは、以下のソースファイルで構成します。
ファイル名 内容
KrtKNL.asm , KrtKnlIf.h リアルタイムOSのカーネル
KrtPci.asm , KrtPciS.c , KrtPciIf.h PCハンドリングモジュール
KrtQue.c , KrtQue.h キュー管理モジュール
KrtAtIO.h, Krt98IO.h 入出力ポート定義ヘッダ
SpMacMsc.inc MASM用マクロ定義
KglDef.h, KglFmm.h, KglFmm.c, LMemMsc.asm kgl\_gbl\doc\kgl1.doc 参照
適用言語
KRTは、以下の言語処理ツールを対象とします。
言 語 ツール
アセンブラ Microsoft MASM V5.1
C Microsoft C V6.00(ラージモデル)
メモリモデル
LARGEメモリモデルで実行可能です。
i8086/MS-DOS リアルタイム・マルチタスクOS
2
2. リアルタイムOS(カーネル) KrtKNLIF.H , KrtKNL.ASM
このリアルタイムOSは、インテル8086(および、80x86等の互換CPU)を使用した装置の組み込みソフトウェア、ある
いは、MS-DOSパソコン上で実行可能な、イベントドリブン型のマルチタスクOSです。
本リアルタイムOSのカーネルでは、ポートの入出力は一切行いません。従って、インテル80x86シリーズのCPU下であれば、
組み込み装置のソフトウェアにも適用可能です。
リアルタイムOSの関数一覧を以下に示します。
分類 関数名 機能 備考
タスク制御 cre_tsk タスク生成 タスクスケジュールなし
sta_tsk タスク起動
タスクスケジューリングext_tsk 自タスク終了
slp_tsk 自タスクウェイト
wai_tsk 自タスク一定時間ウェイト
wup_tsk タスク起床
rot_rdq 自タスク優先度ローテート
タスクスケジュールなしcan_wup 自タスクへの起床要求解除
get_tskid 自タスクのタスクID取得
get_tcbaddr 指定タスクIDのTCBアドレス取得
ista_tsk 割り込みからの、タスク起動 タスクスケジュールは、ret_int 実行時まで延期
iwup_tsk 割り込みからの、タスク起床
セマフォ制御 cre_sem セマフォクリエート タスクスケジュールなし
wai_sem セマフォ設定(資源の獲得) タスクスケジューリング
sig_sem セマフォ解除(資源の返却)
isig_sem 割り込みからの、セマフォ解除 タスクスケジュールは、ret_int 実行時まで延期
wai_sem2 セマフォ設定(資源の獲得,タスク毎ネスト制御) タスクスケジューリング
sig_sem2 セマフォ解除(資源の返却,タスク毎ネスト制御)
メールボックス制御 snd_msg メール送信 タスクスケジューリング
rcv_msg メール受信
pol_msg メール到着チェック タスクスケジュールなし
get_mbqptr 先頭メールデータのアドレスを得る
unl_msg メールキューポインタ退避しメールを空にする
lnk_msg 現メールキューの後部に、指定キューを接続 タスクスケジューリング
isnd_msg 割り込みからの、メール送信 タスクスケジュールは、ret_int 実行時まで延期
ilnk_msg 割り込みからの lnk_mbx
その他 ret_int 割り込み終了処理 割り込みからのシステムコールを実行した場合は、必ず実行要
systic システムタイマ処理 タスクスケジュールは、ret_int 実行時まで延期
i8086/MS-DOS リアルタイム・マルチタスクOS
3
2.1. タスク個数等の資源数
タスク個数等の最大資源数は、以下のとおりです。
資源名 シンボル名 値(個数) 備 考
タスク個数 TCB_NUM 16 タスクID=15は、アイドルタスク専用として使用される為、アプリケーションで
使用できるタスクIDは、0~14の15個
また、タスクID=14はイニシャルタスク用として使用される為、イニシャルタス
クの生存中は、タスクID=14を使用できません。
メールボックス個数 QUE_NUM 16 メールボックスID=0~15
セマフォ個数 SEM_NUM 32 セマフォID=0~31
タスクプライオリティ個数 LVL_NUM 8 最低タスク優先度(=7)は、アイドルタスク専用として使用される為、アプリケー
ションで使用できるタスクプライオリティは、0~6の7個。
また、OS起動時、イニシャルタスクのタスクプライオリティとして0(最高優先度)
が与えられます。
上記の値を変更する場合は、KrtKNL.ASM のシンボル定義を変更し、再アセンブルして下さい。
変更する値に特に制限はありませんが、セグメント(RTM_BSS)サイズが64KB以内でなければなりません。
各々、約100個程度までは定義可能ですが、数が多くなるほどOSの性能は低下します。
尚、上記値を変更した場合、アイドルタスクのタスクID、および、タスク優先度は、定義した値-1となり、イニシャルタスクの
タスクIDは、定義した値-2となります。
2.2. セグメント名称
本マルチタスクOSモジュールのセグメント名称は以下のとおりです。
セグメント名 クラス名 種別
RTM_BSS FAR_BSS RAM
KRTKNL_TEXT CODE ROM
本モジュールを、組み込みソフトウェア等で使用する場合は、上記セグメントを各々RAM、および、ROM領域に配置して下さい。
2.3. タスクのスケジューリング
以下の関数を実行した場合、関数本来の処理(OS管理情報の更新)後に、タスクのスケジューリングが行われます。
・sta_tsk – タスク起動 ・wai_sem - セマフォ設定 ・_ret_int – 割り込み終了処理
・ext_tsk - タスク終了 ・sig_sem - セマフォ解除 ・wai_sem2 – セマフォ設定
・slp_tsk – 自タスクウェイト ・snd_msg - メール送信 ・sig_sem2 – セマフォ解除
・wai_tsk – 自タスク一定時間ウェイト ・rcv_msg - メール受信
・wup_tsk - タスク起床 ・lnk_mbx - メ-ルキュー接続
タスクのスケジューリングとは、現在、READY状態、および、RUN状態の全タスクで、最も優先度の高いタスクをRUN状態
へ移行し、現在実行中のタスクをREADY状態へ移行することをいいます。
尚、現在実行中のタスクが、READY/RUN状態のタスク中で最高優先度である場合は、タスク状態の移行は発生しません。
2.4. メールデータ
snd_msg, isnd_msg, rcv_msg では、メールの送受信を行いますが、メールデータ領域の確保/解放は行いません。
メールデータ領域はアプリケーションで用意(確保)する必要があります。
また、メールデータの先頭4バイトはシステムで使用されます。
従って、アプリケーションでは、メールデータの5バイト目以降を使用しなければなりません。
i8086/MS-DOS リアルタイム・マルチタスクOS
4
2.5. 割り込み処理からのシステムコール
割り込み処理内から使用できるシステムコールは以下のものに限定されます。
・ista_tsk – タスクの起動
・iwup_tsk – タスクの起床
・isnd_msg – メール送信
・ilnk_mbx – メールキュー接続
・isig_sem – セマフォ解除
・systic – システムタイマ処理
・_ret_int – 割り込み終了(レジスタを割り込み時の状態に戻す必要があるため、アセンブラレベルでコールする)
割り込み処理から上記関数を実行した場合は、割り込み処理終了時に必ずラベル( _ret_int )へジャンプしなければなりません。
(上記関数を実行した場合は、OSの管理情報の更新のみ行い、タスクのスケジューリングは保留したままとなります。_ret_int は、
タスクのスケジューリングを行いOSの管理情報を完結させます)
_ret_int へジャンプする場合は、CS:IPおよびフラグレジスタを除くすべてのレジスタを割り込み発生時の値に戻した状態でジ
ャンプしなければなりません。(尚、ista_tsk 等のシステムコールでは、AX~DXレジスタを破壊します)
システムコールを使用する、割り込み処理のコードは通常、以下のようになります。
割り込み入り口点処理(多重割り込みを行わない場合)
.MODEL LARGE
……
EXTRN _ret_int:FAR
EXTRN _CFunc:FAR
……
.CODE
Interrupt PROC FAR
PUSH reg ;割り込み処理で使用するレジスタの待避(通常は、AX~DX,SI,DI,DS,ES 待避)
……
MOV AX,DGROUP
MOV DS,AX
CALL _CFunc ;C関数(割り込み処理本体)の呼び出し
OUT XXXX,XX ;割り込みコントローラへ割り込み終了を通知
POP reg ;割り込み処理で使用したレジスタの回復
……
JMP FAR PTR _ret_int
Interrupt ENDP
割り込み処理本体(C言語)
#include <KrtKNLIF.H>
……
void CFunc( void )
{
割り込み処理 ; iwup_tsk 等のシステムコール発行
}
i8086/MS-DOS リアルタイム・マルチタスクOS
5
2.6. 多重割り込み制御
多重割り込み制御(割り込み処理実行中に他の割り込みを許可)を行う場合は、以下の点に注意しなければなりません。
割り込みがネストする場合、ネスト最上位の割り込みからの戻り時のみ「JMP _retint」により割り込みを終了します。
ネスト中の割り込み処理終了時は、「IRET」により割り込みを終了しなければなりません。
多重割り込みを行う場合の、割り込み処理のコードは通常、以下のようになります。
割り込み入り口点処理(多重割り込みを行う場合)
.MODEL LARGE
……
EXTRN _ret_int:FAR
EXTRN _CFunc:FAR
……
.DATA
INT_NEST DW 0 ; 割り込みネストカウンタ
……
.CODE
Interrupt PROC FAR
PUSH reg ;割り込み処理で使用するレジスタの待避(通常は、AX~DX,SI,DI,DS,ES 退避)
…… ;
MOV AX,DGROUP
MOV DS,AX
INC INT_NEST ;割り込みネストカウンタ加算
STI ;多重割り込み許可
CALL _CFunc ;C関数(割り込み処理本体)の呼び出し
CLI ;多重割り込み禁止
OUT XXXX,XX ;割り込みコントローラへ割り込み終了を通知
DEC INT_NEST ;割り込みネストカウンタ減算
JZ L_RET_INT ;ネスト最上位ならばJUMP
L_IRET: ;割り込み終了処理(割り込みネスト中の場合)
POP reg ; 割り込み処理で使用したレジスタの回復
…… ; ・
IRET ; 割り込み発生点へ戻る
L_RET_INT: ;割り込み終了処理(ネスト最上位の場合)
POP reg ; 割り込み処理で使用したレジスタの回復
…… ; ・
JMP FAR PTR _ret_int ; タスクスケジュール
Interrupt ENDP
尚、割り込み処理で使用するスタック領域は、割り込みが発生した時点のタスクのスタック領域となります。つまり、全てのタスクの
スタックで、割り込み処理用の容量を余分に持たなければなりません。
割込発生
割込発生
割込発生
JMP _ret_intIRET IRET
割り込み処理
(ネスト最上位)
割り込み処理
(ネスト中)
割り込み処理
(ネスト中)
i8086/MS-DOS リアルタイム・マルチタスクOS
6
2.7. エラーコード
名称 値 内容
TE_OK 0 正常
TE_TSKID 1 不正タスクID
TE_MBXID 2 不正メールボックスID
TE_SEMID 3 不正セマフォID
TE_NULL 4 ヌルポインタ指定
TE_NODMT 5 指定タスクは休止状態でない
TE_NOWUP 6 タスク起床不可
TE_TPRI 7 不正タスクプライオリティ
TE_EXS 8 指定タスクIDのタスクは、既に生成されている
TE_NOSEM 9 セマフォが1つも設定されていない状態で sig_sem/isig_sem による資源の解放を行おうとした
TE_NOMAIL 10 到着メールなし
TE_SEMNST_OF 11 セマフォネスト オーバーフロー
TE_SEMNST_UF 12 セマフォネスト アンダフロー
i8086/MS-DOS リアルタイム・マルチタスクOS
7
2.8. 関数仕様
2.8.1. OSの起動 - os_start
形 式 UW os_start ( VO (*ini_tsk)(void), VOP pInistk, VOP pIdlstk, UW dataseg);
ini_tsk : イニシャルタスク(関数)のアドレス
pInistk : イニシャルタスクのスタック領域のアドレス(スタック領域の最高位アドレス)
pIdlstk : アイドルタスクのスタック領域のアドレス(スタック領域の最高位アドレス)
dataseg : イニシャルタスクおよびアイドルタスク起動時に設定する、DSレジスタの値
説 明 OSの作業領域を初期化し、イニシャルタスクの生成および起動を行います。
イニシャルタスクには、最高優先度のタスクプライオリティ(=0)が与えられます。従って、イニシャルタスク中で
生成/起動したタスクは、イニシャルタスクが自タスクを終了するか、あるいは、待ち状態となるまで実行されません。
また、全セマフォの初期化を行い、資源数=1とします。
従って、セマフォを資源数=1として使用する場合は、関数( cre_sem )によるセマフォの初期化は不要です。
この関数は、正常にOSの起動を行った場合、コール元へは戻らずにアイドルタスクとして生存し続けます。
アイドルタスクには、最低優先度のタスクプライオリティが与えられ、全タスクが待ち状態時のみ実行されます。
アイドルタスクは、1つの命令「 JMP $ 」のみで構成します。
戻り値 TE_OK - 正常
TE_NULL - イニシャルタスクアドレス、あるいは、スタック領域アドレスにヌルポインタを指定した。
i8086/MS-DOS リアルタイム・マルチタスクOS
8
2.8.2. タスクの生成 - cre_tsk
形 式 UW cre_tsk ( UW tskid, UW tskpri, VO (*task)(VO), VOP pStack, UW dataseg );
tskid : 生成するタスクのタスクID(0~14)
tskpri : 生成するタスクのタスクプライオリティ(0~14, 0=最高優先度)
task : 生成するタスク(関数)のアドレス
pStack : タスクのスタック領域のアドレス(スタック領域の最高位アドレス)
dataseg : タスク起動時に設定する、DSレジスタの値
説 明 指定されたタスクを生成し、DORMANT(休止)状態とします。
イニシャルタスク中で本関数をコールする場合、タスクID=14は指定できません。
タスクID=14は、イニシャルタスクが( ext_tsk を実行することにより)自タスクを終了後に使用可能となります。
同一タスクプライオリティのタスクを生成した場合、関数( rot_rdq )によりタスク優先度のローテートを行わない限り、
タスクの優先順位はタスク生成順となります。
戻り値 TE_OK - 正常
TE_TSKID – タスクIDが指定可能範囲外
TE_TSKPRI– タスクプライオリティが指定可能範囲外
TE_EXS – 指定されたタスクIDのタスクは、既に生成されている
TE_NULL - タスクアドレス、あるいは、スタック領域アドレスにヌルポインタを指定した。
2.8.3. タスクの起動 - sta_tsk / ista_tsk
形 式 UW sta_tsk ( UW tskid ); - タスクからコールする場合
UW ista_tsk ( UW tskid ); - 割り込み処理からコールする場合
tskid : 起動するタスクのタスクID(0~14)
説 明 指定されたタスクを起動(休止状態から実行可能状態へ移行)します。
sta_tsk 関数を実行した場合は、タスクのスケジューリングが行われます。
ista_tsk 関数を実行した場合は、割り込み処理終了時にラベル(_ret_int)へジャンプしなければなりません。
戻り値 TE_OK - 正常
TE_TSKID – タスクIDが指定可能範囲外
TE_NODMT – 指定されたタスクIDは、休止(DORMANT)状態でない。
2.8.4. 自タスクの終了 - ext_tsk
形 式 VO ext_tsk ( VO );
説 明 自タスクを終了(未登録状態へ移行)します。
本関数を実行した場合、タスクのスケジューリングが行われ、自タスクは消滅します。
戻り値 なし
i8086/MS-DOS リアルタイム・マルチタスクOS
9
2.8.5. タスクの起床 - wup_tsk / iwup_tsk
形 式 UW wup_tsk ( UW tskid ); - タスクからコールする場合
UW iwup_tsk ( UW tskid ); - 割り込み処理からコールする場合
tskid : 起床するタスクのタスクID(0~14)
説 明 指定されたタスクIDのタスクを起床(ウェイト状態から実行可能状態へ移行)します。
但し、起床できるタスクは、関数( slp_tsk / wai_tsk )によりウェイト中のタスクのみです。
セマフォ待ち中やメール受信待ち中のタスクは起床できません。
尚、タスクIDで指定されたタスクが、既に起床している場合は、起床要求を保留し、当該カウンタを更新します。
起床要求は、最大65535回まで保留可能です。
wup_tsk 関数を実行した場合は、タスクのスケジューリングが行われます。
iwup_tsk 関数を実行した場合は、割り込み処理終了時にラベル(_ret_int)へジャンプしなければなりません。
戻り値 TE_OK - 正常
TE_TSKID – タスクIDが指定可能範囲外
TE_NOWUP – 指定されたタスクは起床できない(セマフォ待ち中、メール受信待ち中、休止中、あるいは、未登録状態)。
2.8.6. 自タスクをウェイト - slp_tsk
形 式 VO slp_tsk ( VO );
説 明 自タスクをRUN状態から待ち状態へ移行します。
但し、自タスクへの起床要求が保留されている場合は、ウェイトせずに、起床要求カウンタを減じます。
本関数を実行した場合、タスクのスケジューリングが行われます。
自タスクのウェイトは、関数( wup_tsk / iwup_tsk )により解除されます。
戻り値 なし
2.8.7. 自タスクを一定時間ウェイト - wai_tsk
形 式 VO wai_tsk ( UW cnt );
cnt : タイマカウンタ
説 明 自タスクをウェイト(RUN状態から待ち状態へ移行)し、タイマカウンタを設定します。
但し、自タスクへの起床要求が保留されている場合は、ウェイトせずに、起床要求カウンタを減じます。
本関数を実行した場合、タスクのスケジューリングが行われます。
自タスクのウェイトは、関数( wup_tsk / iwup_tsk )を実行するか、あるいは、システムタイマ処理(systic)がタイマ
カウントで指定した回数実行されることにより解除されます。
戻り値 なし
i8086/MS-DOS リアルタイム・マルチタスクOS
10
2.8.8. 自タスクへの起床要求解除 - can_wup
形 式 VO can_wup ( VO );
説 明 自タスクへの起床要求を解除します。
つまり、自タスクがRUN/READY状態中に実行された wup_tsk / iwup_tsk による自タスクへの起床要求をすべて無
効にします。
戻り値 なし
2.8.9. 自タスクIDの取得 - get_tskid
形 式 UW get_tskid ( VO );
説 明 自タスクのタスクIDを得ます。
戻り値 自タスクのタスクID(0~14)
2.8.10. TCBアドレスの取得 - get_tcbaddr
形 式 VOP get_tcbaddr ( UW tskid );
tskid : TCBアドレスを得るタスクのタスクID(0~15)
説 明 指定したタスクのTCBアドレスを得ます。
TCBの形式は以下のとおりです。
struct RTM_TCB
# 名称 属性 Bit 内容
1 sts unsigned char - タスク状態 0:未登録 (NON EXXISTENCE)
1:休止状態 (DORMANT )
2:待ち状態 (WAIT )
3:実行可能状態(READY )
4:実行中 (RUN )
2 flg unsigned char 7 1:メール受信待ち
6 1:セマフォ解除待ち
5 1:タイマ待ち
4-0 未使用
3 pri unsigned int - タスクプライオリティ
4 lvl_fp struct RTM_TCB based(rtm_seg) * - 同一タスクプライオリティTCBチェイン(前方ポインタ)
5 lvl_bp 〃 - 〃 (後方ポインタ)
6 que_fp 〃 - メール受信待ちTCBチェイン (前方ポインタ)
7 que_bp 〃 - 〃 (後方ポインタ)
8 sem_fp 〃 - セマフォ解除待ちTCBチェイン (前方ポインタ)
9 sem_bp 〃 - 〃 (後方ポインタ)
10 wtm_fp 〃 - タイマ待ちTCBチェイン (前方ポインタ)
11 wtm_bp 〃 - 〃 (後方ポインタ)
12 stk unsigned int _far * - スタックポインタ
13 cnt unsigned int - タイマカウンタ
14 wuc unsigned int - 起床要求カウンタ
15 - char[4] - 未使用
戻り値 指定タスクのTCBアドレス
i8086/MS-DOS リアルタイム・マルチタスクOS
11
2.8.11. セマフォ初期化 - cre_sem
形 式 UW cre_sem ( UW semid, UW cnt );
semid : セマフォID(0~15)
cnt : 資源数
説 明 指定されたセマフォIDの資源数を、cntで指定された値に設定します。
尚、OS起動時、全てのセマフォは資源数=1に初期化されます。
従って、セマフォを資源数=1として使用する場合は、本関数によるセマフォの初期化は不要です。
戻り値 TE_OK – 正常
TE_SEMID – セマフォIDが指定可能範囲外
2.8.12. セマフォ設定(資源の獲得) - wai_sem
形 式 UW wai_sem ( UW semid );
semid : セマフォID(0~15)
説 明 指定されたセマフォIDの資源を1つ獲得します。
資源を獲得できない(他のタスクが資源を獲得している)場合は、自タスクをウェイトします。
他のタスクが資源を返却したら、当該セマフォ待ちのタスクウェイトを順次解除します。
本関数は、sig_sem/isig_sem と対で実行しなければなりません。
戻り値 TE_OK – 正常
TE_SEMID – セマフォIDが指定可能範囲外
2.8.13. セマフォ解除(資源の返却) - sig_sem / isig_sem
形 式 UW sig_sem ( UW semid ); - タスクからコールする場合
UW isig_sem ( UW semid ); - 割り込み処理からコールする場合
semid : セマフォID(0~15)
説 明 指定されたセマフォIDの資源を1つ返却します。
また、当該セマフォ待ち行列の先頭にあるタスクのウェイトを解除します。
本関数は、wai_sem と対で実行しなければなりません。
isig_sem 関数を実行した場合は、割り込み処理終了時にラベル(_ret_int)へジャンプしなければなりません。
戻り値 TE_OK – 正常
TE_SEMID – セマフォIDが指定可能範囲外
TE_NOSEM – 指定されたセマフォIDでは、資源の獲得は行われていない
i8086/MS-DOS リアルタイム・マルチタスクOS
12
2.8.14. セマフォ設定(資源の獲得,タスク毎ネスト制御) - wai_sem2
形 式 UW wai_sem2 ( UW semid );
semid : セマフォID(0~15)
説 明 指定されたセマフォIDの資源を1つ獲得します。
本関数は、sig_sem2 と対で実行しなければなりません。
本関数を、同一タスクで多重に実行した場合は、最初の実行時のみ資源獲得動作を行います。(以下参照)
wai_sem2(id); --- 資源獲得動作を行う
wai_sem2(id); --- 何もしない
・・・
sig_sem2(id); --- 何もしない
sig_sem2(id); --- 資源返却動作を行う
資源を獲得できない(他のタスクが資源を獲得している)場合は、自タスクをウェイトします。
他のタスクが資源を返却したら、当該セマフォ待ちのタスクウェイトを順次解除します。
戻り値 TE_OK – 正常
TE_SEMID – セマフォIDが指定可能範囲外
TE_SEMNST_OF – セマフォネストのオーバーフロー(ネスト数が255を超えた)
2.8.15. セマフォ解除(資源の返却,タスク毎ネスト制御) - sig_sem 2
形 式 UW sig_sem2 ( UW semid );
semid : セマフォID(0~15)
説 明 指定されたセマフォIDの資源を1つ返却します。
また、当該セマフォ待ち行列の先頭にあるタスクのウェイトを解除します。
本関数は、wai_sem2 と対で実行しなければなりません。
本関数を、同一タスクで多重に実行した場合は、最後の実行時のみ資源返却動作を行います。( wai_sem2 参照)
戻り値 TE_OK – 正常
TE_SEMID – セマフォIDが指定可能範囲外
TE_NOSEM – 指定されたセマフォIDでは、資源の獲得は行われていない
TE_SEMNST_UF – セマフォネストのアンダーフロー
i8086/MS-DOS リアルタイム・マルチタスクOS
13
2.8.16. メール送信 - snd_msg / isnd_msg
形 式 UW snd_msg ( UW mbxid, VOP msg ); - タスクからコールする場合
UW isnd_msg ( UW mbxid, VOP msg ); - 割り込み処理からコールする場合
mbxid : メールボックスID(0~15)
msg : メールデータのアドレス
説 明 指定されたメールボックスIDへメールデータを送信します。
また、当該メール受信待ち行列の先頭にあるタスクのウェイトを解除します。
snd_msg 関数を実行した場合は、タスクのスケジューリングが行われます。
isnd_msg 関数を実行した場合は、割り込み処理終了時にラベル(_ret_int)へジャンプしなければなりません。
戻り値 TE_OK – 正常
TE_MBXID - メールボックスIDが指定可能範囲外
TE_NULL - メールデータのアドレスにヌルポインタが指定された
注 意 メールデータの先頭4バイトは、システムにて使用されます。
アプリケーションでは、メールデータの5バイト目以降を使用するようにして下さい。
2.8.17. メール受信 - rcv_msg
形 式 UW rcv_msg ( UW mbxid, VOP *msg );
mbxid : メールボックスID(0~15)
msg : 受信したメールデータへのポインタを格納する領域のアドレス
説 明 指定されたメールボックスからメールデータを1つ取り出します。
取り出したメールデータへのポインタが、msgに設定されます。
メールデータが1つも無い場合は、自タスクをウェイトします。
他のタスクがメールを送信したら、当該メール受信待ちのタスクウェイトを順次解除します。
本関数を実行した場合は、タスクのスケジューリングが行われます。
戻り値 TE_OK – 正常
TE_MBXID - メールボックスIDが指定可能範囲外
TE_NULL - メールデータのアドレス格納領域のアドレスにヌルポインタが指定された
2.8.18. メール到着チェック - pol_msg
形 式 UW pol_msg ( UW mbxid, VOP *msg );
mbxid : メールボックスID(0~15)
msg : 受信したメールデータへのポインタを格納する領域のアドレス
説 明 指定されたメールボックスにメールが到着しているかチェックします。
メールが到着している場合、先頭メールデータへのポインタが、msgに設定されます。
戻り値 TE_OK – 正常(到着メールあり)
TE_MBXID - メールボックスIDが指定可能範囲外
TE_NULL - メールデータのアドレス格納領域のアドレスにヌルポインタが指定された
TE_NOMAIL- 到着メールなし
i8086/MS-DOS リアルタイム・マルチタスクOS
14
2.8.19. 先頭メールアドレス取得 - get_mbqptr
形 式 VOP get_mbqptr ( UW mbxid );
mbxid : メールボックスID(0~15)
説 明 指定されたメールボックスにメールが到着しているかチェックします。
メールが到着している場合、先頭メールデータへのポインタを返します。
尚、メールデータの先頭4バイトは、次のメールデータへのチェインポインタです。
戻り値 ≠0:先頭メールデータへのポインタ
=0:到着メールなし
2.8.20. メールキュー情報退避 - unl_msg
形 式 UW unl_msg ( UW mbxid, VOP *ppSp, VOP *ppEp );
mbxid : メールボックスID(0~15)
ppSp : 先頭キューエントリへのポインタ退避領域のアドレス
ppEp : 最終キューエントリへのポインタ退避領域のアドレス
説 明 現在のメールキューを退避し、メールが空の状態にします。
退避した、メールキューは、関数( lnk_mbx / ilnk_mbx )により回復可能です。
例えば、メールキューの先頭にメッセージをキューイングする場合は、以下のようにします。
VOP sp, ep;
unl_msg(id, &sp, &ep); /* メールキュー退避 */
snd_msg(id, pMsg); /* メールをキューイング */
lnk_msg(id, sp, ep); /* 退避してあるメールキューを末尾へ接続 */
戻り値 TE_OK – 正常
TE_MBXID - メールボックスIDが指定可能範囲外
TE_NULL - メールキューポインタ退避領域のアドレスにヌルポインタが指定された
2.8.21. メールキュー情報回復 - lnk_msg / ilnk_msg
形 式 VO lnk_msg ( UW mbxid, VOP sp, VOP ep );
VO ilnk_msg ( UW mbxid, VOP sp, VOP ep );
mbxid : メールボックスID(0~15)
sp : 先頭キューエントリへのポインタ
ep : 最終キューエントリへのポインタ
説 明 現在のメールキューの後部に、指定メールキューを接続します。
戻り値 TE_OK – 正常
TE_MBXID - メールボックスIDが指定可能範囲外
i8086/MS-DOS リアルタイム・マルチタスクOS
15
2.8.22. システムタイマ処理 - systic
形 式 VO sys_tic ( VO );
説 明 wai_tsk 関数により、タイマ待ち状態となっているタスクのタイマカウントを1つ減じます。
タイマカウントが満了した(0になった)場合は、当該タスクのタイマ待ちウェイト状態を解除します。
本関数は通常、タイマ割り込み処理から一定周期でコールします。
本関数を実行した場合は、JMP _ret_int により割り込みを終了しなければなりません。
戻り値 なし
2.8.23. 割り込み終了処理 - _ret_int
形 式 EXTRN _ret_int:FAR
説 明 割り込みからのシステムコールを行った場合、割り込み処理終了時、このラベルへジャンプします。
このラベルでは、タスクのスケジューリング、および、割り込みの戻り処理(IRET)を行います。
戻り値 なし
2.8.24. 最大資源数取得 - get_XXXnum
形 式 UW get_tcbnum ( VO ); --- 最大 TCB 数(タスク数)取得
UW get_mbxnum ( VO ); --- 最大メールボックス数取得
UW get_semnum ( VO ); --- 最大セマフォ数取得
UW get_lvlnum ( VO ); --- 最大タスク優先度数取得
説 明 各資源の最大個数を返します。
戻り値 各資源の最大個数
i8086/MS-DOS リアルタイム・マルチタスクOS
16
3. キュー管理モジュール KrtQUE.h , KrtQue.c
キュー管理モジュールは、タスクへのメール通知に関する汎用関数群で構成します。
メールの送受信は、マルチタスクOSモジュールのメール送受信関数( snd_msg / isnd_msg / rcv_msg )を使用します。
また、メールデータ用の領域は、固定長メモリ管理モジュールの関数( FmAalloc / FmFree )を使用し、メールデータブロックの
確保/解放を行います。
メールデータ用のメモリスペースは、固定長メモリ管理モジュールの関数( FmCreate / FmInit)により、ブロックサイズ=使用す
るキューデータのサイズ+4として、FmCreate() / FmInit()にて初期化しておく必要があります。
キュー管理に関する汎用関数一覧を以下に示します。
項番 関 数 名 機 能
1 que_inz 起動時初期設定
2 que_enq タスクへのエンキュー
3 ique_enq 割り込み処理からタスクへのエンキュー
4 que_deq キューの取り出し
5 que_pol キューデータ到着チェック
6 que_freesize キュースペースの空きブロック数取得
3.1. エラーコード
名 称 値 内 容
QER_OK 0 正常
QER_NOMEM ―1 キューデータ用のメモリ確保不能
その他 - リアルタイムOSの関数( snd_msg / isnd_msg / rcv_msg / pol_msg )のエラーコードと同じ
3.2. エラーハンドラの登録
キュー管理モジュール関数群(但し、que_inz を除く)の実行中にエラーを検出した場合、エラーハンドラが登録されていれば、当
該エラーハンドラの呼び出しを行います。
エラーハンドラの登録は、que_inz 関数にて行います。
エラーハンドラのプロトタイプは以下のとおりです。
void errhdl( int qid, int err, VOP qd);
qid - キューID
err – エラーコード
qd – キューデータのアドレス
i8086/MS-DOS リアルタイム・マルチタスクOS
17
3.3. 関数仕様
3.3.1. 起動時初期設定 - que_inz
形 式 VO que_inz(HFMM hFmm, VO (*errhdl)(UW qid, UW err, VOP qp));
msh :メモリスペースハンドル(キューデータ用のメモリブロックを獲得/解放するメモリスペースハンドル)
errhdl :エラーハンドラのアドレス(エラーハンドラを指定しない場合はNULL)
説 明 キュー管理モジュールの、起動時初期設定を行ないます。
msh は、キューデータ用のメモリブロックを確保/解放するメモリスペースハンドル( fm_init で得た値)を指定します。
この関数はシステムの起動時に1度だけ実行します。
戻り値 なし
3.3.2. エンキュー - que_enq
形 式 UW que_enq(UW queid, VOP pQueData, UW len);
queid : キューID(snd_msg のメールボックスID)
pQueData : キューデータのアドレス
len : キューデータのバイト数
説 明 指定されたキューデータをエンキューします。
キューデータ用のメモリブロックを FmAlloc 関数により確保し、snd_msg 関数によりメールの送信を行います。
戻り値 =0 : 正常
≠0 : エラー
3.3.3. 割込処理からのエンキュー - ique_enq
形 式 UW ique_enq(UW queid, VOP pQueData, UW len);
queid : キューID(isnd_msg のメールボックスID)
pQueData : キューデータのアドレス
len : キューデータのバイト数
説 明 割り込みハンドラから、指定されたキューデータをエンキューします。
キューデータ用のメモリブロックを iFmAlloc 関数により確保し、isnd_msg 関数によりメールの送信を行います。
この関数では、エラーが発生しても、エラーハンドラの呼び出しは行いません。
戻り値 =0 : 正常
≠0 : エラー
3.3.4. デキュー - que_deq
形 式 UW que_deq(UW queid, VOP pQueBuf, UW len);
queid : キューID(rcv_msg のメールボックスID)
pQueBuf : 取り出したキューデータを格納するバッファのアドレス
len : キューデータのバイト数
説 明 指定されたキューデータを取り出します。(キューデータの取り出しは、rcv_msg 関数により行います。)
キューデータは、quedata で示される領域へコピーした後に、FmFree 関数により解放します。
指定されたキューにデータが無い場合は、エンキューされるまでタスクをウェイトします。
戻り値 =0 : 正常
≠0 : エラー
i8086/MS-DOS リアルタイム・マルチタスクOS
18
3.3.5. キューデータ到着チェック - que_pol
形 式 UW que_pol(UW queid, VOP pQueBuf, UW len);
queid : キューID(pol_msg のメールボックスID)
pQueBuf : 取り出したキューデータを格納するバッファのアドレス
len : キューデータのバイト数
説 明 キューデータが受信されている場合、次に受信すべきキューデータを quedata で示される領域へコピーます。
但し、キューデータの取り出しは行いません。従って、 que_deq 関数により同一キューデータが取り出されます。
指定されたキューにデータが無い場合は、戻り値=TE_NOMAILを返します。
戻り値 =0 : 正常
≠0 : 受信キューデータなし/エラー
3.3.6. 空きキューブロック数取得 - que_freesize
形 式 UL que_freesize(VO);
説 明 キュースペース内の空きキューデータブロック数を取得します。
戻り値 空きキューデータブロック数
i8086/MS-DOS リアルタイム・マルチタスクOS
19
4. リアルタイムOSのPCハンドリング KrtPCIIF.H , KrtPCI.ASM
本モジュール(以下、PCIという)は、リアルタイムOS(KrtKNL.ASM)をパソコン上で使用する際の、割り込み、および、 MS
-DOSファンクションコール等のハンドリングを行います。
4.1. 適用機種
PC/AT互換(DOS/V)機、あるいは、PC-9801のMS-DOS上で動作します
尚、機種の判別は、以下の方法で自動的に行われます。
PCの種別判断は、BIOSコール(INT 1Ch,AH=0)により行います
PC/AT機の場合、INT-1Chはタイマ割り込みから定期的にコールされるようになっていますが実際の処理は何も行ってい
ません。
PC-9801の場合、INT-1ChはリアルタイムクロックBIOSとなっており、AH=0にて日付けの取得を行います。
これにより、INT-1Ch,AH=0にて日付けバッファが変化した場合PC-9801と判断します。
4.2. タイマ割り込みのハンドリング
タイマ割り込みベクタ(INT-08h)を書き換えることにより、タイマ割り込み処理を独自のタイマ割り込み処理に置き換えます。
初期化関数( pci_inz )で、コールバック関数を指定しなかった場合(NULL 指定の場合)は、systic の呼び出しを行った後に、_ret_int
へジャンプし、タスク切り替えを行います。
タイマ割り込み処理として何か特別な処理を行ないたい場合、初期化関数( pci_inz )により、タイマ割り込みコールバック関数を
指定することにより、約10ms周期で当該コールバック関数が呼び出されます。
このコールバック関数は、タイマ割り込みの延長線上で実行されます。従って、DOSファンクションコール等は実行できません。
タイマ割り込みコールバック関数の形式は、以下のとおりです。
UW tim_callback( void );
また、コールバック関数の戻り値により、タイマ割り込みの終了時動作を指定できます。
コールバック関数の戻り値に、以下の値(組み合わせ可)を指定できます。
・PCI_SYSTIC : リアルタイムOSのタイマ処理(systic)をコールします。
・PCI_SCHEDULE : リアルタイムOSの割り込み終了処理(ret_int)へジャンプし、タスクの切り替えを行います。
PCI_SYSTIC を指定する場合は、PCI_SCHEDULE も共に指定して下さい。
また、割り込みからのシステムコール(iwup_tsk 等)を実行した場合は、必ず PCI_SCHEDULE を指定して下さい。
尚、戻り値=PCI_NOFUNC とした場合は、上記動作は何も行わずにIRET命令により割り込みを終了します。
i8086/MS-DOS リアルタイム・マルチタスクOS
20
4.3. キー割り込みのハンドリング
キー割り込みベクタ(INT-09h)を書き換えることにより、システムのキー割り込み処理に、独自のキー 割り込み処理を追加
します。
初期化関数( pci_inz )により、キー割り込みコールバック関数が指定された場合、キー割り込みの延長線上で当該コールバック関
数が呼び出されます。(但し、キーバッファに有効なデータが入った場合のみ)
このコールバック関数は、キー割り込みの延長線上で実行されます。従って、DOSファンクションコール等は実行できません。
コールバック関数の呼び出しに際しては、入力されたキーコードが引き渡されます。
このキーコードは、BIOSコール(PC/ATの場合 INT-16h,AH=1、PC-9801の場合 INT-18h,AH=1)により得たキーコー
ドが設定されます。(Bit15-8=走査コード,Bit7-0=文字コードが設定されます)
尚、特殊キーのキーコードは、以下の名称の変数で定義されています。
K_UP, K_DOWN, K_LEFT, K_RIGHT ---------- ↑ ↓ ← → キー
K_INS, K_DEL, K_HOME, K_PgUp, K_PgDn --- INS,DEL,HOME,PgUp,PgDnキー
K_F1 ~ K_F10 ------------------------ F1~F10キー
KS_F1 ~ KS_F10 ----------------------- Shift + F1~F10キー
KC_F1 ~ KC_F10 ----------------------- Ctrl + F1~F10キー
キー割り込みコールバック関数の形式は、以下のとおりです。
UW key_callback( UW key_code );
また、コールバック関数の戻り値により、キー割り込みの終了時動作を指定できます。
戻り値に、以下の値(組み合わせ可)を指定できます。
・PCI_DISCARD : キーデータの空読みを行い、当該キーデータを読み捨てる。
・PCI_SCHEDULE : リアルタイムOSの割り込み終了処理( _ret_int )へジャンプし、タスクの切り替えを行います。
また、割り込みからのシステムコール(iwup_tsk 等)を実行した場合は、必ず PCI_SCHEDULE を指定して下さい。
尚、戻り値=PCI_NOFUNC とした場合、あるいは、初期化関数( pci_inz )で、コールバック関数を指定しなかった場合
(0指定の場合)は、上記動作は何も行わずにIRET命令により割り込みを終了します。
i8086/MS-DOS リアルタイム・マルチタスクOS
21
4.4. RS-232C割り込みのハンドリング
RS-232C割り込みベクタ(COM1 の場合 INT 0Ch, COM2 の場合 INT 0Bh)を書き換えることにより、割込み処理をハンドルします
RS-232C割り込み発生時のコールバック関数の登録は、関数( pci_set232c )により行います。
但し、この関数では、RS-232C割り込み発生時に、当該コールバック関数の呼び出しを行うように設定するだけであり、割り
込みコントローラによる割り込みの許可/禁止,ボーレート等の通信条件設定や通信データの入出力は、アプリケーション側で行わな
ければなりません。
このコールバック関数は、RS-232C割り込みの延長線上で実行されます。従って、DOSファンクションコール等は実行でき
ません。
RS-232C割り込みコールバック関数の形式は、以下のとおりです。
UW ser_callback( VO );
また、コールバック関数の戻り値により、RS-232C割り込みの終了時動作を指定できます。
戻り値に、以下の値を指定できます。
・PCI_NOFUNC : IRETにより割り込みを終了する。
・PCI_SCHEDULE : リアルタイムOSの割り込み終了処理(ret_int)へジャンプし、タスクの切り替えを行います。
尚、ボーレート等の通信パラメタの設定は pcs_hw_inz 関数で行います。
RS-232C 送受信割り込み処理の設定は pcs_if_inz 関数にて設定します。pcs_if_inz 関数では、pci_set232c をコールします。
i8086/MS-DOS リアルタイム・マルチタスクOS
22
4.5. マウス割り込みのハンドリング
マウス割込ベクタ(INT-15h(PC-98) / INT-75h(DOS/V))を書き換えと、マウスドライバのファンクション(INT-33h,AX=12)により、
割り込みサブルーチンの登録を行うことにより、マウス割り込み処理をハンドルします。
マウスを使用する場合は、OS起動前に pci_initmus() によりマウスの初期化を行います。
マウス割り込み発生時のコールバック関数の登録は、pci_setmus() により行います。
このコールバック関数は、マウス割り込みの延長線上で実行されます。従って、DOSファンクションコール等は実行できません。
マウス割り込みコールバック関数の形式は、以下のとおりです。
UW mus_callback( UW sts, UW btn, UW x, UW y, UW dx, UW dy );
sts - マウス状態
PMS_LB_OFF(Bit4) - 右ボタンが離された
PMS_LB_ON (Bit3) - 〃 押された
PMS_RB_OFF(Bit2) - 左ボタンが離された
PMS_RB_ON (Bit1) - 〃 押された
PMS_CHANGE(Bit0) - カーソル位置が変更された
btn - マウスボタンの状態
PMB_RGT(Bit1) - 右ボタンが押されている
PMB_LFT(Bit0) - 左ボタンが押されている
x - マウスカーソル位置(X座標)
y - 〃 (Y座標)
dx - Δx
dy - Δy
また、コールバック関数の戻り値により、マウス割り込みの終了時動作を指定できます。
戻り値に、以下の値を指定できます。
・PCI_NOFUNC : IRETにより割り込みを終了する。
・PCI_SCHEDULE : リアルタイムOSの割り込み終了処理(ret_int)へジャンプし、タスクの切り替えを行います。
<注意>※ Windows98 のDOSプロンプト窓で実行する場合は、Windowsのマウスシステムが使用される為、DOS上で
のマウス割り込みは発生しません。この為、戻り値に「PCI_SCHEDULE」を指定してもタスク切り替えは行われません。
この場合、タスクの切り替えは、タイマ割り込み等の他の割り込みが発生するか、あるいは、他のシステムコール発行時
までタスクの切り替えが延期されます。
※ マウスを使用する場合は、あらかじめ、MOUSE フォルダ下の「MOUSE.COM」を実行しておかなければなりません。
i8086/MS-DOS リアルタイム・マルチタスクOS
23
4.6. ハードウェア割り込みからのタスクスケジュールの一時停止
PCIでハンドリングするタイマ割り込み、および、キー割り込み等は、ハードウェアにより任意のタイミングで発生します。
プログラムをCV(コードビュー)等のデッバッガ下で実行中、ブレークポイント等によりプログラムが停止した状態(デバッガに
制御が移っている状態)でハードウェア割り込みが発生した場合、割り込みのハンドリングを行うとタスクスケジュールにより自プロ
グラムが勝手に実行され、予期せぬ事態となります。(通常はクラッシュする)
PCIでは、このような事態を避けるため、pci_inz 関数で fDbgChk=TRUE を指定することにより、デバッガに制御が移っている間は
ハードウェア割り込みのハンドリングを行わずに、以下のように処理します。
・タイマ割り込みの場合、何も行いません。
・キー割り込みの場合、システムに備わっている当該ハードウェア割り込み処理のみを実行します。
・RS-232C割り込みの場合、コールバック関数はコールしますが、タスクのスケジュールは行ないません。
デバッガに制御が移っているかどうかは、ネスト最上位の割り込みが発生した時のスタックポインタの値により判断します。
スタックポインタが、自プログラム領域の範囲外ならば、制御がデバッガに移っているものと判断します。
自プログラム領域とは、PSP(プログラムセグメントプリフィクス)を先頭とし、PSP内の「プログラム終了アドレス」で示さ
れるアドレスまでを意味します。
4.7. 多重割り込み制御
本モジュールでは、ハードウェアの多重割り込み制御を行います。
尚、タイマ,キー,RS-232Cおよびマウス割り込み以外のハードウェア割り込み( PC-9801=INT 08h-17h, DOS/V=INT 08h-0Fh &
70h-77h)についても割り込みベクタを書き換えることにより、システムに備わっている当該ハードウェア割り込み処理に加えて、割り
込みのネスト制御を行います。
4.8. DOSファンクションコールのハンドリング
マルチタスクプログラムの場合、各タスクが排他制御なしにDOSファンクションコールを実行することはできません。
(MS-DOSはマルチタスクOSではないので、たちまちクラッシュすることになります)
本モジュールでは、DOSファンクションコールベクタ(INT-21h)を書き換えることにより、リアルタイムOSのセマフォ
機能により、DOSファンクションコールを排他制御します。従って、あるタスクがDOSファンクションコールを実行中に、他のタ
スクがDOSファンクションコールを実行しようとした場合、他のタスクはDOSファンクションコールが終了するまで ウェイトさせ
られることになります。
DOSファンクションコールを使用する場合は、初期化関数( pci_inz )で、DOSファンクションコール排他制御用にセマフォ
IDを1つ指定しなければなりません。
DOSファンクションコールは、ユーザが意図的に「INT-21h」を実行しなくても、printfやfopen等の数多くの
ライブラリ関数により実行されます。
尚、DOSファンクションコールで、AH=4Ch(プロセスの終了)が実行された場合は、本モジュールでハンドリングしている
割り込みベクタを全て元に戻します。
4.9. Ctrl-Break割り込みのハンドリング
Ctrl+Cキーが押された場合、BREAKフラグがONの場合、DOSによりINT-23h割り込みが実行されます。
本モジュールでは、この割り込みをハンドリングし、INT-23h割り込みが実行された場合、本モジュールでハンドリングして
いる割り込みベクタを全て元に戻します。
従って、各割り込みハンドリングや、リアルタイムOSのシステムタイマは停止します。
i8086/MS-DOS リアルタイム・マルチタスクOS
24
4.10. 致命的なエラー割り込みのハンドリング
「ディスクの準備ができていない」等に代表される致命的なエラーが発生した場合、DOSにより、INT-24h割り込みが実行
されます。
本モジュールでは,この割り込みをハンドリングし、独自のエラー処理を可能にします。
初期化関数( pci_inz )により、エラー割り込みコールバック関数が指定された場合、致命的エラーが発生した時点で当該コールバ
ック関数が呼び出されます。
このコールバック関数は、致命的エラーハンドラ(INT-24h)として実行されます。従って、使用できるDOSファンクショ
ンコールは以下のものに限定されます。
・AH=01h~0Ch : キャラクタ入出力
・AH=30h/AX=3306h : バージョン番号の取得
・AX=3300h/3301h : Ctrl-Cフラグの設定/取得
・AH=50h/51h/62h : PSPアドレスの設定/取得
・AH=59h : 拡張エラーコードの取得
コールバック関数の呼び出しに際しては、以下のエラー情報が引き渡されます。
・ax : エラー情報 (INT-24h発生時のAXの値)
・di : エラーコード(INT-24h発生時のDIの値)
・p : デバイスドライバ制御ブロックの先頭アドレス(INT-24h発生時のBP,SIの値)
※ 尚、上記エラー情報の詳細については、当該テクニカルリファレンスを参照してください。
致命的エラー割り込みコールバック関数の形式は、以下のとおりです。
int _far err_callback( int ax, int di, void _far *p );
また、コールバック関数の戻り値により、致命的エラー割り込みの終了時動作を指定できます。
コールバック関数の戻り値で、以下の値(いずれか1ヶのみ)を指定します。
・PCI_IGNORE : エラーを無視し、処理を続行する。
・PCI_RETRY : 操作を再試行する。
・PCI_STOP : プログラムを終了する。
・PCI_ABORT : プログラム上からのシステムコール失敗とする。
・PCI_SYSTEM : DOSの致命的エラー処理を実行する。
尚、致命的エラーが発生した場合、本モジュールでハンドリングしている割り込みベクタは全て元に戻されます。
従って、各割り込みハンドリングや、リアルタイムOSのシステムタイマは停止します。
4.11. プログラムの終了
プログラムの終了時は、関数( pci_end )を実行して下さい。
この関数は、本モジュールでハンドリングしている割り込みベクタを全て元に戻します。
4.12. タスク生成時の注意
MSCのライブラリ関数を使用する場合、os_start間数でのイニシャルタスクのスタック領域、および cre_tsk関数
による生成するタスクのスタック領域は、スタックセグメント中の領域を指定して下さい。
さもないと、ライブラリ関数の実行時に、スタックオーバーチェックによりランタイムエラーとなります。
具体的には、スタック領域を自関数の自動変数として定義し、その自動変数を各タスクのスタック領域として指定します。
スタック領域はデフォルトで2KB割り当てられますが、不足な場合はLINKオプション(STACK)にて拡張します。
(例) LINK /STACK:16384 ・・・ スタックセグメントを16KB割り当てる
尚、各タスクのスタック領域は、(詳細値算出は不能ですが)最低でも1KB以上割り当てるようにして下さい。
i8086/MS-DOS リアルタイム・マルチタスクOS
25
4.13. 関数仕様
4.13.1. PC割り込みベクタ退避 - pci_save_vec
形 式 VO pci_save_vec ( VO );
説 明 PCの割り込みベクタを退避します。
この関数は、PCハンドリングを行う場合、OS起動前に1度だけ実行します。
戻り値 なし
4.13.2. マウス初期設定 - pci_initmus
形 式 UW pci_initmus( VO );
説 明 マウスハードウェアの初期化を行います。この関数は、マウスを使用する場合、OS起動前に1度だけ実行してください。
戻り値 0xFFFF : マウス使用可能
0x0000 : マウス使用不可
4.13.3. パソコン種別の初期化 - pci_ini_pckind
形 式 void pci_ini_pckind( void );
説 明 パソコン種別情報を初期化します。また、PC-9801の場合は、タイマクロック数の設定を行います。
パソコン種別は、以下の方法で設定します。
・INT 1Ch,AH=0(PC-9801の場合リアルタイムクロックBIOS)を実行し、日付格納バッファ
が変化した場合PC-9801と判断する。
PC-9801のタイマクロック数は以下の手順で設定します。
・INT 19h,AH=0(RS-232C BIOS)にて、通信速度=9600bpsを設定する。
(これによりタイマ2には、13(8/16MHz 系 CPU)あるいは16(5/10/12/20MHz 系 CPU)が設定される)
・タイマ2に設定された値を読みとる
(実際は、設定値を直接リードすることはできないので、128回リードループし、最大値を採用する)
・タイマ2<=13ならばタイマクロック数=1,996,800とする。
タイマ2 > 13ならばタイマクロック数=2,457,600とする
・尚、RS-232C割り込み(INT 0Ch)は禁止状態となります。
尚、上記処理は全て初回コール時のみ行います。2回目以降のコールでは何も行いません。
この関数は、pci_inz 関数を実行する前に、pci_get_pckind()により、パソコン種別を判定したい場合に実行します。
戻り値 なし
i8086/MS-DOS リアルタイム・マルチタスクOS
26
4.13.4. PCハンドリング初期設定 - pci_inz
形 式 VO pci_inz( UW dos_semid, BOOL fDbgChk,
UW ( *tim_func ) ( VO ),
UW ( *key_func ) ( UW key_code ),
UW ( *err_func ) ( UW ax, UW dx, VOP p) );
dos_semid - DOSファンクションコールの排他制御用セマフォID
fDbgChk - デバッガモードチェックフラグ
tim_func - タイマ割り込み時コールバック関数のアドレス(未使用の場合は NULL を指定)
key_func - キー割り込み時コールバック関数のアドレス (未使用の場合は NULL を指定)
err_func - 致命的エラー発生割り込み時のコールバック関数のアドレス(未使用の場合は NULL を指定)
説 明 リアルタイムOSをパソコン上で使用する際の、割り込みやDOSファンクションコールハンドリング情報の初期設定を
行います
「dos_semid」は、DOSファンクションコールの排他制御に使用するセマフォID(0~15)を指定します。
「fDbgChk」は、CodeView 等のデバッガモード(デバッガによりブレークポイントで停止している状態)時の、タイマ,
キー,RS-232C 割り込み動作を指定します。fDbgChk=TRUE とした場合は、デバッガモード状態で割り込みが発生した場合に、
タスクスケジュールを行なわないように制御します。つまり、割り込み終了時に_ret_int へ分岐せずに IRET 命令で終了し
ます。「fDbgChk」は通常(デバッグ以外の場合)は FALSE を指定します。
本関数は、リアルタイムOSの起動( os_start )後、イニシャルタスクの先頭で実行して下さい。
戻り値 なし
4.13.5. RS-232C割り込み処理関数の登録 - pci_set232c
形 式 VO pci_set232c( UW com, UW (*ser_callback)(VO) );
com – COMポート番号(0:COM1 1:COM2, 但し、PC-98の場合は、0のみ指定可)
ser_callback – RS-232C割り込み時コールバック関数のアドレス(未使用の場合は0を指定)
説 明 RS-232C割り込み処理関数の登録を行います。
以降、RS-232C割り込みが発生したら、ser_callback で指定された関数がコールされます。
戻り値 なし
4.13.6. マウス割り込み処理関数の登録 - pci_setmus
形 式 UW pci_setmus( UW (*mus_callback)(UW sts, UW btn, UW x, UW y, UW dx, UW dy));
mus_callback - マウス割り込み時コールバック関数のアドレス(未使用の場合は0を指定)
説 明 マウス割り込み処理関数の登録を行います。
以降、マウス割り込みが発生したら、mus_callback で指定された関数がコールされます。
戻り値 0xFFFF : マウス使用可能
0x0000 : マウス使用不可
i8086/MS-DOS リアルタイム・マルチタスクOS
27
4.13.7. パソコン種別の取得 - pci_get_pckind
形 式 UW pci_get_pckind( VO );
説 明 パソコン種別を返します。
本関数実行前に、pci_inz あるいは pci_ini_pckind が実行されていなければなりません。
以下のマクロは、pci_get_pckind()を実行し、パソコン種別を判定します。
マクロ名 内容
IsDosv DOS/V(PC/AT)の場合 TRUE, PC-9801 の場合 FALSE を返します
IsPc98 PC-9801 の場合 TRUE, DOS/V(PC/AT)の場合 FALSE を返します
戻り値 PCI_PC98 : PC-98シリーズ
PCI_DOSV : IBM-PC/AT
4.13.8. 遅延起床タスクの設定 - pci_delayed_wup
形 式 UW pci_delayed_wup( UW tskid );
tskid – 遅延起床するタスクのタスクID
説 明 タスクIDで指定されたタスクを遅延起床します。
遅延起床とは、プログラムの制御がCV等のデバッガから自プログラムに移った時に、タスク起床することを意味します。
タスクの遅延起床は、タイマ割り込み処理にてプログラム制御状態を監視し、デバッガに制御が移っていない場合に、当
該タスクに対しiwup_tskを発行することにより行います。
戻り値 0 : 正常
1 : 遅延起床タスク数オーバー
4.13.9. プログラムの終了時処理 - pci_end
形 式 VO pci_end( VO );
説 明 本モジュールでハンドリングしている割り込みベクタを全て元に戻します。
戻り値 なし
i8086/MS-DOS リアルタイム・マルチタスクOS
28
5. RS-232CのPCハンドリング KrtPCIIF.h, KrtPCIS.c
このモジュールは、PC上でのRS-232C通信に関する汎用関数群で構成します。
RS-232C通信の汎用関数群を以下に示します。
項番 関数名 機 能
1 pcs_inz 初期設定
2 pcs_snd データブロック送信
3 pcs_status ステータス取得
物理アクセス関数群4 pcs_rxdat 受信データ取得
5 pcs_txdat 1バイト送信
6 pcs_distx 送信割り込み禁止
7 pcs_enatx 送信割り込み許可
8 pcs_IsDisTx 送信割り込み禁止状態取得
5.1. RS―232Cステータス
「RS-232Cステータス」は、以下のシンボル名で表されます。
項番 シンボル Bit 内 容
1 PCS_BKD 6 ブレーク検出
2 PCS_FE 5 フレーミングエラー
3 PCS_OVE 4 オーバーランエラー
4 PCS_PE 3 パリティエラー
5 PCS_RBRDY 1 受信データあり
6 PCS_TBRDY 0 送信バッファエンプティ
i8086/MS-DOS リアルタイム・マルチタスクOS
29
5.2. 関数仕様
5.2.1. 232Cハードウェア初期設定 - pcs_hw_inz
形 式 UL pcs_hw_inz( UW com, UL bau, UB prm);
com - COMポート番号(0:COM1 1:COM2) ……… PC-9801の場合は、0(COM1)のみ指定可
bau - 通信速度
prm - 回線制御パラメタ
説 明 RS-232Cハードウェアの初期設定を行います。
「com」は、COMポート番号(0~1)を指定します。(但し、PC-9801の場合は、何を指定してもCOM1固定となります)
「bau」は、通信速度値(以下のいずれか)を指定します。
・DOS/Vの場合、2~115200の間の任意の値。但し、指定値が設定不能な場合は、一番近い値を設定します。
・PC-98の場合、1~2457600の間の任意の値。但し、指定値が設定不能な場合は、一番近い値を設定します。
「prm」は、回線制御パラメタ(以下の組み合わせ)を指定します。
・PCS_NOPTY(パリティなし), PCS_ODDPTY(奇数パリティ), or PCS_EVENPTY(偶数パリティ)
・PCS_STP1(ストップビット=1ビット), or PCS_STP2(ストップビット=2ビット)
・PCS_LEN7(データ長=7ビット), or PCS_LEN8(データ長=8ビット)
本関数では、内部的にPC種別初期化関数( pci_ini_pckind )が実行されます。
戻り値 実際に設定された通信速度[bps]
i8086/MS-DOS リアルタイム・マルチタスクOS
30
5.2.2. OSインタフェース初期設定 - pcs_if_inz
形 式 VO pcs_if_inz( UW com, UW irq, UW (*ser_rx)(UB dat, UB sts), UW (*ser_tx)(VO), VOP p_txb, UW l_txb);
com - COMポート番号(0:COM1 1:COM2) ……… PC-9801の場合は、0(COM1)のみ指定可
irq - COM割り込み番号
ser_rx – 受信割り込み処理関数のアドレス(無い場合はヌルポインタを指定)
ser_tx – 送信割り込み処理関数のアドレス(内蔵されている送信割り込み処理を使用する場合はヌルポインタを指定)
pTxb - 送信バッファ領域の先頭アドレス(ser_tx=ヌルポインタ時のみ指定要)
lTxb - 送信バッファ領域のバイト数 ( 〃 )
説 明 RS-232CのPCハンドリングに関するOSとのインタフェースの初期設定を行います。
この関数は、PCハンドリング初期化関数( pci_inz )の直後に実行しなければなりません。
「com」は、COMポート番号(0~1)を指定します。(但し、PC-9801の場合は、0(COM1)のみ指定可)
「irq」は、COMポートの割り込み番号であり、通常はCOM1の場合4を,COM2の場合は3を指定します。
「ser_rx」は、受信割り込み処理関数のアドレスを指定します。
この関数は、シリアルデータ1バイト受信毎にコールされます。
「ser_tx」は、送信割り込み処理関数のアドレスですが、通常は NULL を指定します。
この場合、内蔵されている送信割り込み処理が有効となり、pcs_snd()関数による送信処理が可能となります。
NULL 以外を指定した場合は、RS-232C送信割り込み時に当該関数がコールされます。
「pTxb」および、「lTxb」は、送信用スプールバッファのアドレスとバイト数を指定します。
このスプールバッファは、内蔵されている送信割り込み処理で使用されます。従って、ser_tx≠NULL の場合は
指定不要です。(ser_tx≠NULL の場合は、pTxb=NULL, lTxb=0 を指定して下さい)
「ser_rx」で指定される、受信割り込み処理関数の形式は以下のとおりです。
「ser_tx」で指定される、送信割り込み処理関数の形式は以下のとおりです。
本関数を実行した場合、RS-232C受信割り込みは許可状態となり、送信割り込みは禁止状態となります。
戻り値 なし
形 式 UW ser_rx ( UB dat, UB sts );
引 数 dat – 受信データバイト
sts – RS-232Cステータス
戻り値 PCI_NOFUNC : IRETにより割り込みを終了
PCI_SCHEDULE : 割り込み終了時、タスクスケジュールを行う
形 式 UW ser_tx ( VO );
引 数 なし
戻り値 PCI_NOFUNC : IRETにより割り込みを終了
PCI_SCHEDULE : 割り込み終了時、タスクスケジュールを行う
i8086/MS-DOS リアルタイム・マルチタスクOS
31
5.2.3. データブロック送信 - pcs_snd
形 式 BOOL pcs_snd( UB *dat, UW len);
dat - 送信するデータブロックの先頭アドレス
len - 送信するデータブロックのバイト数
説 明 RS-232C回線へデータブロックを送信します。
この関数は、送信用スプールバッファへデータの格納を行うだけであり、実際のデータ送信は本関数実行後、送信割り込
み処理にて1バイトずつ行われます。
この関数は、初期化関数( pcs_if_inz )で 引数( ser_tx )にヌルポインタを指定し、内蔵されている送信割り込み
処理を選択した場合のみ使用可能です。
この関数は、割り込み処理からはコールできません。
また、複数のタスクからコールする場合は、セマフォにより排他制御する必要があります。
戻り値 TRUE - OK
FALSE – エラー(送信スプールバッファに必要量の空きが無い)
5.2.4. 物理アクセス関数
物理アクセス関数(ハードウェアレジスタを直接アクセスする関数)の仕様は以下のとおりです。
項番 形 式 機 能 戻り値
1 UB pcs_status ( VO ); RS-232Cステータス読み出し 「RS-232Cステータス」参照
2 UB pcs_rxdat ( VO ); 受信データ読み出し 受信データ
3 VO pcs_txdat ( UB dat ); 送信データ書き込み なし
4 VO pcs_distx ( VO ); 送信割り込み禁止 なし
5 VO pcs_enatx ( VO ); 送信割り込み許可 なし
6 UB pcs_IsDisTx( VO ); 送信割り込み禁止状態取得 =0:送信割り込みは許可状態
≠0:送信割り込みは禁止状態
7 VO pcs_disrx ( VO ); 受信割り込み禁止 なし
8 VO pcs_enarx ( VO ); 受信割り込み許可 なし
9 UB pcs_IsDisRx( VO ); 受信割り込み禁止状態取得 =0:受信割り込みは許可状態
≠0:受信割り込みは禁止状態
10 VO pcs_sigout(UB sig); 信号出力(※1) なし
11 UB pcs_sigsts( VO ); 入力信号状態取得 入力信号状態(※2)
※1:出力信号は、次の名称の論理和を指定します。 -----> PCI_DTR, PCI_RTS
※2:入力信号は、次の名称の論理和が設定されます。-----> PCI_CI , PCI_DCD, PCI_DSR, PCI_CTS
上記関数は、232C-H/W初期設定( pcs_hw_inz )実行後、使用可能となります。
i8086/MS-DOS リアルタイム・マルチタスクOS
32
6. サンプルプログラム
以下に、マウスを扱ったものと、RS-232C を扱った、2つのサンプルプログラムを示します。
これらのサンプルプログラムは、IBM-PC/AT(DOS/V)、あるいは NEC-PC9801 の MS-DOS 上か、Windows95/98 の DOS プロンプト窓で実
行可能です。
6.1. サンプルプログラム1
以下のプログラムは、タイマ割り込み,キー割り込みおよび、マウス割り込みをハンドリングします。
このサンプルプログラムを実行する場合は、あらかじめ、KRT\MOUSE フォルダ下の、MOUSE.COM を実行しておかなければなりません。
タイマ割り込みは、単にシステムタイマ処理のみを行います。(この場合、 pci_inz 関数の tim_func は NULL 指定で OK)
キー割り込みでは、ESC キーが押された場合はプログラムを終了するように制御し、その他のキーが押された場合はキーコードを
TskPrt タスクへ通知します。この時 TskPrt タスクはキーコードをプリントします。
マウス割り込みでは、マウス情報を TskPrt タスクへ通知します。この時 TskPrt タスクはマウス情報をプリントします。
イニシャルタスク(TskIni)は、各タスクを生成/起動したら、30秒後にプログラムを強制的に終了します。
/*==============================================================================================================*/
/* */
/* S A M P L E 1 */
/* */
/*==============================================================================================================*/
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include "krtknlif.h"
#include "krtpciif.h"
#include "kglfmm.h"
/*----- システム資源ID定義 ----------------------------------------------------------------------------------- */
enum { TSKID_PRT, TSKID_END }; /* タスクID */
enum { SEMID_DOS }; /* セマフォID */
enum { QUEID_PRT }; /* キューID */
/*----- キューデータ形式 --------------------------------------------------------------------------------------- */
typedef struct {
UW kind; /* 種別(KND_KEY / KND_MUS) */
union {
UW key; /* キーコード */
struct {UW sts, btn, x, y, dx, dy;} m; /* マウスデータ */
} u;
} QUEDATA;
enum {KND_KEY, KND_MUS};
/*----- その他 ------------------------------------------------------------------------------------------------- */
static KGLFMM objFmm; /* FMMオブジェクトインスタンス */
static UB QueSpace[32768]; /* キューデータスペース */
struct SREGS segregs; /* セグメントレジスタ値 */
/*-------------------------------------------------------------------------------------------------------------- */
/* FMM排他制御用コールバック(割り込み禁止/許可) */
/* */
/*--------------------------------------------------------------------------------------------------------------*/
static cbDisInt(HFMM h)
{
_asm {CLI};
}
i8086/MS-DOS リアルタイム・マルチタスクOS
33
/*-------------------------------------------------------------------------------------------------------------- */
static cbEnaInt(HFMM h)
{
_asm {STI};
}
/*-------------------------------------------------------------------------------------------------------------- */
/* キー割り込み処理 */
/* */
/* この関数は、キーが押下された際に、システムよりコールされます。 */
/*--------------------------------------------------------------------------------- -----------------------------*/
UW IntKey(UW kc)
{
QUEDATA qd;
if ((kc & 255) == CC_ESC) { /* ESCキー押下? */
iwup_tsk(TSKID_END); /* ジョブ終了タスク起動 */
}
else { /* その他のキー押下? */
qd.kind = KND_KEY; /* キューデータ(キーコード)設定 */
qd.u.key = kc; /* ・ */
ique_enq(QUEID_PRT, &qd, sizeof qd); /* エンキュー */
}
return (PCI_DISCARD | PCI_SCHEDULE); /* キー読み捨て,タスクスケジュール */
}
/*-------------------------------------------------------------------------------------------------------------- */
/* マウス割り込み処理 */
/* */
/* この関数は、マウスが動いたりボタンが押された際に、システムよりコールされます。 */
/*-------------------------------------------------------------------------------------------------------------- */
UW IntMus(UW sts, UW btn, UW x, UW y, int dx, int dy)
{
QUEDATA qd;
qd.kind = KND_MUS; /* キューデータ(マウス情報)設定 */
qd.u.m.sts = sts; /* ・ */
qd.u.m.btn = btn; /* ・ */
qd.u.m.x = x; /* ・ */
qd.u.m.y = y; /* ・ */
qd.u.m.dx = dx; /* ・ */
qd.u.m.dy = dy; /* ・ */
ique_enq(QUEID_PRT, &qd, sizeof qd); /* エンキュー */
return PCI_SCHEDULE; /* タスクスケジュール */
}
/*-------------------------------------------------------------------------------------------------------------- */
/* イベントプリントタスク */
/*-------------------------------------------------------------------------------------------------------------- */
VO TskPrt(VO)
{
QUEDATA qd;
while (TRUE) {
que_deq(QUEID_PRT, &qd, sizeof qd);
switch (qd.kind) {
case KND_KEY: printf("KEY : %04X\n", qd.u.key); break;
case KND_MUS: printf("MUS : STS=%04Xh BTN=%04Xh, X=%d, Y=%d, dX=%d, dY=%d \n",
qd.u.m.sts, qd.u.m.btn, qd.u.m.x, qd.u.m.y, qd.u.m.dx, qd.u.m.dy); break;
}
}
}
/*-------------------------------------------------------------------------------------------------------------- */
/* ジョブ終了タスク */
i8086/MS-DOS リアルタイム・マルチタスクOS
34
/*-------------------------------------------------------------------------------------------------------------- */
VO TskEnd(VO)
{
slp_tsk();
pci_end();
exit(0);
}
/*-------------------------------------------------------------------------------------------------------------- */
/* イニシャルタスク */
/*-------------------------------------------------------------------------------------------------------------- */
VO TskIni(VO)
{
UB StkPrt[2048];
UB StkEnd[2048];
pci_inz(SEMID_DOS, FALSE, NULL, IntKey, NULL); /* OSのPCインタフェース初期化 */
pci_setmus( IntMus ); /* マウス割り込み処理登録 */
cre_tsk(TSKID_PRT, 1, TskPrt, StkPrt + sizeof StkPrt, segregs.ds); /* タスク生成 */
cre_tsk(TSKID_END, 2, TskEnd, StkEnd + sizeof StkEnd, segregs.ds); /* ・ */
sta_tsk(TSKID_PRT); /* ・ */
sta_tsk(TSKID_END); /* ・ */
printf("キー入力/マウス操作してください。当該割り込み情報を表示します。\n");
printf("但し、30秒すると自動的にプログラムを終了します\n");
wai_tsk(3000); /* 30秒ウェイト */
wup_tsk(TSKID_END); /* ジョブ終了タスク起床 */
ext_tsk(); /* 自タスク終了 */
}
/*--------------------------------------------------------------------------------------------------------------*/
/* m a i n */
/*-------------------------------------------------------------------------------------- ------------------------*/
main(int argc, char *argv[])
{
UB StkIni[8192]; /* イニシャルタスクおよびその他のタスク用スタック領域 */
UB StkIdl[1024]; /* アイドルタスク用スタック領域 */
HFMM hFmm;
segread(&segregs); /* セグメントレジスタ リード */
if (pci_initmus() != 0xFFFF) { /* マウス初期化 */
printf("マウス使用不可\n");
}
hFmm = FmCreate(QueSpace, sizeof QueSpace, /* キュースペース初期化(固定長メモリ管理) */
sizeof(QUEDATA) + 4, /* ・ */
NULL, /* ・ */
cbDisInt, cbEnaInt); /* ・ */
que_inz(hFmm, NULL); /* キュー管理初期化 */
pci_save_vec(); /* 割り込みベクタ退避 */
pci_ini_pckind(); /* PC種別初期化 */
os_start(TskIni, StkIni + sizeof StkIni, StkIdl + sizeof StkIdl, segregs.ds);
}
i8086/MS-DOS リアルタイム・マルチタスクOS
35
6.2. サンプルプログラム2
以下のプログラムは、タイマ割り込み,キー割り込みおよび、RS-232C(COM1)割り込みをハンドリングします。
RS-232C のパラメタは、9600bps, NoParity, StopBit=1, DatBits=8 です。
タイマ割り込みは、単にシステムタイマ処理のみを行います。(この場合、 pci_inz 関数の tim_func は NULL 指定で OK)
キー割り込みでは、ESC キーが押された場合はプログラムを終了するように制御し、その他のキーが押された場合はキーコードを
送信データリングバッファ( txbf)に格納します。
RS-232C 送信割り込みでは、スプールバッファにデータがあれば、これを送出します。(この場合、 pcs_if_inz 関数の ser_tx 引数
は NULL で OK です。スプールバッファだけを指定すれば送信スプール制御を自動的に行います)
RS-232C 受信割り込みでは、受信したデータを受信データリングバッファ(rxbf)に格納します。
通信タスク(TskCom)は、受信データリングバッファにデータがあれば、これを取り出して画面に表示します。また、送信デー
タリングバッファにデータがあれば、これを取り出して、COM1 回線へ送出します。
/*==============================================================================================================*/
/* */
/* S A M P L E 2 */
/* */
/*==============================================================================================================*/
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include "krtknlif.h"
#include "krtpciif.h"
/*----- COMポート定義 --------------------------------------------------------------------------------------- */
#define COM1 0
#define COM1_IRQ 4
/*----- システム資源ID定義 -----------------------------------------------------------------------------------*/
enum { TSKID_COM, TSKID_END }; /* タスクID */
enum { SEMID_DOS }; /* セマフォID */
/*----- 送受信データバッファ ----------------------------------------------------------------------------------- */
static UW rsix=0, reix=0;
static UB rxbf[1024];
static UW tsix=0, teix=0;
static UB txbf[1024];
/*----- 送信スプールバッファ -----------------------------------------------------------------------------------*/
static UB SpoolBuf[16384];
/*----- その他 ------------------------------------------------------------------------------------------------- */
struct SREGS segregs; /* セグメントレジスタ値 */
/*----- 割り込み禁止 ------------------------------------------------------------------------------------------- */
#define DIS_INT _asm {CLI}
#define ENA_INT _asm {STI}
/*-------------------------------------------------------------------------------------------------------------- */
/* キー割り込み処理 */
/* */
/* この関数は、キーが押下された際に、システムよりコールされます。 */
/*---------------------------------------------------------------------------------------------------------- ----*/
UW IntKey(UW kc)
{
UW rc = PCI_DISCARD;
UW nix = ((teix + 1) & 1023);
i8086/MS-DOS リアルタイム・マルチタスクOS
36
if ((kc & 0xFF) != CC_ESC) { /* ESCキー以外? */
if (tsix != nix) { /* 送信バッファに空きあり? */
txbf[teix] = (UB)(kc & 0xFF); /* 送信バッファにデータ格納 */
teix = nix; /* ・ */
}
}
else { /* ESCキー? */
iwup_tsk(TSKID_END); /* ジョブ終了タスク起床 */
rc |= PCI_SCHEDULE; /* タスクスケジュールする */
}
return rc;
}
/*-------------------------------------------------------------------------------------------------------------- */
/* RS-232C受信割り込み処理 */
/* */
/* この関数は、RS-232C回線より1バイト受信した際に、システムよりコールされます。 */
/*-------------------------------------------------------------------------------------------------------------- */
UW IntRx(UB dat, UB sts)
{
UW nix = ((reix + 1) & 1023);
if ((sts & (PCS_FE | PCS_OVE | PCS_PE)) == 0) { /* 受信エラーなし? */
if (rsix != nix) { /* 受信バッファに空きあり? */
rxbf[reix] = dat; /* 受信バッファにデータ格納 */
reix = nix; /* ・ */
}
}
return PCI_NOFUNC; /* タスクスケジュールなし
この割り込みでは、システムコールを発行していない
ので、タスクスケジュールする必要はない。 */
}
/*-------------------------------------------------------------------------------------------------------------- */
/* ジョブ終了タスク */
/*-------------------------------------------------------------------------------------------------------------- */
VO TskEnd(VO)
{
slp_tsk();
pci_end();
exit(0);
}
/*-------------------------------------------------------------------------------------------------------------- */
/* 送受信タスク */
/*-------------------------------------------------------------------------------------------------------------- */
VO TskCom(VO)
{
UB c;
while (TRUE) {
while (rsix != reix) { /* 受信バッファにデータあり? */
DIS_INT /* 割り込み禁止 */
c = rxbf[rsix]; /* 受信データ取り出し */
rsix = ((rsix + 1) & 1023); /* ・ */
ENA_INT /* 割り込み許可 */
putchar(c); /* 受信データ表示 */
}
while (tsix != teix) { /* 送信バッファにデータあり? */
DIS_INT /* 割り込み禁止 */
c = txbf[tsix]; /* 送信データ取り出し */
tsix = ((tsix + 1) & 1023); /* ・ */
ENA_INT /* 割り込み許可 */
while (!pcs_snd(&c, 1)) { /* 1 バイト送信 */
wai_tsk(1); /* 満杯ならば、ウェイト後再試行する */
i8086/MS-DOS リアルタイム・マルチタスクOS
37
}
}
wai_tsk(1);
}
}
/*-------------------------------------------------------------------------------------------------------------- */
/* イニシャルタスク */
/*-------------------------------------------------------------------------------------------------------------- */
VO TskIni(VO)
{
UB StkCom[2048];
UB StkEnd[2048];
pci_inz(SEMID_DOS, FALSE, NULL, IntKey, NULL); /* OSのPCインタフェース初期化 */
pcs_if_inz(COM1, COM1_IRQ, IntRx, NULL, SpoolBuf, sizeof SpoolBuf); /* RS-232cインタフェース初期化 */
cre_tsk(TSKID_COM, 1, TskCom, StkCom + sizeof StkCom, segregs.ds); /* タスク生成 */
cre_tsk(TSKID_END, 2, TskEnd, StkEnd + sizeof StkEnd, segregs.ds); /* ・ */
sta_tsk(TSKID_COM); /* ・ */
sta_tsk(TSKID_END); /* ・ */
printf("RS-232C(COM1, 9600, 8, N, 1)の送受信を行ないます。\n");
printf("キー入力した内容を送信し、受信した内容を表示します。\n");
printf("ESCキーを押すとプログラムを終了します。\n");
ext_tsk(); /* 自タスク終了 */
}
/*-------------------------------------------------------------------------------------------------------------- */
/* m a i n */
/*-------------------------------------------------------------------------------------------------------------- */
main(int argc, char *argv[])
{
UB StkIni[8192]; /* イニシャルタスクおよびその他のタスク用スタック領域 */
UB StkIdl[1024]; /* アイドルタスク用スタック領域 */
segread(&segregs); /* セグメントレジスタリード*/
pci_save_vec(); /* 割り込みベクタ退避 */
pci_ini_pckind(); /* PC種別初期化 */
pcs_hw_inz(COM1, 9600, PCS_NOPTY | PCS_STP1 | PCS_LEN8); /* RS-232C初期化 */
os_start(TskIni, StkIni + sizeof StkIni, StkIdl + sizeof StkIdl, segregs.ds); /* OSスタート */
}
i8086/MS-DOS リアルタイム・マルチタスクOS
38
7. アセンブラマクロ SpMacMSC.inc
7.1. 単純マクロ
# 機 能 形 式 動 作
1 バイトメモリ 転送 ?MOVB BMem1, BMem2 [BMem1] ← [BMem2]
2 ワードメモリ 転送 ?MOVW WMem1, WMem2 [WMem1] ← [WMem2]
3 ロングワードメモリ 転送 ?MOVL DMem1, DMem2 [DMem1] ← [DMem2]
4 バイトメモリ 比較 ?CMPB BMem1, BMem2 [BMem1] : [BMem2]
5 ワードメモリ 比較 ?CMPW WMem1, WMem2 [WMem1] : [WMem2]
6 ロングワードメモリ 比較 ?CMPL DMem1, DMem2 [DMem1] : [DMem2]
7 ロングワードメモリ ゼロチェック ?CMPZ DMem [Dmem ] : 0
8 ロングワードメモリ ロード ?LD DMem DX,AX ← [DMem ]
9 ロングワードメモリ ストアー ?ST DMem [DMem ] ← DX,AX
10 ロングワード ゼロロード ?LDZ DX,AX ← 0
11 ロングワード ゼロストアー ?STZ DMem [DMem ] ← 0
12 ロングワード 比較 ?CMPM DMem DX,AX : [DMem ]
13 ロングワード 定数比較 ?CMPI ImmH, ImmL DX,AX : Immh,ImmL
14 バイトポート出力 ?OUT WAdr, BDat WAdr ← BDat
15 ワードポート出力 ?OUTW WAdr, WDat WAdr ← WDat
16 バイトポート入力 ?IN BDat, WAdr BDat ← WAdr
17 ワードポート入力 ?INW WDat, WAdr WDat ← WAdr
18 マルチレジスタ プッシュ $_push <R1 [,R2]... [,Rn] > R1~Rnの順にPUSH
19 マルチレジスタ ポップ $_pop <[Rn,] ... [R2,] R1 > Rn~R1の順にPOP
7.2. 構造化プログラミングマクロ
7.2.1. 初期設定 - $_init
形 式 $_init <構造化マクロの展開オプション>,<ユーザマクロの展開オプション>
説 明 構造化プログラミングマクロ用の初期設定(アセンブリ変数の初期化)を行います。
構造化マクロの展開オプション、および、ユーザマクロの展開オプションは、アセンブルリスト出力時、マクロ展開形の
リスティング形式( OFF / ON / ALL )を指定します。
OFF:展開結果をリスティングしない
ON :実行命令だけマクロ展開結果をリスティングする
ALL:非実行命令も含め、全てのマクロ展開結果をリスティングする
マクロ「$_init」は、ソースプログラムの先頭で1度だけ記述します。
記述例 INCLUDE X_SPMAC.INC
$_init OFF,OFF
i8086/MS-DOS リアルタイム・マルチタスクOS
39
7.2.2. 二分岐ブロック - $_if ~ $_else ~ $_endif
$_if 条件指定1
[$_c 条件指定2 ]
・・・
[$_c 条件指定n]
条件成立時の処理
$_else
条件不成立時の処理
$_endif
7.2.3. 繰り返し(前条件)ブロック - $_while ~ $_enddo
$_while 条件指定1[,ブロック名]
[$_c 条件指定2 ] 「$_while TRUE」と記述した場合は、無限ループとなる
・・・
[$_c 条件指定n]
条件成立中の間、繰り返し実行する処理
$_enddo
7.2.4. 繰り返し(後条件)ブロック - $_do ~ $_until
$_do [ブロック名]
条件不成立中の間(条件が成立するまで)繰り返す処理。但し、最初の1回は必ず実行される。
$_until 条件指定1
[$_c 条件指定2 ] 条件指定を省略した場合は、ブロックを1度だけ実行する
・・・ 条件指定に次のものを指定した場合は、指定した命令そのものを展開する
[$_c 条件指定n] LOOP, LOOPNE, LOOPE, LOOPZ or LOOPNZ
i8086/MS-DOS リアルタイム・マルチタスクOS
40
7.2.5. 選択ブロック - $_switch ~ $_case ~ $_endswitch
$_switch [ブロック名]
$_case 条件指定1―1
[$_c 条件指定1-2]
・・・
[$_c 条件指定1-n]
条件1成立時の処理
[$_break [ブロック名] ] ・・・(※1)
$_case 条件指定2―1
[$_c 条件指定2-2]
・・・
[$_c 条件指定2-n]
条件2成立時の処理
[$_break [ブロック名] ] ・・・(※1)
・
・ (条件3以降について同上)
・
$_default
いずれの条件も不成立時の処理
$_endswitch
※1:「$_break」を記述しない場合は、直下の「$_case」が評価されるか、あるいは、「$_default」の部分が実行されます。
7.2.6. ブロックからの抜け出し - $_break
$_breakマクロにより、処理ブロックからの抜け出しが可能です。
ブロック名を省略した場合は、当該ネストレベルの処理ブロックを抜けます。
ブロック名を指定した場合は、同一ブロック名が指定されている、上位ネストレベルの $_while, $_do, or $_switch 処理ブロックを抜けます。
$_break [ブロック名]
i8086/MS-DOS リアルタイム・マルチタスクOS
41
7.2.7. 条件指定
条件指定は、次の形式で指定します。
<[命令行]> : 条件判断に先だって、実行する命令行を指定します。実行する命令が無い場合は、「< >」と記述します。
命令行は、マクロ記述も可能です。
比較演算子 : 以下のものが指定可能です。(ジャンプ命令(Jxx)のxxの部分)
A, AE, B, BE, C, E, G, GE, L, LE, NA, NAE, NB, NBE, NC, NE, NG, NGE, NL, NLE, NO, NP, NS, NZ, O, P, PE, PO, S, Z
論理演算子 : 複合条件を指定する場合、条件指定間の論理関係を指定します。
「AND」および「OR」が指定可能です。(ANDの方が高優先度となります)
7.2.8. ブロック間のオブジェクトが128バイト以上となる場合
処理ブロック内のオブジェクトサイズが128バイト以上となる(アセンブルエラーとなる)場合は、当該処理ブロックのマクロ名の後ろにアンダライン( _ )を
付加して下さい。
(例) $_if_ <CMP AX,0>,E
・
・
・
128バイト以上のオブジェクト
・
・
・
$_endif_
<[命令行]>,比較演算子[ ,論理演算子]
i8086/MS-DOS リアルタイム・マルチタスクOS
42
7.2.9. 記述例
$_if <CMP AL, ’0’>,AE,AND$_c <CMP AL, ’9’>,BE,OR$_c <CMP AL, ’A’>,AE,AND$_c <CMP AL, ’F’>,BE,OR$_c <CMP AL, ’a’>,AE,AND$_c <CMP AL, ’f’>,BE ・
・
・
AL=16進文字(‘0’~‘9’, ‘A’~‘F’ あるいは ‘a’~‘f’)である場合の処理
・
・
・
$_else
・
・
・
AL≠16進文字である場合の命令群
・
・
・
$_endif
$_do
・・・
$_if <CALL SUB>,C
$_break
$_endif
・・・
$_until <CMP SI,100>,B
$_while <CMP AX,0>,E,,MAIN_LOOP
・・・
$_do
・・・
$_if <CMP DH,80h>,E
$_break MAIN_LOOP
$_endif
・・・
$_until LOOP
・・・
$_enddo
DH=80hの場合、
$_while~$_enddo ブロックを抜けます
サブルーチン(SUB)実行後、CF=1である場合、
$_do~$_until ブロックを抜けます
SI<100となるまでループします。
但し、初回は必ず実行します。
AX=0である間、ループします。
最初からAX≠0である場合は、1回も
実行しません。