/*****************************************************************************/
/* リアルタイム・マルチタスクカーネル 「ai-TRON」*/
/* Copyright (C) 2000 by 今井彰彦 */
/*****************************************************************************/
/* スタック設定 */
/* この中のＣルーチンは毎回＝ROSを使うプログラム毎にコンパイルされる */

#ifndef	__ROSSTK__
#define __ROSSTK__	1

/*****************************************************************************/
/* 新旧バージョン互換のため */

#ifdef STACKOLD
/* #define STACKOLD として、定数名の後ろに_を付ける */
	#define	SYSSTSIZE	(SYSSTSIZE_*sizeof(UB *))
	#define	TIMSTSIZE	(TIMSTSIZE_*sizeof(UB *))
	#if ROS_CYC_ALL	== ROS_ON
		#define	CYCSTSIZE	(CYCSTSIZE_*sizeof(UB *))
	#endif
	#define	USRSTSIZE	(USRSTSIZE_*sizeof(UB *))
#endif

/*****************************************************************************/

/* スタック設定チェック */
/* 各設定がないとコンパイルエラーが出る */
#ifndef	SYSSTSIZE
#error	"SYSSTSIZEが設定されていません"
#endif
#ifndef	TIMSTSIZE
#error	"TIMSTSIZEが設定されていません"
#endif
#if ROS_CYC_ALL	== ROS_ON
#ifndef	CYCSTSIZE
#error	"CYCSTSIZEが設定されていません"
#endif
#endif
#ifndef	USRSTSIZE
#error	"USRSTSIZEが設定されていません"
#endif

/*****************************************************************************/

/* 一時記憶用ワーク */
#ifdef __7900_
/* 以下の定義をkernels.c/ros79.mac内で行うので書き替えた時はそちらも変更すること */
#define	AOFST_DRP0	0			/* [0,1]=drp0 */
#define	AOFST_EXEC	(AOFST_DRP0+2)		/* [2〜]=&MyTsk->exec */
#define	AOFST_STACK	(AOFST_EXEC+4)		/* [6〜]=&MyTsk->stack */
#define	AOFST_RET	(AOFST_STACK+4)		/* [10〜]=&MyTsk->ret */
*/
#define	WRKSTSIZE	(AOFST_RET+4)	/* ﾀﾞｲﾚｸﾄ･ｲﾝﾀﾞｲﾚｸﾄﾛﾝｸﾞｱﾄﾞﾚｯｼﾝｸﾞ計算用 */
#else
#define	WRKSTSIZE	0
#endif

/* 全スタックサイズ */
#if ROS_CYC_ALL	== ROS_ON
#define	ALLSTSIZE	(WRKSTSIZE+SYSSTSIZE+TIMSTSIZE+CYCSTSIZE+USRSTSIZE)
#else
#define	ALLSTSIZE	(WRKSTSIZE+SYSSTSIZE+TIMSTSIZE+USRSTSIZE)
#endif

/*****************************************************************************/
/* スタックエリア */

/* 一体で確保して分割する */
/* 確保順
	下位	Wrk	ROSInit()〜ROS()間も使われるので最下位アドレスへ
	 ↑	Sys	ROSInit()〜ROS()間も使われるので最下位アドレス側へ
	 ↑	Tim	ROS()前は未使用
	 ↑	Cyc	ROS()前は未使用
	上位	Usr	初期スタックとしても使われるので最高位アドレスへ
*/

/* アセンブラールーチン内で退避するスタックポインタの型（というよりサイズ）*/
#if defined(__7900__)
typedef	UH	STACKP;		/* 7900 :スタックポインタはページ０固定で１６ビット */
#else
typedef	STACK*	STACKP;
#endif

#ifdef __DOSV__
volatile UH	_StackSS;	/* スタックワークのセグメント */
				/* 設定はＣで、利用はアセンブラーで行う */
				/* スタックは_AllStack_[]と言うワークを分割して割り当てるので、*/
				/* 全てのスタックで同一セグメントを使うと想定している */
#endif

STACK	*_SysStack;		/* システムスタックポインタ */

