TOPPERS/FMP リリースとの相違点
対応予定の拡張機能
SOLID-OS の FMP カーネルでは、SOLID-OS の ASP3カーネル もしくは FMP3カーネルでサポートしている 以下の拡張機能については、現時点では未サポートですが、今後のアップデートで対応予定です。
タスク起動要求キューイング数/タスク起床要求キューイング数の上限をコンフィグレーション可能
複数プロセッサをターゲットとする割込みの指定が可能
対応している拡張機能
SOLID-OSにおけるカーネルでは以下の点がオリジナルのTOPPERS/FMPと仕様または動作が異なります
カーネル資源の静的な生成方法
SOLID-OSではタスクなどのカーネル資源を生成するために, カーネル起動時に読み込まれるパラメータをC言語のテーブルに 記述しておくことで行います。
ミューテックスのサポート
TOPPERS/FMP3 相当のミューテックスをサポートします。API仕様については、TOPPERS第三世代カーネル統合仕様書に準拠します。
ミューテックスでの優先度継承プロトコルサポート
API仕様については μITRON4.0 仕様に準拠します
割込み及び例外の処理
SOLID-OSにおいてはCPUからの割込み及び例外の処理はCore Serviceの内部で行われます。
割込み処理については関連システムコールはオリジナル実装と同様に動作します。 ただし、kernel_cfg.cの中の設定テーブルに記述されていな割込みについては すべてカーネル管理外の割込みとして扱われます。
例外処理についてはすべてCore Serivceの内部で処理が完結します。 プロセッサ例外時でもカーネルに通知が行われないため、 以下のシステムコールは未実装か、オリジナルのカーネル仕様通りには機能しません。
def_exc
xns_dpn
静的資源カーネルにおいて以下のAPIにおけるパラメータ制限が緩和されています
それぞれ、CRE_DTQ での dtqmp, CRE_PDQ での pdqmb、CRE_MPF での mpfmb に NULL 以外を指定してもエラーになりません。 (動的生成拡張サポートカーネルと同等)。
CRE_DTQ [ASPS0132]
CRE_PDQ [ASPS0142]
CRE_MPF [ASPS0166]
割り込み操作APIの対象割込み番号
以下のAPIについてカーネルに登録された割込み(カーネル管理割込み)以外の割込み番号をパラメータに渡した場合にエラーとなりますが、SOLIDでは指定された割込みについて割り込みコントーラへの操作を試みます
dis_int
ena_int
イベントフラグ待ち解除時のクリア方法指定
イベントフラグがセットされ、待ち状態にあったタスクの待ち状態が解除される際にフラグのビットパターンのビットをクリアする方法を以下の中から選択可能です。
指定なし(クリアしない)
すべてのビットをクリア
待ち対象のビットのみクリア
待ち対象のビットのみクリアする場合はイベントフラグ待ちAPI(wai_flg/pol_flg/twai_flg)のパラメータ 待ちビットパターン(waiptn)で'1'になっているビットがすべてクリアされます。それ以外のビットは変化しません。
クリア方法の指定は資源生成時の属性とイベントフラグ待ちAPI(wai_flg/pol_flg/twai_flg)の待ちモード(wfmode)の両方で指定可能です。両方とも指定されている場合にはAPI呼び出し時のwfmodeが優先されます。
資源生成時の属性
TA_CLR
全ビットクリア
TA_BITCLR
待ち対象ビットのみクリア(追加)
API(wai_flg/pol_flg/twai_flg)の待ちモード(wfmode) [全て追加]
TWF_CLR
全ビットクリア
TWF_BITCLR
待ち対象ビットのみクリア
資源生成時の属性とAPIの待ちモードの組み合わせによる動作
生成時属性
API待ちモード
ビットクリア動作
(指定なし)
(指定なし)
ビットクリアしない
(指定なし)
TWF_CLR
全ビットクリア
(指定なし)
TWF_BITCLR
待ち対象ビットのみクリア
TA_CLR
(指定なし)
全ビットクリア
TA_CLR
TWF_CLR
全ビットクリア
TA_CLR
TWF_BITCLR
待ち対象ビットのみクリア
TA_BITCLR
(指定なし)
待ち対象ビットのみクリア
TA_BITCLR
TWF_CLR
全ビットクリア
TA_BITCLR
TWF_BITCLR
待ち対象ビットのみクリア
非タスクからの ena_int, dis_int 呼び出し可能
ena_int及びdis_intを非タスクコンテキストから呼び出した場合でもコンテキストエラー(E_CTX)を返さずに正常処理を行います。(第三世代カーネルと同等の動作)
タイマーイベントハンドラを各コアで実行可能
グローバルタイマ方式(システムで単一のタイマのみ使用)で動作している場合でも周期通知ハンドラ及びアラーム通知ハンドラをkernel_cfg.cで指定されたプロセッサコア上で実行します。
本機能を使用するためにはビルドするアプリケーションで以下のプロパティを設定してください。
LibMPTimer <- 'global_handler_local' (使用しない場合はLibMPTimerの値をデフォルト値の'global'に設定してください)
Readers/Writerロックのサポート
複数の読み手タスク(Readers)と単一の書き手タスク(Write)の間で排他処理を行うオブジェクト
ビルド方法、インクルードファイル(関数仕様)については以下のファイルを参照してください
rtos/toppers_fmp/fmp_1.4.0/solid_extension/rwlock/Readme.md
[2020.2.27]デッドロック対策として同一タスクが多重にロックを取得しようとした場合の動作を以下の通りに変更しました。
すでに読み手ロックを取得したタスクが再度読み手ロックを取得 -> 成功 (ただしこの場合には取得した回数分だけアンロックを行う必要があります。)
すでに書き手ロックを取得したタスクが再度書き手ロックを取得 -> エラー(E_OBJ)
すでに書き手ロックを取得したタスクが読み手ロックを取得 -> エラー(E_OBJ)
[制限事項]
以下の場合についてはAPIでエラーとはならずにデッドロックが発生する可能性があります。
読み手ロックを取得したタスクが書き手ロックを取得
各プロセッサアイドル時間取得機能
各プロセッサのアイドル時間(タスクも割り込み処理も実行していない時間)の積算値を取得します。
プロセッサアイドル時間取得機能を使用するためにはビルドするアプリケーションで以下のプロパティを設定してください。
LibSKXProcessorStat <- 'true' (有効) or 'false' (無効)
追加されたAPIの関数仕様は以下の通りです。
#include <prcstat.h>
ER pst_ref_idt(T_PIDT *p_pidt);
/*
* 全プロセッサのIDLE時間の参照
*
* <param>
* T_PIDT *p_pidt アイドル時間を格納する構造体のアドレス
*
* <return value>
* (戻り値)正常終了(E_OK)
*
* 全プロセッサのアイドル時間積算値をp_pidtに指定された領域に格納します。
* 積算値はシステム開始またはpst_rst_idt関数でリセットされてからの
* 各プロセッサのアイドル時間であり、単位はマイクロ秒です。
*
* <errors>
* なし
*
*/
#include <prcstat.h>
void pst_rst_idt(void);
/*
* 全プロセッサのIDLE時間のリセット
*
* <param>
* なし
*
* <return value>
* (戻り値)なし
*
* 全プロセッサのアイドル時間積算値を0に初期化します。
*
* <errors>
* なし
*
*/
指定優先度以下の実行待ちタスクの中から最も優先度及び優先順位が高いタスクIDの取得(xsm_get_frt, xsm_iget_frt)
システム管理機能拡張を使用するためにはビルドするアプリケーションで以下のプロパティを設定してください。
LibSKXSysManage <- 'true' (有効) or 'false' (無効)
追加されたAPIの関数仕様は以下の通りです。
#include <kernel.h>
ER xsm_get_frt(PRI tskpri_thresh, ID prcid, ID *p_tskid);
/*
* 指定優先度以下の実行待ちタスクIDの取得
*
* <param>
* PRI tskpri_thresh 閾値となるタスク優先度
* ID prcid 実行可能プロセッサの指定
* ID *p_tskid 結果のタスクIDを格納する変数アドレス
*
* <return value>
* (戻り値)正常終了(E_OK) またはエラーコード(<errors>参照のこと)
*
* 自プロセッサコア上でtskpri_threshで指定された優先度以下の
* 実行待ちタスクを検索し、最初に見つかったタスクIDをp_tskidの指す
* アドレスに格納します。
*
* 指定優先度以下の全ての優先度で実行待ちタスクが見つからない場合は
* p_tskidの指すアドレスにはTSK_NONE(0)が書き込み、戻り値として
* E_OKを返します。
*
* tskpri_threshに実行中のタスクの優先度を表すTPRI_SELFを指定すると
* 呼び出したタスクの優先度を指定優先度として扱います。
*
* <errors>
* E_PAR tskpri_threshの値が範囲外
* E_ID prcidの値が範囲外
* E_CTX 非タスクコンテキストから呼び出された
*
*/
#include <kernel.h>
ER xsm_iget_frt(PRI tskpri_thresh, ID prcid, ID *p_tskid);
/*
* 指定優先度以下の実行待ちタスクIDの取得
*
* <param>
* PRI tskpri_thresh 閾値となるタスク優先度
* ID prcid 実行可能プロセッサの指定
* ID *p_tskid 結果のタスクIDを格納する変数アドレス
*
* <return value>
* (戻り値)正常終了(E_OK) またはエラーコード(<errors>参照のこと)
*
* 自プロセッサコア上でtskpri_threshで指定された優先度以下の
* 実行待ちタスクを検索し、最初に見つかったタスクIDをp_tskidの指す
* アドレスに格納します。
*
* 指定優先度以下の全ての優先度で実行待ちタスクが見つからない場合は
* p_tskidの指すアドレスにはTSK_NONE(0)が書き込み、戻り値として
* E_OKを返します。
*
* tskpri_threshにTPRI_SELFを指定した場合にはパラメータエラー(E_PAR)と
* なります。
*
* <errors>
* E_PAR tskpri_threshの値が範囲外
* E_ID prcidの値が範囲外
* E_CTX タスクコンテキストから呼び出された
*
*/
実行中タスクのローテート(=同一優先度中で優先順位を最低にする) (xsm_imsbk_rtk)
システム管理機能拡張を使用するためにはビルドするアプリケーションで以下のプロパティを設定してください。
LibSKXSysManage <- 'true' (有効) or 'false' (無効)
追加されたAPIの関数仕様は以下の通りです。
#include <kernel.h>
typedef bool_t (*T_XSM_TSK_FILTER)(ID tskid, ID prcid, PRI tpri, intptr_t arg, ER *p_error);
ER xsm_imsbk_rtk(ID prcid, T_XSM_TSK_FILTER filter, intptr_t arg, ID *p_tskid);
/*
* 実行中タスクのローテート(=優先順位を最低にする)
* (set-back running task)
*
* <param>
* ID prcid 処理対象プロセッサの指定
* T_XSM_TSK_FILTER filter ローテートの実行可否を判定するユーザー関数アドレス
* intptr_t arg filterの引数argに渡されるユーザーパラメータ
* ID *p_tskid ローテートされたタスクのIDを格納する変数アドレス
*
* <return value>
* (戻り値)正常終了(E_OK) またはエラーコード(<errors>参照のこと)
*
* プロセッサコア prcid上で実行中(RUNNING)のタスクと優先度を引数に
* ユーザが指定した判定関数 filterを呼び出す。
* -filterがtrueを返した場合は内部でrot_rdqを実行し、E_OKを返す
* -filterがfalseを返した場合はrotateを行わずにfilterがセットしたエラーコードを戻り値として返す
*
* 指定されたコアがアイドル状態で実行中のタスクが無い場合にはE_OBJを返す
*
* filter関数の呼び出し時点では以下の条件が保証される。
* -割り込み禁止/全コアロック状態( → 割り込みや他のコアの動作の影響を受けない)
* -filter関数に渡されるタスクがRUNNING状態であること
*
* <errors>
* E_ID prcidの値が範囲外
* E_CTX タスクコンテキストから呼び出された
* CPUロック状態から呼び出された
* E_OBJ 動作中のタスクがない(アイドル状態)
* 実行中タスク以外に同一優先度の実行可能タスクが無い
* 上記以外 filterの引数 p_errorにセットされたユーザー関数のエラーコード
*
* ----------------------------------------------------------------------------
*
* T_XSM_TSK_FILTER filter 関数の仕様
*
* tskid: 実行中タスクID
* prcid: 実行中プロセッサID
* tpri: tskidの現在優先度
* arg: ユーザー使用引数 (=xsm_imsbk_rtkの引数 arg)
* p_error: フィルタ関数内でエラーコードを返す場合の書き込み先アドレス
*
* 戻り値(bool_t): true → rotate実行 / false → rotateをスキップ
*
*/
カーネル内の各資源について最大数を取得するAPI
各資源について確保可能な最大数を取得することができます。
静的に生成された資源に対しては ref_cfg, 動的に生成される資源についてはaref_cfgを呼び出します。
aref_cfgは動的資源生成機能拡張が有効な場合のみ使用可能です。
#include <kernel.h>
typedef struct t_rcfg {
uint_t tskid_max; /* タスクの最大数 */
uint_t semid_max; /* セマフォの最大数 */
uint_t flgid_max; /* イベントフラグの最大数 */
uint_t dtqid_max; /* データキューの最大数 */
uint_t pdqid_max; /* 優先度データキューの最大数 */
uint_t mbxid_max; /* メールボックスの最大数 */
uint_t mtxid_max; /* ミューテックスの最大数 */
uint_t mbfid_max; /* メッセージバッファの最大数 */
uint_t mpfid_max; /* 固定長メモリプールの最大数 */
uint_t cycid_max; /* 周期ハンドラの最大数 */
uint_t almid_max; /* アラームハンドラの最大数 */
uint_t spnid_max; /* スピンロックの最大数 */
uint_t isrid_max; /* ISRの最大数 */
} T_RCFG;
ER ref_cfg(T_RCFG *pk_rcfg);
/*
* カーネル資源最大数の取得
*
* <param>
* T_RCFG pk_rcfg 結果を格納するパケットのアドレス
*
* <return value>
* (戻り値)正常終了(E_OK)
*
* 各資源で定義されている最大数をpk_rcfgに書き込みます。
* ここで書き込まれる数は静的生成資源と動的生成資源の合計となります。
* 動的資源生成機能拡張が無効な場合には静的資源の最大数と同一になります。
* タスクコンテキスト/非タスクコンテキストのどちらからもで呼び出し可能です。
*
* <errors>
* (なし)
*
*/
#include <kernel.h>
ER aref_cfg(T_RCFG *pk_rcfg);
/*
* カーネル資源最大数の取得(動的生成資源のみ)
*
* <param>
* T_RCFG pk_rcfg 結果を格納するパケットのアドレス
*
* <return value>
* (戻り値)正常終了(E_OK)
*
* 各資源で定義されている動的資源の生成可能な最大数をpk_rcfgに書き込みます。
* ここで書き込まれる数は動的生成資源のもののみとなります。
* タスクコンテキスト/非タスクコンテキストのどちらからもで呼び出し可能です。
*
* <errors>
* (なし)
*
*/
カーネル内の生成済み動的生成資源の数を取得する
API関数呼び出し時点で動的に生成されているカーネル資源の数を取得することができます。
動的資源生成機能拡張が有効な場合のみ使用可能です。
#include <kernel.h>
typedef struct t_rnid {
uint_t tskid_num; /* タスクの生成済ID数 */
uint_t semid_num; /* セマフォの生成済ID数 */
uint_t flgid_num; /* イベントフラグの生成済ID数 */
uint_t dtqid_num; /* データキューの生成済ID数 */
uint_t pdqid_num; /* 優先度データキューの生成済ID数 */
uint_t mbxid_num; /* メールボックスの生成済ID数 */
uint_t mtxid_num; /* ミューテックスの生成済ID数 */
uint_t mbfid_num; /* メッセージバッファの生成済ID数 */
uint_t mpfid_num; /* 固定長メモリプールの生成済ID数 */
uint_t cycid_num; /* 周期ハンドラの生成済ID数 */
uint_t almid_num; /* アラームハンドラの生成済ID数 */
uint_t spnid_num; /* スピンロックの生成済ID数 */
uint_t isrid_num; /* ISRの生成済ID数 */
} T_RNID;
ER aref_nid(T_RNID *pk_rnid);
/*
* カーネル資源最大数の取得
*
* <param>
* T_RNID pk_rnid 結果を格納するパケットのアドレス
*
* <return value>
* (戻り値)正常終了(E_OK)
*
* 呼び出し時点で生成されている動的資源の数をpk_rcfgに書き込みます。
* タスクコンテキスト/非タスクコンテキストのどちらからもで呼び出し可能です。
*
* <errors>
* (なし)
*
*/
周期ハンドラAPIの非タスクコンテキスト拡張 (ista_cyc/istp_cyc/imsta_cyc)
周期ハンドラを非タスクコンテキストから操作するための拡張として以下のAPIが追加されています。
タスクコンテキストから呼び出された場合にE_CTX(コンテキストエラー)を返す点以外はsta_cyc/msta_cyc/stp_cycと同じ仕様です。
ER ista_cyc(ID cycid)
ER imsta_cyc(ID cycid, ID prcid)
ER istp_cyc(ID cycid)
アラームハンドラAPIの非タスクコンテキスト拡張 (ista_alm/istp_alm/imsta_alm)
アラームハンドラを非タスクコンテキストから操作するための拡張として以下のAPIが追加されています。
タスクコンテキストから呼び出された場合にE_CTX(コンテキストエラー)を返す点以外はsta_cyc/msta_cyc/stp_cycと同じ仕様です。
ER ista_alm(ID almid)
ER imsta_alm(ID almid, ID prcid)
ER istp_alm(ID almid)
プロセッサで実行中のタスク優先度の取得
指定されたプロセッサ上で実行中のタスクの優先度を取得します
非タスクコンテキストからの呼び出しのみをサポートします。
#include <kernel.h>
ER imget_ppri(ID prcid, PRI *p_tskpri);
/*
* プロセッサで実行中のタスク優先度の取得
*
* <param>
* ID prcid 対象のプロセッサID
* PRI *p_tskpri 実行中タスクの優先度を格納するアドレス
*
* <return value>
* (戻り値)正常終了(E_OK) またはエラーコード(<errors>参照のこと)
*
* prcidで指定されたプロセッサ上で実行中(RUNNING状態)のタスクがある場合には
* p_tskpriにそのタスクの現在優先度を格納し、E_OKを返します。
* 対象プロセッサがアイドル状態である場合にはp_tskpriのさす領域は変更せずに
* E_OBJを戻り値として復帰します。
*
* <errors>
* E_ID prcidの値が範囲外
* E_CTX タスクコンテキストから呼び出された
* CPUロック状態から呼び出された
* E_OBJ 動作中のタスクがない(アイドル状態)
*
*/
プロセッサで実行状態のタスクIDの参照
指定されたプロセッサ上で実行中のタスクIDを取得します
非タスクコンテキストからの呼び出しのみをサポートします。
#include <kernel.h>
ER imget_tid(ID prcid, PRI *p_tskid);
/*
* プロセッサで実行中のタスク優先度の取得
*
* <param>
* ID prcid 対象のプロセッサID
* PRI *p_tskid 実行中タスクIDを格納するアドレス
*
* <return value>
* (戻り値)正常終了(E_OK) またはエラーコード(<errors>参照のこと)
*
* prcidで指定されたプロセッサ上で実行中(RUNNING状態)のタスクがある場合には
* p_tskidにそのタスクのIDを格納し、E_OKを返します。
* 対象プロセッサがアイドル状態である場合にはp_tskidのさす領域にTSK_NONE(=0)を
* 書き込んだ後にE_OBJを戻り値として復帰します。
*
* <errors>
* E_ID prcidの値が範囲外
* E_CTX タスクコンテキストから呼び出された
* CPUロック状態から呼び出された
* E_OBJ 動作中のタスクがない(アイドル状態)
*
*/
CPU0以外をマスタープロセッサコアに指定可能
SOLID-OS のマスタープロセッサコアを CPU0 以外に変更可能です
マスタープロセッサコアを指定する場合は、ビルドするアプリケーションで以下のプロパティを設定してください。
SOLID_BOOT_CPUID <- CPU ID を指定。省略時は "0" 指定として処理
マルチCPUクラスタ構成に対応
マルチCPUクラスタの SoC にも対応しています
マルチCPUクラスタの SoC の場合には、以下のマクロを定義してください
SOLID_ARM_MULTICLUSTER <- =の後は、クラスタ0のCPU数を指定する(現状2,4のみ対応)
ref_tsk の機能拡張
ref_tsk で取得可能なタスク情報に、スタック領域先頭、スタック領域サイズ、現スタックポインタを追加しました
この機能有効時の T_RTSK 型の定義は以下の通りです
typedef struct t_rtsk { STAT tskstat; /* タスク状態 */ PRI tskpri; /* タスクの現在優先度 */ PRI tskbpri; /* タスクのベース優先度 */ STAT tskwait; /* 待ち要因 */ ID wobjid; /* 待ち対象のオブジェクトのID */ TMO lefttmo; /* タイムアウトするまでの時間 */ uint_t actcnt; /* 起動要求キューイング数 */ uint_t wupcnt; /* 起床要求キューイング数 */ ID prcid; /* 割付けプロセッサのID */ ID actprc; /* 次の起動時の割付けプロセッサのID */ uint_t affinity_mask; /* タスクの割付け可能プロセッサ *//* SOLID */ #ifdef SOLID_ENABLE_KERNEL_EXT_REF_TSK_STACK_INFO SIZE stksz; /* スタック領域のサイズ(丸めた値) */ void *stk; /* スタック領域の先頭番地 */ void *stkp; /* 現スタックポインタ */ #endif /* SOLID_ENABLE_KERNEL_EXT_REF_TSK_STACK_INFO */ } T_RTSK;
ref_tsk の機能拡張を使用するためにはビルドするアプリケーションで以下のプロパティを設定してください。
SOLID_EXTEND_REF_TSK <- '1' (有効) or '0' (無効)
eget_tid API の追加
コンテキスト、CPUロック状態によらず当該CPUコアでのRUNNING 状態のタスクのタスクIDを返す
呼び出し形式等は get_tid() と同じです。
eget_tid の機能拡張を使用するためにはビルドするアプリケーションで以下のプロパティを設定してください。
SOLID_SUPPORT_EGET_TID <- '1' (有効) or '0' (無効)
制限事項
サービスコール get_utm()は使用できません。(ハードウェアタイマが1個の場合の仕様上の制限)
動的資源生成機能拡張パッケージが有効な場合、スピンロックの動的生成(acre_spn)には対応しますが、資源の削除には対応しません。del_spnを呼び出した場合E_NOSPT(-9, 未サポート機能)を返します。