$ $ 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: interrupt.tf 480 2016-01-03 07:37:12Z ertl-hiro $ $ $ $ 割込み管理機能のテンプレートファイル $ $ $ kernel_cfg.hの生成 $ $FILE "kernel_cfg.h.new"$ #define TNUM_ISRID $LENGTH(ISR.ID_LIST)$$NL$ $FOREACH id ISR.ID_LIST$ #define $id$ $+id$$NL$ $END$ $ $ kernel_cfg.cの生成 $ $FILE "kernel_cfg.c"$ /*$NL$ $SPC$* Interrupt Management Functions$NL$ $SPC$*/$NL$ $NL$ $ $ トレースログマクロのデフォルト定義 $ #ifndef LOG_ISR_ENTER$NL$ #define LOG_ISR_ENTER(isrid)$NL$ #endif /* LOG_ISR_ENTER */$NL$ $NL$ #ifndef LOG_ISR_LEAVE$NL$ #define LOG_ISR_LEAVE(isrid)$NL$ #endif /* LOG_ISR_LEAVE */$NL$ $NL$ $ $ CRE_ISRで使用できる割込み番号とそれに対応する割込みハンドラ番号のデフォ $ ルト定義 $ $IF !LENGTH(INTNO_CREISR_VALID)$ $INTNO_CREISR_VALID = INTNO_VALID$ $END$ $IF !LENGTH(INHNO_CREISR_VALID)$ $INHNO_CREISR_VALID = INHNO_VALID$ $END$ $ $ CFG_INTで使用できる割込み優先度のデフォルト定義 $ $IF !LENGTH(INTPRI_CFGINT_VALID)$ $INTPRI_CFGINT_VALID = RANGE(TMIN_INTPRI, TMAX_INTPRI)$ $END$ $ $ 割込み番号と割込みハンドラ番号の変換テーブルの作成 $ $IF LENGTH(INTNO_CREISR_VALID) != LENGTH(INHNO_CREISR_VALID)$ $ERROR$length of `INTNO_CREISR_VALID' is different from length of `INHNO_CREISR_VALID'$END$ $END$ $i = 0$ $FOREACH intno INTNO_CREISR_VALID$ $inhno = AT(INHNO_CREISR_VALID, i)$ $INHNO[intno] = inhno$ $INTNO[inhno] = intno$ $i = i + 1$ $END$ $ $ 割込み要求ラインに関するエラーチェック $ $ INTNO_LIST:処理済みの割込み番号のリスト(ここでのみ使用) $ $FOREACH intno INT.ORDER_LIST$ $ // intnoが割込み番号として正しくない場合(E_PAR)[NGKI2972] $IF !LENGTH(FIND(INTNO_VALID, INT.INTNO[intno]))$ $ERROR INT.TEXT_LINE[intno]$E_PAR:$SPC$ $FORMAT(_("illegal %1% `%2%\' in %3%"), "intno", INT.INTNO[intno], "CFG_INT")$ $END$ $END$ $ // intnoがCFG_INTによって設定済みの場合(E_OBJ)[NGKI2976] $IF LENGTH(FIND(INTNO_LIST, INT.INTNO[intno]))$ $ERROR INT.TEXT_LINE[intno]$E_OBJ:$SPC$ $FORMAT(_("%1% `%2%\' in %3% is duplicated"), "intno", INT.INTNO[intno], "CFG_INT")$ $END$ $END$ $ // intatrが無効の場合(E_RSATR)[NGKI2969] $ //(TA_ENAINT,TA_EDGE,TARGET_INTATR以外のビットがセットされている場合) $IF (INT.INTATR[intno] & ~(TA_ENAINT|TA_EDGE|TARGET_INTATR)) != 0$ $ERROR INT.TEXT_LINE[intno]$E_RSATR:$SPC$ $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "intatr", INT.INTATR[intno], "intno", INT.INTNO[intno], "CFG_INT")$ $END$ $END$ $ // intpriがCFG_INTに対する割込み優先度として正しくない場合(E_PAR) $ // [NGKI2973] $IF !LENGTH(FIND(INTPRI_CFGINT_VALID, INT.INTPRI[intno]))$ $ERROR INT.TEXT_LINE[intno]$E_PAR:$SPC$ $FORMAT(_("illegal %1% `%2%\' in %3%"), "intpri", INT.INTPRI[intno], "CFG_INT")$ $END$ $END$ $ // カーネル管理外に固定されているintnoに対して,intpriにTMIN_INTPRI $ // よりも小さい値が指定されなかった場合(E_OBJ)[NGKI2983] $IF LENGTH(FIND(INTNO_FIX_NONKERNEL, intno))$ $IF INT.INTPRI[intno] >= TMIN_INTPRI$ $ERROR INT.TEXT_LINE[intno]$E_OBJ:$SPC$ $FORMAT(_("%1% `%2%\' must have higher priority than %3%"), "intno", INT.INTNO[intno], "TMIN_INTPRI")$ $END$ $END$ $END$ $ // カーネル管理に固定されているintnoに対して,intpriにTMIN_INTPRI $ // よりも小さい値が指定された場合(E_OBJ)[NGKI2984] $IF LENGTH(FIND(INTNO_FIX_KERNEL, intno))$ $IF INT.INTPRI[intno] < TMIN_INTPRI$ $ERROR INT.TEXT_LINE[intno]$E_OBJ:$SPC$ $FORMAT(_("%1% `%2%\' must not have higher priority than %3%"), "intno", INT.INTNO[intno], "TMIN_INTPRI")$ $END$ $END$ $END$ $INTNO_LIST = APPEND(INTNO_LIST, INT.INTNO[intno])$ $END$ $ $ 割込みハンドラに関するエラーチェック $ $ INHNO_LIST:処理済みの割込みハンドラ番号のリスト(ここでのみ使用) $ $FOREACH inhno INH.ORDER_LIST$ $ // inhnoが割込みハンドラ番号として正しくない場合(E_PAR)[NGKI3055] $IF !LENGTH(FIND(INHNO_VALID, INH.INHNO[inhno]))$ $ERROR INH.TEXT_LINE[inhno]$E_PAR:$SPC$ $FORMAT(_("illegal %1% `%2%\' in %3%"), "inhno", INH.INHNO[inhno], "DEF_INH")$ $END$ $END$ $ // inhnoがDEF_INHによって設定済みの場合(E_OBJ)[NGKI3063] $IF LENGTH(FIND(INHNO_LIST, INH.INHNO[inhno]))$ $ERROR INH.TEXT_LINE[inhno]$E_OBJ:$SPC$ $FORMAT(_("%1% `%2%\' in %3% is duplicated"), "inhno", INH.INHNO[inhno], "DEF_INH")$ $END$ $END$ $ // inhatrが無効の場合(E_RSATR)[NGKI3052] $ //(TARGET_INHATR以外のビットがセットされている場合) $IF (INH.INHATR[inhno] & ~TARGET_INHATR) != 0$ $ERROR INH.TEXT_LINE[inhno]$E_RSATR:$SPC$ $FORMAT(_("illegal %1% `%2%\' of %3% `%4%\' in %5%"), "inhatr", INH.INHATR[inhno], "inhno", INH.INHNO[inhno], "DEF_INH")$ $END$ $END$ $ // カーネル管理外に固定されているinhnoに対して,inhatrにTA_NONKERNEL $ // が指定されていない場合(E_RSATR)[NGKI3067] $IF LENGTH(FIND(INHNO_FIX_NONKERNEL, inhno))$ $IF (INH.INHATR[inhno] & TA_NONKERNEL) == 0$ $ERROR INH.TEXT_LINE[inhno]$E_RSATR:$SPC$ $FORMAT(_("%1% `%2%\' must be non-kernel interrupt"), "inhno", INH.INHNO[inhno])$ $END$ $END$ $END$ $ // カーネル管理に固定されているinhnoに対して,inhatrにTA_NONKERNEL $ // が指定されている場合(E_RSATR)[NGKI3068] $IF LENGTH(FIND(INHNO_FIX_KERNEL, inhno))$ $IF (INH.INHATR[inhno] & TA_NONKERNEL) != 0$ $ERROR INH.TEXT_LINE[inhno]$E_RSATR:$SPC$ $FORMAT(_("%1% `%2%\' must not be non-kernel interrupt"), "inhno", INH.INHNO[inhno])$ $END$ $END$ $END$ $IF LENGTH(INTNO[INH.INHNO[inhno]])$ $intno = INTNO[INH.INHNO[inhno]]$ $ // inhnoに対応するintnoに対するCFG_INTがない場合(E_OBJ)[NGKI3062] $IF !LENGTH(INT.INTNO[intno])$ $ERROR INH.TEXT_LINE[inhno]$E_OBJ:$SPC$ $FORMAT(_("%1% `%2%\' corresponding to %3% `%4%\' is not configured with %5%"), "intno", intno, "inhno", INH.INHNO[inhno], "CFG_INT")$ $END$ $ELSE$ $IF (INH.INHATR[inhno] & TA_NONKERNEL) == 0$ $ // inhatrにTA_NONKERNELが指定されておらず,inhnoに対応 $ // するintnoに対してCFG_INTで設定された割込み優先度が $ // TMIN_INTPRIよりも小さい場合(E_OBJ)[NGKI3065] $IF INT.INTPRI[intno] < TMIN_INTPRI$ $ERROR INT.TEXT_LINE[intno]$E_OBJ:$SPC$ $FORMAT(_("%1% `%2%\' configured for %3% `%4%\' is higher than %5%"), "intpri", INT.INTPRI[intno], "inhno", INH.INHNO[inhno], "TMIN_INTPRI")$ $END$ $END$ $ELSE$ $ // inhatrにTA_NONKERNELが指定されており,inhnoに対応 $ // するintnoに対してCFG_INTで設定された割込み優先度が $ // TMIN_INTPRI以上である場合(E_OBJ)[NGKI3066] $IF INT.INTPRI[intno] >= TMIN_INTPRI$ $ERROR INT.TEXT_LINE[intno]$E_OBJ:$SPC$ $FORMAT(_("%1% `%2%\' configured for %3% `%4%\' is lower than or equal to %5%"), "intpri", INT.INTPRI[intno], "inhno", INH.INHNO[inhno], "TMIN_INTPRI")$ $END$ $END$ $END$ $END$ $END$ $INHNO_LIST = APPEND(INHNO_LIST, INH.INHNO[inhno])$ $END$ $ $ 割込みサービスルーチン(ISR)に関するエラーチェックと割込みハンドラの生成 $ $FOREACH id ISR.ID_LIST$ $ // isratrが無効の場合(E_RSATR)[NGKI2998] $ //(TARGET_ISRATR以外のビットがセットされている場合) $IF (ISR.ISRATR[id] & ~TARGET_ISRATR) != 0$ $ERROR ISR.TEXT_LINE[id]$E_RSATR:$SPC$ $FORMAT(_("illegal %1% `%2%\' in %3%"), "isratr", ISR.ISRATR[id], "CRE_ISR")$ $END$ $END$ $ // intnoがCRE_ISRに対する割込み番号として正しくない場合(E_PAR) $ // [NGKI3003] $IF !LENGTH(FIND(INTNO_CREISR_VALID, ISR.INTNO[id]))$ $ERROR ISR.TEXT_LINE[id]$E_PAR:$SPC$ $FORMAT(_("illegal %1% `%2%\' in %3%"), "intno", ISR.INTNO[id], "CRE_ISR")$ $END$ $END$ $ // (TMIN_ISRPRI <= isrpri && isrpri <= TMAX_ISRPRI)でない場合(E_PAR) $ // [NGKI3005] $IF !(TMIN_ISRPRI <= ISR.ISRPRI[id] && ISR.ISRPRI[id] <= TMAX_ISRPRI)$ $ERROR ISR.TEXT_LINE[id]$E_PAR:$SPC$ $FORMAT(_("illegal %1% `%2%\' in %3%"), "isrpri", ISR.ISRPRI[id], "CRE_ISR")$ $END$ $END$ $END$ $FOREACH intno INTNO_CREISR_VALID$ $inhno = INHNO[intno]$ $ // 割込み番号intnoに対して登録されたISRのリストの作成 $isrid_list = {}$ $FOREACH id ISR.ID_LIST$ $IF ISR.INTNO[id] == intno$ $isrid_list = APPEND(isrid_list, id)$ $id_for_error = id$ $END$ $END$ $ // 割込み番号intnoに対して登録されたISRが存在する場合 $IF LENGTH(isrid_list) > 0$ $ // intnoに対応するinhnoに対してDEF_INHがある場合(E_OBJ)[NGKI3013] $IF LENGTH(INH.INHNO[inhno])$ $ERROR ISR.TEXT_LINE[id_for_error]$E_OBJ:$SPC$ $FORMAT(_("%1% `%2%\' in %3% is duplicated with %4% `%5%\'"), "intno", ISR.INTNO[id_for_error], "CRE_ISR", "inhno", INH.INHNO[inhno])$ $END$ $END$ $ // intnoに対するCFG_INTがない場合(E_OBJ)[NGKI3012] $IF !LENGTH(INT.INTNO[intno])$ $ERROR ISR.TEXT_LINE[id_for_error]$E_OBJ:$SPC$ $FORMAT(_("%1% `%2%\' is not configured with %3%"), "intno", ISR.INTNO[id_for_error], "CFG_INT")$ $END$ $ELSE$ $ // intnoに対してCFG_INTで設定された割込み優先度がTMIN_INTPRI $ // よりも小さい場合(E_OBJ)[NGKI3014] $IF INT.INTPRI[intno] < TMIN_INTPRI$ $ERROR INT.TEXT_LINE[intno]$E_OBJ:$SPC$ $FORMAT(_("%1% `%2%\' configured for %3% `%4%\' is higher than %5%"), "intpri", INT.INTPRI[intno], "intno", ISR.INTNO[id_for_error], "TMIN_INTPRI")$ $END$ $END$ $END$ $ // DEF_INH(inhno, { TA_NULL, _kernel_inthdr_ } ); $INH.INHNO[inhno] = inhno$ $INH.INHATR[inhno] = VALUE("TA_NULL", 0)$ $INH.INTHDR[inhno] = CONCAT("_kernel_inthdr_", intno)$ $INH.ORDER_LIST = APPEND(INH.ORDER_LIST, inhno)$ $ // ISR用の割込みハンドラ void$NL$ _kernel_inthdr_$intno$(void)$NL$ {$NL$ $ // ISRを優先度順に呼び出す $JOINEACH id SORT(isrid_list, "ISR.ISRPRI") "\n\tif (sense_lock()) {\n\t\tunlock_cpu();\n\t}\n\n"$ $TAB$LOG_ISR_ENTER($ISR.ISRID[id]$);$NL$ $TAB$((ISR)($ISR.ISR[id]$))((intptr_t)($ISR.EXINF[id]$));$NL$ $TAB$LOG_ISR_LEAVE($ISR.ISRID[id]$);$NL$ $END$ }$NL$ $END$ $END$ $NL$ $ $ 割込みハンドラのための標準的な初期化情報の生成 $ $IF !OMIT_INITIALIZE_INTERRUPT || USE_INHINIB_TABLE$ $ $ 定義する割込みハンドラの数 $ #define TNUM_DEF_INHNO $LENGTH(INH.ORDER_LIST)$$NL$ const uint_t _kernel_tnum_def_inhno = TNUM_DEF_INHNO;$NL$ $NL$ $ $ 割込みハンドラのエントリ $ $FOREACH inhno INH.ORDER_LIST$ $IF (INH.INHATR[inhno] & TA_NONKERNEL) == 0$ INTHDR_ENTRY($INH.INHNO[inhno]$, $+INH.INHNO[inhno]$,$SPC$ $INH.INTHDR[inhno]$)$NL$ $END$ $END$$NL$ $ $ 割込みハンドラ初期化ブロック $ $IF LENGTH(INH.ORDER_LIST)$ const INHINIB _kernel_inhinib_table[TNUM_DEF_INHNO] = {$NL$ $JOINEACH inhno INH.ORDER_LIST ",\n"$ $TAB${$SPC$ ($INH.INHNO[inhno]$),$SPC$ ($INH.INHATR[inhno]$),$SPC$ $IF (INH.INHATR[inhno] & TA_NONKERNEL) == 0$ (FP)(INT_ENTRY($INH.INHNO[inhno]$, $INH.INTHDR[inhno]$)) $ELSE$ (FP)($INH.INTHDR[inhno]$) $END$$SPC$ }$END$$NL$ };$NL$ $ELSE$ TOPPERS_EMPTY_LABEL(const INHINIB, _kernel_inhinib_table);$NL$ $END$$NL$ $END$ $ $ 割込み要求ラインのための標準的な初期化情報の生成 $ $IF !OMIT_INITIALIZE_INTERRUPT || USE_INTINIB_TABLE$ $ $ 設定する割込み要求ラインの数 $ #define TNUM_CFG_INTNO $LENGTH(INT.ORDER_LIST)$$NL$ const uint_t _kernel_tnum_cfg_intno = TNUM_CFG_INTNO;$NL$ $NL$ $ $ 割込み要求ライン初期化ブロック $ $IF LENGTH(INT.ORDER_LIST)$ const INTINIB _kernel_intinib_table[TNUM_CFG_INTNO] = {$NL$ $JOINEACH intno INT.ORDER_LIST ",\n"$ $TAB${$SPC$ ($INT.INTNO[intno]$),$SPC$ ($INT.INTATR[intno]$),$SPC$ ($INT.INTPRI[intno]$)$SPC$ }$END$$NL$ };$NL$ $ELSE$ TOPPERS_EMPTY_LABEL(const INTINIB, _kernel_intinib_table);$NL$ $END$$NL$ $END$ $ $ 割込み管理機能初期化関数 $ $initfuncs = APPEND(initfuncs, "_kernel_initialize_interrupt();")$