/* 以下??SpSave(??SSPush)はアセンブラ内でスタックを変更する前のスタックポインタ記録用 */
/* Ｃから参照してはいけない */
volatile STACKP	_SysSpSave;	/* kernel用 */
#ifdef __DOSV__
volatile UH	_SysSSPush;	/* スタックセグメント一時記録用;アセンブラルーチン内で利用 */
#endif
volatile STACKP	_ISysSpSave;	/* isys用 */
#ifdef __DOSV__
volatile UH	_ISysSSPush;	/* スタックセグメント一時記録用;アセンブラルーチン内で利用 */
#endif

STACK	*_TimStack;		/* wai_tskカウントダウン */
volatile STACKP	_TimSpSave;	/* tdcnt用 */
#ifdef __DOSV__
volatile UH	_TimSSPush;	/* スタックセグメント一時記録用;アセンブラルーチン内で利用 */
#endif

#if ROS_CYC_ALL	== ROS_ON
STACK	*_CycStack;		/* 周期起動スタックポインタ */
volatile STACKP	_CycSpSave;	/* tecyc用 */
#ifdef __DOSV__
volatile UH	_CycSSPush;	/* スタックセグメント一時記録用;アセンブラルーチン内で利用 */
#endif
#endif

STACK	*_UsrStack;		/* ユーザースタックポインタ(cre_tskで変化) */
STACK	*_UsrStack0;		/* 初期ユーザースタックポインタ */

/* スタック本体 */
/* いくつかのＣＰＵでは_AllStack_は偶数アドレスからに配置される必要がある */
/* その場合、ここに偶数アドレスに配置されるような#pragma等を書く */
/* そのような#pragmaがなくても、偶数サイズ変数の後であれば偶数アドレスになる確率が高いので
　 後先になるが、ここで確保させる */

#ifdef __7900__
/* 7900はスタックはバンク０固定なので、_AllStack_[]も必ずバンク０内に設定すること */
/* kernel79.a79内からも参照する */
#endif

STACK	_AllStack_[ALLSTSIZE];		/* 全スタック本体 */
					/* マイコン上では単なるアドレスで良い */
					/* STACK *_AllStack_=0x????; */

/*****************************************************************************/

#ifdef __DOSV__
#include <dos.h>	/* FP_SEG() */
#endif

void _SetStack(void)
/* スタック設定 */
{
	/* 設定順は上記の通り */
	
	#ifdef __DOSV__
	_SaveDataSegment(); /* DS記録;Tiny/Smallでは_StackSSと同じなのだが、将来のため分けて記録しておく */
	_StackSS=FP_SEG(_AllStack_);	/* SS記録;スタック領域のセグメントを記録しておく */
	/* AllStack[]を分割して使う＝１つのワークがセグメント境界をまたぐことはないので
	 　全て同一セグメントであると考えて良い。*/
	#endif
	/* システムスタック */
	_SysStack=&_AllStack_[WRKSTSIZE+SYSSTSIZE];

	/* wai_tskカウントダウンスタック */
	_TimStack=&_SysStack[TIMSTSIZE];

	#if ROS_CYC_ALL	== ROS_ON
	_CycStack=&_TimStack[CYCSTSIZE];	/* 周期起動スタック */
	_UsrStack=&_CycStack[USRSTSIZE];	/* ユーザースタック */
	#else
	_UsrStack=&_TimStack[USRSTSIZE];	/* ユーザースタック */
	#endif

	#ifdef __7900__
	/* 7900はスタックがポストデクリメントなので、最終アドレスそのものを与える */
	_UsrStack--;
	_SysStack--;
	_TimStack--;
	#if ROS_CYC_ALL	== ROS_ON
	_CycStack--;
	#endif
	#endif
	
	/* 初期ユーザースタック */
	_UsrStack0=_UsrStack;
	
	#if DEBUG !=0
	/* デバッグ用ルーチン初期化 */
	InitDebug(WRKSTSIZE,SYSSTSIZE,TIMSTSIZE,USRSTSIZE
	#if ROS_CYC_ALL	== ROS_ON
	,CYCSTSIZE
	#endif
	);
	#endif
}

/*****************************************************************************/

#endif

/*****************************************************************************/
