; ; TOPPERS/SSP Kernel ; Smallest Set Profile Kernel ; ; Copyright (C) 2014 by Naoki Saito ; Nagoya Municipal Industrial Research Institute, JAPAN ; ; 上記著作権者は,以下の (1)〜(4) の条件を満たす場合に限り,本ソフトウェ ; ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改変・ ; 再配布(以下,利用と呼ぶ)することを無償で許諾する. ; (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作権 ; 表示,この利用条件および下記の無保証規定が,そのままの形でソース ; コード中に含まれていること. ; (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使用 ; できる形で再配布する場合には,再配布に伴うドキュメント(利用者マ ; ニュアルなど)に,上記の著作権表示,この利用条件および下記の無保 ; 証規定を掲載すること. ; (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使用 ; できない形で再配布する場合には,次のいずれかの条件を満たすこと. ; (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著作 ; 権表示,この利用条件および下記の無保証規定を掲載すること. ; (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに報 ; 告すること. ; (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損害 ; からも,上記著作権者およびTOPPERSプロジェクトを免責すること.また, ; 本ソフトウェアのユーザまたはエンドユーザからのいかなる理由に基づ ; く請求からも,上記著作権者およびTOPPERSプロジェクトを免責すること. ; ; 本ソフトウェアは,無保証で提供されているものである.上記著作権者およ ; びTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的に対す ; る適合性も含めて,いかなる保証も行わない.また,本ソフトウェアの利用 ; により直接的または間接的に生じたいかなる損害に関しても,その責任を負 ; わない. ; ; ; ; カーネル実装のプロセッサ依存部分 ; ; ; マクロ定義のインクルード ; $INCLUDE(prc_support_def.inc) ; ; グローバルシンボル ; ; コンパイラが使用する saddr領域のレジスタ extrn _@RTARG0,_@RTARG2,_@RTARG4,_@RTARG6,_@SEGAX,_@SEGDE extrn _@NRARG0,_@NRARG1,_@NRARG2,_@NRARG3 extrn _@NRAT00,_@NRAT02,_@NRAT04,_@NRAT06 ; kernel_cfg.c extrn __kernel_istkpt ; スタックポインタの初期値 ; prc_config.c extrn _t_lock_cpu ; CPUロック状態への移行 extrn __kernel_intnest ; 割込みのネストカウンタ extrn __kernel_lock_flag ; CPUロックフラグ ; task.c extrn __kernel_dispatcher ; ディスパッチャ extrn __kernel_reqflg ; ディスパッチ要求フラグ extrn __kernel_disdsp ; ディスパッチ禁止状態 extrn __kernel_search_schedtsk ; 最高優先度のサーチ extrn __kernel_run_task ; タスクの開始 ; startup.c extrn __kernel_exit_kernel ; カーネルの終了処理 ; prc_support.asm public __kernel_start_dispatch ; ディスパッチの開始処理 public __kernel_call_exit_kernel ; 終了処理のコール public __kernel_interrupt_entry ; 割込みの入口処理(共通部) public __kernel_int_return ; レジスタを復帰して割込み発生元へリターン public _unused_interrupt ; 未使用割込みの処理 ; ; コンパイラで使用するsaddr領域のレジスタを保存 ; restore_saddr_regs macro $if (ALLOC_REGVAR_TO_SADDR) ; -qr オプションを使用する場合 pop ax ; レジスタ復帰 movw _@NRAT06, ax ; pop ax ; movw _@NRAT04, ax ; pop ax ; movw _@NRAT02, ax ; pop ax ; movw _@NRAT00, ax ; pop ax ; movw _@NRARG3, ax ; pop ax ; movw _@NRARG2, ax ; pop ax ; movw _@NRARG1, ax ; pop ax ; movw _@NRARG0, ax ; $endif pop ax ; レジスタ復帰 movw _@SEGDE, ax ; pop ax ; movw _@SEGAX, ax ; pop ax ; movw _@RTARG6, ax ; pop ax ; movw _@RTARG4, ax ; pop ax ; movw _@RTARG2, ax ; pop ax ; movw _@RTARG0, ax ; endm ; ; スタックポインタを初期化 ; reset_sp macro movw de, #__kernel_istkpt mov es, #00H movw ax, es:[de] movw sp, ax endm ; ; PSW の ISP1 = 1, ISP0 = 1 にして割込みのマスクを解除する ; clear_pswisp_mask macro mov a, psw and a, #0f9h or a, #06h ; PSW.ISP{1,0}=(1,1) mov psw, a endm @@CODE CSEG BASE ; ; カーネルの動作開始に必要とされる後始末を行うための関数 ; sta_ker(startup.c) から呼び出される. ; __kernel_start_dispatch: ; ; CPUロック状態と全割込みロック状態とを区別する必要がある場合, ; CPUロック状態にし,全割込みロック相当の状態を解除する. ; call !!_t_lock_cpu $_IF (TMIN_INTPRI_EQU_MINUS4) clear_pswisp_mask $ELSE ei $ENDIF ; ; スタックポインタを初期化する ; sta_ker から start_dispatch の関数コールによるスタック消費分を ; クリアするため,スタックポインタを初期化する. ; reset_sp ; ; dispatcher (task.c) へジャンプする ; 関数コールにしないのはスタックを節約するため. ; ; dispatcher (kernel/task.c) の呼び出し br !!__kernel_dispatcher ; ; 終了処理の呼び出し ; スタックポインタを初期化し,exit_kernel を呼び出す. ; __kernel_call_exit_kernel: reset_sp br __kernel_exit_kernel @@BASE CSEG BASE ; ; 割込み/CPU例外の出入口処理(共通部) ; カーネル管理の割込みまたはCPU例外の場合にレジスタ保存後,呼び出される. ; ; 前提条件 ; ・PSWレジスタのIEビット=0, ISPは受付けた割込みのISP. ; ・ハンドラのアドレスが bc に格納されている. ; ・CPU例外ハンドラの入口から来た場合,スタックポインタの ; 先頭番地(p_excinf)が ax に格納されており, ; これはCPU例外ハンドラの引数(p_excinf)としてそのまま渡される. ; ; レジスタがスタック上にどのように保存されているかを以下に示す. ; 図は並び順のみを表現したものであり,サイズを考慮していないことに注意する. ; 正確にはデータシートを参照のこと. ; この図では上が低位, 下が高位のアドレスで, スタックは図の下側から ; 上方向に向かって積み上げられるものとする. ; ; ※1 saddr領域のワークエリアはコンパイラオプション -qr を指定する場合に ; 保存が必要であり,通常は保存しない.保存する場合はアセンブラオプション ; にて「ALLOC_REGVAR_TO_SADDR」を定義すること. ; ; ※2 CPU例外の入口を経由した場合のみ保存される ; ; ; ---------------<-- p_excinf(※) ; | saddr領域 | ; |ワーク用エリア| ; | (16byte)※1 | ; ---------------<-- p_excinf ; | saddr領域 | ; |セグメント情報| ; | 格納用エリア | ; | (4byte) | ; --------------- ; | saddr領域 | ; | ランタイム | ; | 引数エリア | ; | (8byte) | ; --------------- ; | ES,CS(2byte) | ; --------------- ; | HL(2byte) | ; --------------- ; | DE(2byte) | ; --------------- ; | BC(2byte) | ; --------------- ; | AX(2byte) | ; --------------- ; | PC(2byte) | ; --------------- ; | PSW(1byte) | ; --------------- ; ; ハンドラからリターンした後は, 多重割込みでなく, かつ, ; reqflg が TRUE,かつ,disdsp が FALSE の時に,interrupt_dispatch へ分岐する. ; ; 多重割込みかどうかは割込みネストカウンタの値で判定する. ; intnest > 0 ならば多重割込みであると判定する. ; __kernel_interrupt_entry: inc !__kernel_intnest ; ネストカウンタをインクリメント ei ; 割込み許可(IPLは受け付けられた割込みのレベル) call bc ; 割込みハンドラ呼び出し di ; 割込み禁止 dec !__kernel_intnest ; ネストカウンタをデクリメント bnz $__kernel_int_return ; 戻り先が非タスクコンテキスト(非ゼロ)なら単にリターン movw ax,!__kernel_reqflg ; ディスパッチ要求があるかどうか cmpw ax, #0 bz $__kernel_int_return ; なければ,単にリターン movw ax, #0 movw !__kernel_reqflg, ax ; reqflg = FALSE に戻しておく movw ax, !__kernel_disdsp ; ディスパッチ禁止かどうか cmpw ax, #0 bnz $__kernel_int_return ; 禁止なら,単にリターン ; ; 割込みの出口処理(ディスパッチ付き) ; CPU ロック相当の状態に移行し,新規タスクを開始する ; ; 前提条件: ; PSWレジスタのIEフラグ = 0 (割込み禁止) ; PSWレジスタのISP{1,0} = 受け付けた割込みの割込みレベル ; __kernel_interrupt_dispatch: call !!_t_lock_cpu $_IF (TMIN_INTPRI_EQU_MINUS4) clear_pswisp_mask $ELSE ei $ENDIF call !!__kernel_search_schedtsk movw ax, bc call !!__kernel_run_task ; run_task からのリターン後の状態: CPUロック状態 ; __kernel_int_return の reti で PSW の IE, ISP は ; 割込み発生前の状態に戻るため,lock_flag だけ元に戻す. movw ax, #0 movw !__kernel_lock_flag, ax ; lock_flag をクリア ; ; レジスタ復帰して割込みからリターン ; __kernel_int_return: restore_saddr_regs ; saddr領域のレジスタ復帰 pop ax ; ES, CS の復帰 mov cs, a ; mov a, x ; mov es, a ; pop hl ; レジスタを復帰 pop de pop bc pop ax reti ; ; 無限ループ(念のため) ; _loop: br $_loop ; ; 未使用割込み ; _unused_interrupt: reti end