$ $ TOPPERS/ASP Kernel $ Toyohashi Open Platform for Embedded Real-Time Systems/ $ Advanced Standard Profile Kernel $ $ Copyright (C) 2007 by TAKAGI Nobuhisa $ Copyright (C) 2007-2015 by Embedded and Real-Time Systems Laboratory $ Graduate School of Information Science, Nagoya Univ., JAPAN $ $ 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ $ ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 $ 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. $ (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 $ 権表示,この利用条件および下記の無保証規定が,そのままの形でソー $ スコード中に含まれていること. $ (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 $ 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 $ 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 $ の無保証規定を掲載すること. $ (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 $ 用できない形で再配布する場合には,次のいずれかの条件を満たすこ $ と. $ (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 $ 作権表示,この利用条件および下記の無保証規定を掲載すること. $ (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに $ 報告すること. $ (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 $ 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. $ また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 $ 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを $ 免責すること. $ $ 本ソフトウェアは,無保証で提供されているものである.上記著作権者お $ よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 $ に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ $ アの利用により直接的または間接的に生じたいかなる損害に関しても,そ $ の責任を負わない. $ $ $Id: kernel.tf 480 2016-01-03 07:37:12Z ertl-hiro $ $ $ $ コンフィギュレータのパス2のテンプレートファイル $ $ $ kernel_cfg.hの先頭部分の生成 $ $FILE "kernel_cfg.h.new"$ /* kernel_cfg.h */$NL$ #ifndef TOPPERS_KERNEL_CFG_H$NL$ #define TOPPERS_KERNEL_CFG_H$NL$ $ $ kernel_cfg.cの先頭部分の生成 $ $FILE "kernel_cfg.c"$ /* kernel_cfg.c */$NL$ #include "kernel/kernel_int.h"$NL$ #include "kernel_cfg.h"$NL$ $NL$ #if !(TKERNEL_PRID == 0x0007U && (TKERNEL_PRVER & 0xf000U) == 0x3000U)$NL$ #error The kernel does not match this configuration file.$NL$ #endif$NL$ $NL$ $ $ インクルードディレクティブ(#include) $ /*$NL$ $SPC$* Include Directives (#include)$NL$ $SPC$*/$NL$ $NL$ $INCLUDES$ $NL$ $ $ スタック領域の確保関数 $ $IF !ISFUNCTION("ALLOC_STACK")$ $FUNCTION ALLOC_STACK$ $ // 大きい方に丸めたサイズで確保する[NGKI1050][NGKI3220] static STK_T $ARGV[1]$[COUNT_STK_T($ARGV[2]$)];$NL$ $RESULT = FORMAT("ROUND_STK_T(%1%)", ARGV[2])$ $END$ $END$ $ $ 通知ハンドラの生成関数 $ $FUNCTION GENERATE_NFYHDR$ $ // パラメータを変数に格納 $nfymode = ARGV[1]$ $nfymode1 = nfymode & 0x0f$ $nfymode2 = nfymode & ~0x0f$ $par1 = ARGV[2]$ $par2 = ARGV[3]$ $text_line = ARGV[6]$ $objid = ARGV[7]$ $apiname = ARGV[8]$ $ // 通知処理のパラメータ数による補正処理 $IF nfymode == TNFY_HANDLER || nfymode1 == TNFY_SETVAR || nfymode1 == TNFY_SETFLG || nfymode1 == TNFY_SNDDTQ$ $ // 通知処理のパラメータが2つの場合 $numpar = 2$ $epar1 = ARGV[4]$ $epar2 = ARGV[5]$ $ELSE$ $ // 通知処理のパラメータが1つの場合 $numpar = 1$ $epar1 = ARGV[3]$ $epar2 = ARGV[4]$ $END$ $ // パラメータ数のチェック $IF (numpar == 2 && !LENGTH(par2)) || (nfymode2 != 0 && !LENGTH(epar1)) || (nfymode2 == TENFY_SETFLG && !LENGTH(epar2))$ $ // パラメータが足りない場合 $ERROR text_line$ $FORMAT(_("too few parameters for %1% `%2%\' of `%3%\' in %4%"), "nfymode", nfymode, objid, apiname)$ $END$ $ELIF (nfymode2 == 0 && LENGTH(epar1)) || (nfymode2 != TENFY_SETFLG && LENGTH(epar2))$ $ // パラメータが多すぎる場合 $ERROR text_line$ $FORMAT(_("too many parameters for %1% `%2%\' of `%3%\' in %4%"), "nfymode", nfymode, objid, apiname)$ $END$ $ELIF nfymode == TNFY_HANDLER$ $ // タイムイベントハンドラの呼出し $funcname = FORMAT("(NFYHDR)(%s)", par2)$ $ELSE$ $ // 通知ハンドラの関数名 $funcname = CONCAT("_kernel_nfyhdr_", objid)$ $ // エラー通知のための変数のアドレスとオブジェクトIDを格納する $ // 変数の生成(エラーチェックのために必要) $IF nfymode2 == TENFY_SETVAR || nfymode2 == TENFY_INCVAR$ intptr_t *const $funcname$_p_evar = $SPC$(intptr_t *)($epar1$);$NL$$NL$ $ELIF nfymode2 == TENFY_ACTTSK || nfymode2 == TENFY_WUPTSK$ const ID $funcname$_etskid = $epar1$;$NL$$NL$ $ELIF nfymode2 == TENFY_SIGSEM$ const ID $funcname$_esemid = $epar1$;$NL$$NL$ $ELIF nfymode2 == TENFY_SETFLG$ const ID $funcname$_eflgid = $epar1$;$NL$$NL$ $ELIF nfymode2 == TENFY_SNDDTQ$ const ID $funcname$_edtqid = $epar1$;$NL$$NL$ $END$ $ // 関数の先頭部分の生成 static void$NL$ $funcname$(intptr_t exinf)$NL$ {$NL$ $IF nfymode2 == 0$ $ // エラー通知がない場合 $error_code = "(void) "$ $ELSE$ $ // エラー通知がある場合 $TAB$ER ercd;$NL$ $NL$ $error_code = "ercd = "$ $END$ $ // イベント通知処理の処理 $IF nfymode1 == TNFY_SETVAR && nfymode2 == 0$ $ // 変数の設定 $TAB$*((intptr_t *) exinf) = ($par2$);$NL$ $ELIF nfymode1 == TNFY_INCVAR && nfymode2 == 0$ $ // 変数のインクリメント $TAB$*((intptr_t *) exinf) += 1;$NL$ $ELIF nfymode1 == TNFY_ACTTSK$ $ // タスクの起動 $TAB$$error_code$act_tsk((ID) exinf);$NL$ $ELIF nfymode1 == TNFY_WUPTSK$ $ // タスクの起床 $TAB$$error_code$wup_tsk((ID) exinf);$NL$ $ELIF nfymode1 == TNFY_SIGSEM$ $ // セマフォの返却 $TAB$$error_code$sig_sem((ID) exinf);$NL$ $ELIF nfymode1 == TNFY_SETFLG$ $ // イベントフラグのセット $TAB$$error_code$set_flg(((ID) exinf), $par2$);$NL$ $ELIF nfymode1 == TNFY_SNDDTQ$ $ // データキューへの送信 $TAB$$error_code$psnd_dtq(((ID) exinf), $par2$);$NL$ $ELSE$ $ERROR text_line$E_PAR:$SPC$ $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "nfymode", nfymode, objid, apiname)$ $END$ $END$ $IF nfymode2 != 0$ $ // エラー通知処理の処理 $TAB$if (ercd != E_OK) {$NL$ $IF nfymode2 == TENFY_SETVAR$ $ // 変数の設定 $TAB$$TAB$*$funcname$_p_evar = (intptr_t) ercd;$NL$ $ELIF nfymode2 == TENFY_INCVAR$ $ // 変数のインクリメント $TAB$$TAB$*$funcname$_p_evar += 1;$NL$ $ELIF nfymode2 == TENFY_ACTTSK$ $ // タスクの起動 $TAB$$TAB$(void) act_tsk($funcname$_etskid);$NL$ $ELIF nfymode2 == TENFY_WUPTSK$ $ // タスクの起床 $TAB$$TAB$(void) wup_tsk($funcname$_etskid);$NL$ $ELIF nfymode2 == TENFY_SIGSEM$ $ // セマフォの返却 $TAB$$TAB$(void) sig_sem($funcname$_esemid);$NL$ $ELIF nfymode2 == TENFY_SETFLG$ $ // イベントフラグのセット $TAB$$TAB$(void) set_flg($funcname$_eflgid, $epar2$);$NL$ $ELIF nfymode2 == TENFY_SNDDTQ$ $ // データキューへの送信 $TAB$$TAB$(void) psnd_dtq ($funcname$_edtqid, (intptr_t) ercd);$NL$ $ELSE$ $ERROR text_line$E_PAR:$SPC$ $FORMAT(_("illegal %1% `%2%\' of `%3%\' in %4%"), "nfymode", nfymode, objid, apiname)$ $END$ $END$ $TAB$}$NL$ $END$ $ // 関数の末尾部分の生成 }$NL$ $NL$ $END$ $RESULT = funcname$ $END$ $ $ 各機能モジュールのコンフィギュレーション $ $INCLUDE "kernel/task.tf"$ $INCLUDE "kernel/semaphore.tf"$ $INCLUDE "kernel/eventflag.tf"$ $INCLUDE "kernel/dataqueue.tf"$ $INCLUDE "kernel/pridataq.tf"$ $INCLUDE "kernel/mutex.tf"$ $INCLUDE "kernel/mempfix.tf"$ $INCLUDE "kernel/cyclic.tf"$ $INCLUDE "kernel/alarm.tf"$ $INCLUDE "kernel/overrun.tf"$ $INCLUDE "kernel/interrupt.tf"$ $INCLUDE "kernel/exception.tf"$ $ $ 非タスクコンテキスト用のスタック領域 $ /*$NL$ $SPC$* Stack Area for Non-task Context$NL$ $SPC$*/$NL$ $NL$ $IF !LENGTH(ICS.ORDER_LIST)$ $ // DEF_ICSがない場合のデフォルト値の設定 #ifdef DEFAULT_ISTK$NL$ $NL$ #define TOPPERS_ISTKSZ DEFAULT_ISTKSZ$NL$ #define TOPPERS_ISTK DEFAULT_ISTK$NL$ $NL$ #else /* DEAULT_ISTK */$NL$ $NL$ $istksz = ALLOC_STACK("_kernel_istack", "DEFAULT_ISTKSZ")$$NL$ #define TOPPERS_ISTKSZ $istksz$$NL$ #define TOPPERS_ISTK _kernel_istack$NL$ $NL$ #endif /* DEAULT_ISTK */$NL$ $ELSE$ $ // 静的API「DEF_ICS」が複数ある(E_OBJ)[NGKI3216] $IF LENGTH(ICS.ORDER_LIST) > 1$ $ERROR$E_OBJ: $FORMAT(_("too many %1%"), "DEF_ICS")$$END$ $END$ $ // istkszが0以下か,ターゲット定義の最小値(TARGET_MIN_ISTKSZ)よりも $ // 小さい場合(E_PAR)[NGKI3254] $IF ICS.ISTKSZ[1] <= 0 || (TARGET_MIN_ISTKSZ && ICS.ISTKSZ[1] < TARGET_MIN_ISTKSZ)$ $ERROR ICS.TEXT_LINE[1]$E_PAR:$SPC$ $FORMAT(_("too small %1% `%2%\' in %3%"), "istksz", ICS.ISTKSZ[1], "DEF_ICS")$ $END$ $END$ $ // istkszがスタック領域のサイズとして正しくない場合(E_PAR)[NGKI3222] $IF !EQ(ICS.ISTK[1], "NULL") && CHECK_STKSZ_ALIGN && (ICS.ISTKSZ[1] & (CHECK_STKSZ_ALIGN - 1))$ $ERROR ICS.TEXT_LINE[1]$E_PAR:$SPC$ $FORMAT(_("%1% `%2%\' in %3% is not aligned"), "istksz", ICS.ISTKSZ[1], "DEF_ICS")$ $END$ $END$ $IF EQ(ICS.ISTK[1], "NULL")$ $ // スタック領域の自動割付け $istksz = ALLOC_STACK("_kernel_istack", ICS.ISTKSZ[1])$$NL$ #define TOPPERS_ISTKSZ $istksz$$NL$ #define TOPPERS_ISTK _kernel_istack$NL$ $ELSE$ #define TOPPERS_ISTKSZ ($ICS.ISTKSZ[1]$)$NL$ #define TOPPERS_ISTK (void *)($ICS.ISTK[1]$)$NL$ $END$ $END$ $NL$ $ 非タスクコンテキスト用のスタック領域 const size_t _kernel_istksz = TOPPERS_ISTKSZ;$NL$ STK_T *const _kernel_istk = TOPPERS_ISTK;$NL$ $NL$ #ifdef TOPPERS_ISTKPT$NL$ STK_T *const _kernel_istkpt = TOPPERS_ISTKPT(TOPPERS_ISTK, TOPPERS_ISTKSZ);$NL$ #endif /* TOPPERS_ISTKPT */$NL$ $NL$ $ $ タイムイベント管理 $ /*$NL$ $SPC$* Time Event Management$NL$ $SPC$*/$NL$ $NL$ TMEVTN _kernel_tmevt_heap[1 + TNUM_TSKID + TNUM_CYCID + TNUM_ALMID];$NL$ $NL$ $ $ 各モジュールの初期化関数 $ /*$NL$ $SPC$* Module Initialization Function$NL$ $SPC$*/$NL$ $NL$ void$NL$ _kernel_initialize_object(void)$NL$ {$NL$ $FOREACH func (initfuncs)$ $TAB$$func$$NL$ $END$ }$NL$ $NL$ $ $ 初期化ルーチンの実行関数 $ /*$NL$ $SPC$* Initialization Routine$NL$ $SPC$*/$NL$ $NL$ void$NL$ _kernel_call_inirtn(void)$NL$ {$NL$ $FOREACH order INI.ORDER_LIST$ $ // iniatrが無効の場合(E_RSATR)[NGKI3241] $ //(TA_NULLでない場合) $IF INI.INIATR[order] != 0$ $ERROR INI.TEXT_LINE[order]$E_RSATR:$SPC$ $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "iniatr", INI.INIATR[order], "inirtn", INI.INIRTN[order], "ATT_INI")$ $END$ $END$ $TAB$((INIRTN)($INI.INIRTN[order]$))((intptr_t)($INI.EXINF[order]$));$NL$ $END$ }$NL$ $NL$ $ $ 終了処理ルーチンの実行関数 $ /*$NL$ $SPC$* Termination Routine$NL$ $SPC$*/$NL$ $NL$ void$NL$ _kernel_call_terrtn(void)$NL$ {$NL$ $FOREACH rorder TER.RORDER_LIST$ $ // teratrが無効の場合(E_RSATR)[NGKI3248] $ //(TA_NULLでない場合) $IF TER.TERATR[rorder] != 0$ $ERROR TER.TEXT_LINE[rorder]$E_RSATR:$SPC$ $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "teratr", TER.TERATR[rorder], "terrtn", TER.TERRTN[rorder], "ATT_TER")$ $END$ $END$ $TAB$((TERRTN)($TER.TERRTN[rorder]$))((intptr_t)($TER.EXINF[rorder]$));$NL$ $END$ }$NL$ $NL$ $ $ kernel_cfg.hの末尾部分の生成 $ $FILE "kernel_cfg.h.new"$ #endif /* TOPPERS_KERNEL_CFG_H */$NL$