TOPPERS/FMP3 リリースとの相違点
SOLID-OSにおけるカーネルでは以下の点がオリジナルのTOPPERS/FMP3と仕様または動作が異なります
対応予定の拡張機能
SOLID-OS の FMP3 カーネルでは、SOLID-OS の ASP3カーネル もしくは FMPカーネルでサポートしている 以下の拡張機能については、現時点では未サポートですが、今後のアップデートで対応予定です。
ミューテックスのロック解除順序についての制限緩和
タスク起動要求キューイング数/タスク起床要求キューイング数の上限をコンフィグレーション可能
タイマーイベントハンドラを各コアで実行可能
各プロセッサアイドル時間取得機能
実行中タスクのローテート(=同一優先度中で優先順位を最低にする) (
xsm_imsbk_rtk()
)指定プロセッサについて実行中タスクの優先度を取得するAPI (
imget_ppri()
)指定プロセッサについて実行中タスクのタスクIDを取得するAPI (
imget_tid()
)
対応している拡張機能
SOLID-OSにおけるカーネルでは以下の点がオリジナルのTOPPERS/FMP3と仕様または動作が異なります
カーネル資源の静的な生成方法
SOLID-OSではタスクなどのカーネル資源を生成するために、カーネル起動時に読み込まれるパラメータをC言語のテーブルに記述しておくことで行います。
ミューテックスでの優先度継承プロトコルサポート
API仕様については μITRON4.0 仕様に準拠します
割込み及び例外の処理
SOLID-OSにおいてはCPUからの割込み及び例外の処理はCore Serviceの内部で行われます。
割込み処理については関連システムコールはオリジナル実装と同様に動作します。 ただし、
kernel_cfg.c
の中の設定テーブルに記述されていな割込みについては すべてカーネル管理外の割込みとして扱われます。例外処理についてはすべてCore Serivceの内部で処理が完結します。 プロセッサ例外時でもカーネルに通知が行われないため、
def_exc()
とxns_dpn()
は未実装か、オリジナルのカーネル仕様通りには機能しません。
割り込み優先度/割り込み優先マスクの扱いについて
割り込み優先度のレベル数は32段階固定 (
TIPM_ENAALL
(0),TMAX_INTPRI
(-1), ...,TMIN_INTPRI
(-31)) で定義され、TMAX_INTPRI
が割り込みコントローラの最も低い優先度に対応します(以降、TOPPERS優先度が-1するごとに優先度が1ずつ高くなります)
- 割り込みコントローラの割込み優先度レベル数が32未満の場合
割込みハンドラの登録 (
kernel_cfg.c
)
kernel_cfg.c
で割込み初期化テーブルに設定された優先度が割り込みコントローラがサポートする最高優先度を超える場合、割り込みコントローラの最高優先度でハンドラの登録を行います。
chg_ipm()
の動作パラメータ intpriに指定された優先度が割り込みコントローラがサポートする最高優先度を超える場合、割り込みコントローラの最高優先度でハンドラの登録を行います。
get_ipm()
の動作
get_ipm()
は割り込みコントローラに実際に設定されている割込みマスク値に対応する範囲内で優先度を返します。 上述のchg_ipmの動作により、割り込みコントローラでサポートする優先度の範囲外の値を設定した場合にはget_ipm()
は割込みコントローラがサポートする最高の優先度に対応する値を返すため、chg_ipm()
の設定値とその後のget_ipm()
の取得値は一致しません。割り込みコントローラの割込み優先度レベル数が32を超える場合
get_ipm()
の動作割込みコントローラか取得したマスク値がTOPPERS側の最高優先度 (
TMIN_INTPRI
) を超えている場合にはエラーとはせずにTMIN_INTPRI
(-1) を値として返します。
静的資源カーネルにおいて以下のAPIにおけるパラメータ制限が緩和されています
それぞれ、CRE_DTQ
での dtqmp
、CRE_PDQ
での pdqmb
、CRE_MPF
での mpfmb
に NULL 以外を指定してもエラーになりません。(動的生成拡張サポートカーネルと同等)。
CRE_DTQ [ASPS0132]
CRE_PDQ [ASPS0142]
CRE_MPF [ASPS0166]
割り込み操作APIの対象割込み番号
次のAPIについてASP3.3.0以降のリリースではカーネルに登録された割込み(カーネル管理割込み)以外の割込み番号をパラメータに渡した場合にエラーとなりますが、SOLIDでは指定された割込みについて割り込みコントローラへの操作を試みます:
dis_int()
,ena_int()
,clr_int()
,ras_int()
,prb_int()
イベントフラグ待ち解除時のクリア方法指定
イベントフラグがセットされ、待ち状態にあったタスクの待ち状態が解除される際にフラグのビットパターンのビットをクリアする方法を以下の中から選択可能です。
指定なし(クリアしない)
すべてのビットをクリア
待ち対象のビットのみクリア
待ち対象のビットのみクリアする場合はイベントフラグ待ちAPI (
wai_flg()
/pol_flg()
/twai_flg()
) の待ちビットパターンパラメータwaiptn
でセットされているビットがすべてクリアされます。それ以外のビットは変化しません。クリア方法の指定は資源生成時の属性とイベントフラグ待ちAPI (
wai_flg()
/pol_flg()
/twai_flg()
) の待ちモードパラメータ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
待ち対象ビットのみクリア
Readers/Writerロックのサポート
複数の読み手タスク(Readers)と単一の書き手タスク(Write)の間で排他処理を行うオブジェクト
ビルド方法、インクルードファイル(関数仕様)については以下のファイルを参照してください
rtos/toppers_fmp3/fmp3/solid_extension/rwlock/Readme.md
[2020.2.27]デッドロック対策として同一タスクが多重にロックを取得しようとした場合の動作を以下の通りに変更しました。
すでに読み手ロックを取得したタスクが再度読み手ロックを取得 -> 成功 (ただしこの場合には取得した回数分だけアンロックを行う必要があります。)
すでに書き手ロックを取得したタスクが再度書き手ロックを取得 -> エラー (
E_OBJ
)すでに書き手ロックを取得したタスクが読み手ロックを取得 -> エラー (
E_OBJ
)[制限事項]
以下の場合についてはAPIでエラーとはならずにデッドロックが発生する可能性があります。
読み手ロックを取得したタスクが書き手ロックを取得
カーネル内の各資源について最大数を取得する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 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 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>
* (なし)
*
*/
非タスクコンテキストからの clr_flg()
を呼び出した場合の動作
SOLID-OSでは非タスクコンテキストから
clr_flg()
を呼び出した場合、タスクコンテキストから呼び出した場合と同等の動作をします。(第3世代カーネル仕様ではE_CTX
エラー)
CPUロック状態から呼び出すことが可能なサービスコール
TOPPERS標準仕様においてCPUロック状態で呼出可能なサービスコールに加えて、 以下のサービスコールについてもCPUロック状態から呼び出すことが可能です。 (E_CTXを返さずにCPUロック状態を維持したまま正常処理を行います。)
set_flg
これらのサービスコール内部で呼び出したプロセッサ上でタスク切替が必要となる様なタスク状態の変更が行われた場合には該当サービスコール終了後にユーザーが
unl_cpu()
またはunl_spn()
を呼び出すことによりCPUロック状態が解除(=割り込み許可)されるタイミングでタスクの遷移(ディスパッチ)が行われます。
警告
割り込みを許可するためにSOLID Core Serviceの SOLID_MUTEX_EnaInt()
関数を呼び出してもタスクの切替は行われません。CPUロック状態でサービスコールを呼び出した後の割り込み許可には必ず unl_cpu()
(スピンロック保持中の場合は unl_spn()
)を使用してください。
注釈
TOPPERS標準仕様においてCPUロック状態で呼出可能なサービスコールについてはTOPPERS第3世代カーネル(ITRON系)統合仕様書 の「2.5.5 CPUロック状態とCPUロック解除状態」を参照してください。
複数プロセッサをターゲットする割込みの指定が可能
カーネル起動時に読み込まれる割込みハンドラのパラメータテーブルでGICが通知するターゲットのCPUコアを複数指定することができます
複数プロセッサをターゲットとする割込みの設定について
同じ割込み番号(IRQNO)に対し、複数のプロセッサを指定可能となりました。
注釈
SGI/PPIの場合: あるIRQNOに対してプロセッサ毎に異なるハンドラを設定可能です。 SPIの場合: あるIRQNOに対して全プロセッサに共通な一つのハンドラのみ設定可能です。
割り込み設定はマクロ
CFG_DEF_INT
/CFG_DEF_INT_MT
を使用してkernel_cfg.c
に記述します。割込み初期化設定ブロックの設定例 (
kernel_cfg.c
)#define INTNO_SGI_1 1 // SGI #1 #define INTNO_SGI_2 2 // SGI #2 #define INTNO_16_1 16 // 割込み番号16 #define INTNO_17_2 17 // 割込み番号17 #define INTNO_PPI_1 1 // PPI extern void int_handler_int17(void); extern void sgi_handler_p1(void); extern void sgi_handler_p2(void); extern void sgi_handler_p3(void); extern void sgi_handler_p4(void); extern void sgi_handler_common(void); extern void spi_handler_common(void); // // 割込み初期化ブロック // const INTINIB _kernel_intinib_table[] = { // IRQ1 <- 最低優先度、ISRを使用, プロセッサ1のみ CFG_DEF_INT(INTNO_16_1, INTINI_USE_ISR, TA_NULL, (-1), 1), // IRQ2 <- 最高優先度、直接割込みハンドラ関数を登録, すべてのプロセッサに割込みを設定 CFG_DEF_INT_MT(INTNO_17_2, int_handler_int17, TA_NULL, (-32), CFG_PROC_MASK_ANY), // SGIを複数コアをターゲットにしてプロセッサ毎に個別のハンドラを // 登録する例 CFG_DEF_INT(INTNO_SGI_1, sgi_handler_p1, TA_ENAINT, (-2), 1), CFG_DEF_INT(INTNO_SGI_1, sgi_handler_p2, TA_ENAINT, (-2), 2), CFG_DEF_INT(INTNO_SGI_1, sgi_handler_p3, TA_NULL, (-2), 3), CFG_DEF_INT(INTNO_SGI_1, sgi_handler_p4, TA_ENAINT, (-2), 4), // SGIを複数コアをターゲットにしてプロセッサ毎に共通のハンドラを // 登録する例 (affinity_maskを使用して複数コア分を1行で登録) // 下記の例ではSGI発行でprc(1, 2, 3)で割り込み発生し、同じハンドラ関数が呼び出されます。 CFG_DEF_INT_MT(INTNO_SGI_2, sgi_handler_common, TA_ENAINT, (-2), (CFG_PROC_MASK(1) | CFG_PROC_MASK(2) | CFG_PROC_MASK(3))), // SPIを複数コアをターゲットにしてプロセッサ毎に共通のハンドラを // 登録する例 (affinity_maskを使用して複数コア分を1行で登録) CFG_DEF_INT_MT(INTNO_PPI_1, spi_handler_common, TA_ENAINT, (-2), CFG_PROC_MASK_ANY), };警告
GICv3以降の環境でAffinity Routingを使用している場合など、GICのコンフィグレーションに よっては
CFG_DEF_INT_MT
による複数コアをターゲットにした登録が行えない場合があります。 この場合、affinity_mask
で最も下位のビットにあたるプロセッサ1個の身に対して 割込みがあがる様に設定を行います。(affinity_mask
中の他のプロセッサは対象外)
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; /* タスクのベース優先度 */ uint_t subpri; /* タスクのサブ優先度 */ STAT tskwait; /* 待ち要因 */ ID wobjid; /* 待ち対象のオブジェクトのID */ TMO lefttmo; /* タイムアウトするまでの時間 */ uint_t actcnt; /* 起動要求キューイング数 */ uint_t wupcnt; /* 起床要求キューイング数 */ bool_t raster; /* タスク終了要求状態 */ bool_t dister; /* タスク終了禁止状態 */ ID prcid; /* 割付けプロセッサのID */ ID actprc; /* 次の起動時の割付けプロセッサのID */ uint_t affinity_mask; /* タスクの割付け可能プロセッサ */ #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' (無効)
制限事項
スピンロックの動的削除 (
del_spn()
) は機能せずエラーになるスピンロックはエミュレート方式のみ対応しています。今後のリリースで対応予定です。