/* * TOPPERS ATK2 * Toyohashi Open Platform for Embedded Real-Time Systems * Automotive Kernel Version 2 * * Copyright (C) 2000-2003 by Embedded and Real-Time Systems Laboratory * Toyohashi Univ. of Technology, JAPAN * Copyright (C) 2004-2015 by Center for Embedded Computing Systems * Graduate School of Information Science, Nagoya Univ., JAPAN * Copyright (C) 2011-2015 by FUJI SOFT INCORPORATED, JAPAN * Copyright (C) 2011-2013 by Spansion LLC, USA * Copyright (C) 2011-2015 by NEC Communication Systems, Ltd., JAPAN * Copyright (C) 2011-2015 by Panasonic Advanced Technology Development Co., Ltd., JAPAN * Copyright (C) 2011-2014 by Renesas Electronics Corporation, JAPAN * Copyright (C) 2011-2015 by Sunny Giken Inc., JAPAN * Copyright (C) 2011-2015 by TOSHIBA CORPORATION, JAPAN * Copyright (C) 2004-2015 by Witz Corporation * Copyright (C) 2014-2015 by AISIN COMCRUISE Co., Ltd., JAPAN * Copyright (C) 2014-2015 by eSOL Co.,Ltd., JAPAN * Copyright (C) 2014-2015 by SCSK Corporation, JAPAN * * 上記著作権者は,以下の(1)〜(4)の条件を満たす場合に限り,本ソフトウェ * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー * スコード中に含まれていること. * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 * の無保証規定を掲載すること. * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ * と. * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 * 作権表示,この利用条件および下記の無保証規定を掲載すること. * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに * 報告すること. * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを * 免責すること. * * 本ソフトウェアは,AUTOSAR(AUTomotive Open System ARchitecture)仕 * 様に基づいている.上記の許諾は,AUTOSARの知的財産権を許諾するもので * はない.AUTOSARは,AUTOSAR仕様に基づいたソフトウェアを商用目的で利 * 用する者に対して,AUTOSARパートナーになることを求めている. * * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ * の責任を負わない. * * $Id: osctl.c 187 2015-06-25 03:39:04Z t_ishikawa $ */ /* * OS制御モジュール */ #include "kernel_impl.h" #include "interrupt.h" #include "task.h" /* * トレースログマクロのデフォルト定義 */ #ifndef LOG_ERRHOOK_ENTER #define LOG_ERRHOOK_ENTER(ercd) #endif /* LOG_ERRHOOK_ENTER */ #ifndef LOG_ERRHOOK_LEAVE #define LOG_ERRHOOK_LEAVE() #endif /* LOG_ERRHOOK_LEAVE */ #ifndef LOG_ERRHOOKOSAP_ENTER #define LOG_ERRHOOKOSAP_ENTER(p_runosap, ercd) #endif /* LOG_ERRHOOKOSAP_ENTER */ #ifndef LOG_ERRHOOKOSAP_LEAVE #define LOG_ERRHOOKOSAP_LEAVE(p_runosap) #endif /* LOG_ERRHOOKOSAP_LEAVE */ #ifndef LOG_PROHOOK_ENTER #define LOG_PROHOOK_ENTER(ercd) #endif /* LOG_PROHOOK_ENTER */ #ifndef LOG_PROHOOK_LEAVE #define LOG_PROHOOK_LEAVE(pret) #endif /* LOG_PROHOOK_LEAVE */ #ifndef LOG_SHUTHOOK_ENTER #define LOG_SHUTHOOK_ENTER(ercd) #endif /* LOG_SHUTHOOK_ENTER */ #ifndef LOG_SHUTHOOK_LEAVE #define LOG_SHUTHOOK_LEAVE() #endif /* LOG_SHUTHOOK_LEAVE */ #ifndef LOG_SHUTHOOKOSAP_ENTER #define LOG_SHUTHOOKOSAP_ENTER(index, ercd) #endif /* LOG_SHUTHOOKOSAP_ENTER */ #ifndef LOG_SHUTHOOKOSAP_LEAVE #define LOG_SHUTHOOKOSAP_LEAVE(index) #endif /* LOG_SHUTHOOKOSAP_LEAVE */ #ifndef LOG_STUTOS_ENTER #define LOG_STUTOS_ENTER(ercd) #endif /* LOG_STUTOS_ENTER */ #ifndef LOG_STUTOS_LEAVE #define LOG_STUTOS_LEAVE() #endif /* LOG_STUTOS_LEAVE */ #ifdef CFG_USE_ERRORHOOK /* * エラーフックに渡す情報を格納する変数 */ #ifdef TOPPERS_internal_call_errorhook #ifdef CFG_USE_GETSERVICEID DEFINE_VAR_SEC_NOBITS(OSServiceIdType, _errorhook_svcid, ".srpw_bss_kernel"); #endif /* CFG_USE_GETSERVICEID */ #ifdef CFG_USE_PARAMETERACCESS _ErrorHook_Par _errorhook_par1; _ErrorHook_Par _errorhook_par2; _ErrorHook_Par _errorhook_par3; DEFINE_VAR_SEC_NOBITS(_ErrorHook_Par, errorhook_par1, ".srpw_bss_kernel"); DEFINE_VAR_SEC_NOBITS(_ErrorHook_Par, errorhook_par2, ".srpw_bss_kernel"); DEFINE_VAR_SEC_NOBITS(_ErrorHook_Par, errorhook_par3, ".srpw_bss_kernel"); #endif /* CFG_USE_PARAMETERACCESS */ /* * エラーフックの呼び出し */ void internal_call_errorhook(StatusType ercd, OSServiceIdType svcid) { void (*volatile errorhook_adr) (StatusType Error); uint8 saved_sus_all_cnt_ctx; uint8 saved_sus_os_cnt_ctx; boolean saved_run_trusted = run_trusted; saved_sus_all_cnt_ctx = sus_all_cnt_ctx; saved_sus_os_cnt_ctx = sus_os_cnt_ctx; sus_all_cnt_ctx = 0U; sus_os_cnt_ctx = 0U; #ifdef CFG_USE_SYSTEM_ERRORHOOK /* * C言語の規格では関数のアドレスは0にならないという前提から, * コンパイラの最適化によりErrorHookのアドレス判定分岐が * 削除されてしまう場合があるため, volatile指定したローカル変数に * アドレスを代入してから判定している */ errorhook_adr = &ErrorHook; if (errorhook_adr != NULL) { if ((callevel_stat & (TCL_ERROR | TSYS_ISR1)) == TCL_NULL) { #ifdef CFG_USE_GETSERVICEID _errorhook_svcid = svcid; #endif /* CFG_USE_GETSERVICEID */ #ifdef CFG_USE_PARAMETERACCESS errorhook_par1 = _errorhook_par1; errorhook_par2 = _errorhook_par2; errorhook_par3 = _errorhook_par3; #endif /* CFG_USE_PARAMETERACCESS */ ENTER_CALLEVEL(TCL_SYS_ERROR); run_trusted = TRUE; LOG_ERRHOOK_ENTER(ercd); ErrorHook(ercd); LOG_ERRHOOK_LEAVE(); LEAVE_CALLEVEL(TCL_SYS_ERROR); release_interrupts(OSServiceId_HookMissingEnd); } } #endif /* CFG_USE_SYSTEM_ERRORHOOK */ #ifdef CFG_USE_OSAP_ERRORHOOK /* OSアプリケーション定義のエラーフック呼出し */ errorhook_adr = NULL; if (p_runosap != NULL) { errorhook_adr = p_runosap->p_osapinib->ErrorHook; } if (errorhook_adr != NULL) { if ((callevel_stat & (TCL_ERROR | TSYS_ISR1)) == TCL_NULL) { #ifdef CFG_USE_GETSERVICEID _errorhook_svcid = svcid; #endif /* CFG_USE_GETSERVICEID */ #ifdef CFG_USE_PARAMETERACCESS errorhook_par1 = _errorhook_par1; errorhook_par2 = _errorhook_par2; errorhook_par3 = _errorhook_par3; #endif /* CFG_USE_PARAMETERACCESS */ ENTER_CALLEVEL(TCL_OSAP_ERROR); LOG_ERRHOOKOSAP_ENTER(p_runosap, ercd); if (p_runosap->p_osapinib->osap_trusted != FALSE) { run_trusted = TRUE; errorhook_adr(ercd); } else { run_trusted = FALSE; call_nontrusted_hook((void *) errorhook_adr, ercd, ERROR_HOOK); } LOG_ERRHOOKOSAP_LEAVE(p_runosap); LEAVE_CALLEVEL(TCL_OSAP_ERROR); release_interrupts(OSServiceId_HookMissingEnd); } } #endif /* CFG_USE_OSAP_ERRORHOOK */ sus_all_cnt_ctx = saved_sus_all_cnt_ctx; sus_os_cnt_ctx = saved_sus_os_cnt_ctx; run_trusted = saved_run_trusted; } #endif /* TOPPERS_internal_call_errorhook */ #endif /* CFG_USE_ERRORHOOK */ #ifdef CFG_USE_POSTTASKHOOK /* * ポストタスクフックの呼び出し */ #ifdef TOPPERS_call_posttaskhook void call_posttaskhook(void) { boolean saved_run_trusted; ENTER_CALLEVEL(TCL_PREPOST); saved_run_trusted = run_trusted; run_trusted = TRUE; PostTaskHook(); run_trusted = saved_run_trusted; LEAVE_CALLEVEL(TCL_PREPOST); release_interrupts(OSServiceId_HookMissingEnd); } #endif /* TOPPERS_call_posttaskhook */ #endif /* CFG_USE_POSTTASKHOOK */ #ifdef CFG_USE_PRETASKHOOK /* * プレタスクフックの呼び出し */ #ifdef TOPPERS_call_pretaskhook void call_pretaskhook(void) { boolean saved_run_trusted; ENTER_CALLEVEL(TCL_PREPOST); saved_run_trusted = run_trusted; run_trusted = TRUE; PreTaskHook(); run_trusted = saved_run_trusted; LEAVE_CALLEVEL(TCL_PREPOST); release_interrupts(OSServiceId_HookMissingEnd); } #endif /* TOPPERS_call_pretaskhook */ #endif /* CFG_USE_PRETASKHOOK */ #ifdef CFG_USE_STACKMONITORING #ifdef TOPPERS_init_stack_magic_region /* * スタックモニタリング機能の初期化 * スタックモニタリング機能のためのマジックナンバー領域の初期化 */ void init_stack_magic_region(void) { StackType *p_stack_magic_region; /* * スタックモニタリング機能のため,スタック成長方向考慮した * 非タスクスタックのマジックナンバー領域の初期化 */ p_stack_magic_region = TOPPERS_ISTK_MAGIC_REGION(_ostk, _ostksz); *p_stack_magic_region = STACK_MAGIC_NUMBER; } #endif /* TOPPERS_init_stack_magic_region */ #endif /* CFG_USE_STACKMONITORING */ /* * シャットダウンフックの強制終了 */ #ifdef TOPPERS_cancel_shutdown_hook void cancel_shutdown_hook(void) { if (is_running_nontrusted_shtdwnhk() != FALSE) { /* 非信頼フックの強制終了 */ exit_nontrusted_hook(); } else { /* 信頼フックの強制終了 */ exit_trusted_shutdown_hook(); } ASSERT(0); } #endif /* TOPPERS_cancel_shutdown_hook */ /* * 処理レベルチェック付きのOSシャットダウン * プロテクションフックの呼び出し処理から呼ばれる * シャットダウンフック実行中に発生した場合, * シャットダウンフックをキャンセルして後続シャット * ダウン処理を続ける * */ #ifdef TOPPERS_callevel_chk_shutdown void callevel_chk_shutdown(StatusType ercd) { if ((callevel_stat & TCL_SHUTDOWN) != TCL_NULL) { if (((callevel_stat & TCL_OSAP_SHUTDOWN) != TCL_NULL) && (p_runosap != NULL)) { p_runosap->osap_stat = APPLICATION_TERMINATED; } cancel_shutdown_hook(); } else { internal_shutdownos(ercd); } } #endif /* TOPPERS_callevel_chk_shutdown */ /* * プロテクションフックの呼び出し * 引数の最上位ビットは,呼び出し箇所を示す役割がある */ #ifdef TOPPERS_call_protectionhk_main void call_protectionhk_main(StatusType peob_ercd) { StatusType protection_error = peob_ercd & (~PROTECTION_ERROR_OPTIONAL_BIT); #ifdef CFG_USE_PROTECTIONHOOK boolean saved_run_trusted; ProtectionReturnType pret; ProtectionReturnType (*volatile protectionhook_adr) (StatusType FatalError); uint8 saved_sus_all_cnt_ctx; uint8 saved_sus_os_cnt_ctx; /* プロテクションフック実行中に保護違反が発生した場合 */ if ((callevel_stat & TCL_PROTECT) == TCL_PROTECT) { callevel_chk_shutdown(E_OS_PROTECTION_FATAL); } /* * C言語の規格では関数のアドレスは0にならないという前提から, * コンパイラの最適化によりProtectionHookのアドレス判定分岐が * 削除されてしまう場合があるため, volatile指定したローカル変数に * アドレスを代入してから判定している */ protectionhook_adr = &ProtectionHook; /* 以下 システム定義のプロテクションフックを呼出す処理 */ if (protectionhook_adr != NULL) { saved_sus_all_cnt_ctx = sus_all_cnt_ctx; saved_sus_os_cnt_ctx = sus_os_cnt_ctx; sus_all_cnt_ctx = 0U; sus_os_cnt_ctx = 0U; ENTER_CALLEVEL(TCL_PROTECT); saved_run_trusted = run_trusted; run_trusted = TRUE; LOG_PROHOOK_ENTER(protection_error); pret = protectionhook_adr(protection_error); LOG_PROHOOK_LEAVE(pret); run_trusted = saved_run_trusted; LEAVE_CALLEVEL(TCL_PROTECT); release_interrupts(OSServiceId_HookMissingEnd); sus_all_cnt_ctx = saved_sus_all_cnt_ctx; sus_os_cnt_ctx = saved_sus_os_cnt_ctx; /* 以下 ProtectionHook 実行後の処理 */ switch (pret) { case PRO_SHUTDOWN: callevel_chk_shutdown(protection_error); break; case PRO_TERMINATETASKISR: if ((callevel_stat & TCL_SHUTDOWN) != TCL_NULL) { if (((callevel_stat & TCL_OSAP_SHUTDOWN) != TCL_NULL) && (p_runosap != NULL)) { p_runosap->osap_stat = APPLICATION_TERMINATED; } cancel_shutdown_hook(); } if ((callevel_stat & TSYS_ISR1) != TSYS_NULL) { internal_shutdownos(E_OS_PROTECTION_FATAL); } if ((callevel_stat & (TCL_STARTUP | TCL_ERROR | TCL_PREPOST)) != TCL_NULL) { /* スタートアップフック実行中はシャットダウン */ internal_shutdownos(E_OS_PROTECTION_FATAL); } if (p_runisr != NULL) { /* 機能レベル2ではC2ISR実行中はシャットダウン */ internal_shutdownos(E_OS_PROTECTION_FATAL); } else if ((p_runtsk != NULL) && (p_runtsk->calltfn == FALSE)) { /* タスクの場合 */ force_terminate_task(p_runtsk, peob_ercd, FALSE); /* * ディスパッチャ,割込み入口処理でのスタックモニタリング * の場合は,ここに戻るが,それ以外の場合ここに戻らない */ } else { /* 機能レベル2でタスク,C2ISRが存在しない場合 */ internal_shutdownos(E_OS_PROTECTION_FATAL); } break; case PRO_IGNORE: if (protection_error != E_OS_PROTECTION_EXCEPTION) { callevel_chk_shutdown(E_OS_PROTECTION_FATAL); } break; case PRO_TERMINATEAPPL: if ((callevel_stat & TCL_SHUTDOWN) != TCL_NULL) { if (((callevel_stat & TCL_OSAP_SHUTDOWN) != TCL_NULL) && (p_runosap != NULL)) { p_runosap->osap_stat = APPLICATION_TERMINATED; } cancel_shutdown_hook(); } if ((callevel_stat & TSYS_ISR1) != TSYS_NULL) { internal_shutdownos(E_OS_PROTECTION_FATAL); } if ((callevel_stat & (TCL_SYS_STARTUP | TCL_SYS_ERROR | TCL_PREPOST)) != TCL_NULL) { internal_shutdownos(E_OS_PROTECTION_FATAL); } if ((p_runosap == NULL) || (run_trusted != FALSE)) { internal_shutdownos(E_OS_PROTECTION_FATAL); } else { internal_term_osap(p_runosap, NO_RESTART); } break; case PRO_TERMINATEAPPL_RESTART: if ((callevel_stat & TCL_SHUTDOWN) != TCL_NULL) { if (((callevel_stat & TCL_OSAP_SHUTDOWN) != TCL_NULL) && (p_runosap != NULL)) { p_runosap->osap_stat = APPLICATION_TERMINATED; } cancel_shutdown_hook(); } if ((callevel_stat & TSYS_ISR1) != TSYS_NULL) { internal_shutdownos(E_OS_PROTECTION_FATAL); } if ((callevel_stat & (TCL_STARTUP | TCL_SYS_ERROR | TCL_PREPOST)) != TCL_NULL) { internal_shutdownos(E_OS_PROTECTION_FATAL); } if ((p_runosap == NULL) || (run_trusted != FALSE)) { internal_shutdownos(E_OS_PROTECTION_FATAL); } else { internal_term_osap(p_runosap, RESTART); } break; default: /* ProtectionHookから不正な値が返った場合 */ callevel_chk_shutdown(E_OS_PROTECTION_FATAL); break; } } else { callevel_chk_shutdown(protection_error); } #else /* CFG_USE_PROTECTIONHOOK */ /* * プロテクションフックがコンフィギュレーション時に無効と * されている場合,OSは保護違反時処理としてOSシャットダウンを * 行う * このとき,OSシャットダウンのパラメータとして, * 違反の区別を示すエラーコードを指定する */ callevel_chk_shutdown(protection_error); #endif /* CFG_USE_PROTECTIONHOOK */ } #endif /* TOPPERS_call_protectionhk_main */ /* * OS内部からのShutdownOSの呼び出し */ #ifdef TOPPERS_internal_shutdownos void internal_shutdownos(StatusType ercd) { LOG_STUTOS_ENTER(ercd); x_nested_lock_os_int(); #ifdef CFG_USE_SHUTDOWNHOOK call_shutdownhook(ercd); #endif /* CFG_USE_SHUTDOWNHOOK */ /* 各モジュールの終了処理 */ object_terminate(); /* 全割込み禁止状態に移行 */ x_lock_all_int(); LOG_STUTOS_LEAVE(); /* ターゲット依存の終了処理 */ target_exit(); /* * ターゲット依存部から処理が返ってきた場合, * 無限ループを行う */ while (1) { } } #endif /* TOPPERS_internal_shutdownos */ #ifdef TOPPERS_internal_call_shtdwnhk #ifdef CFG_USE_SHUTDOWNHOOK void internal_call_shtdwnhk(StatusType ercd) { void (*volatile shutdownhook_adr) (StatusType Error); #ifdef CFG_USE_OSAP_SHUTDOWNHOOK ApplicationType i; #endif /* CFG_USE_OSAP_SHUTDOWNHOOK */ /* * シャットダウンフック中のシャットダウンではシャットダウンフック * は呼び出さない */ if ((callevel_stat & TCL_SHUTDOWN) == TCL_NULL) { sus_all_cnt_ctx = 0U; sus_os_cnt_ctx = 0U; #ifdef CFG_USE_OSAP_SHUTDOWNHOOK /* * OSアプリケーション定義のShutdownHook呼出し * * OSアプリケーション初期化ブロックに設定されたエントリが * NULLでなければ実行する */ for (i = 0U; i < tnum_osap; i++) { shutdownhook_adr = osapinib_table[i].ShutdownHook; p_runosap = &(osapcb_table[i]); if ((shutdownhook_adr != NULL) && (p_runosap->osap_stat == APPLICATION_ACCESSIBLE)) { ENTER_CALLEVEL(TCL_OSAP_SHUTDOWN); LOG_SHUTHOOKOSAP_ENTER(i, ercd); if (p_runosap->p_osapinib->osap_trusted != FALSE) { run_trusted = TRUE; call_trusted_hook((void *) shutdownhook_adr, ercd); } else { run_trusted = FALSE; call_nontrusted_hook((void *) shutdownhook_adr, ercd, SHUTDOWN_HOOK); } LOG_SHUTHOOKOSAP_LEAVE(i); LEAVE_CALLEVEL(TCL_OSAP_SHUTDOWN); release_interrupts(OSServiceId_HookMissingEnd); } } #endif /* CFG_USE_OSAP_SHUTDOWNHOOK */ #ifdef CFG_USE_SYSTEM_SHUTDOWNHOOK p_runosap = NULL; /* * ShutdownHook の呼び出し * * C言語の規格では関数のアドレスは0にならないという前提から, * コンパイラの最適化によりShutdownHookのアドレス判定分岐が * 削除されてしまう場合があるため, volatile指定したローカル変数に * アドレスを代入してから判定している */ shutdownhook_adr = &ShutdownHook; if (shutdownhook_adr != NULL) { ENTER_CALLEVEL(TCL_SYS_SHUTDOWN); run_trusted = TRUE; LOG_SHUTHOOK_ENTER(ercd); call_trusted_hook((void *) &ShutdownHook, ercd); LOG_SHUTHOOK_LEAVE(); LEAVE_CALLEVEL(TCL_SYS_SHUTDOWN); release_interrupts(OSServiceId_HookMissingEnd); } #endif /* CFG_USE_SYSTEM_SHUTDOWNHOOK */ } } #endif /* CFG_USE_SHUTDOWNHOOK */ #endif /* TOPPERS_internal_call_shtdwnhk */