| name | toppers-kernel-dev |
| description | TOPPERS系カーネル(ASP/ASP3/FMP3/HRP3 等 ITRON系RTOS)の「カーネル・アーキ・ターゲット側」を扱う作業の共通規約。上流TOPPERSを追従する派生カーネルを保守するとき、`arch/`・`target/`・`syssvc/` のアーキ/ボード依存部を実装・編集するとき、新ターゲットへ移植するとき、上流の新バージョンとマージするとき、静的API構造(`kernel_api.def`)やコンフィギュレータ(cfg)を扱うとき、カーネルをビルド・テストして検証するときの「やってよいこと/いけないこと」と作業順序を示す。ユーザが「TOPPERS」「カーネルを直す」「移植」「上流マージ」「ターゲット依存部」「アーキ依存部」「cfg」「静的生成」と言ったときに発動。**アプリ(タスク・セマフォ等)のCコードや`.cfg`記述を書くときは別skill `toppers-asp`。実装・トレース・テストの具体コマンドはリポジトリ固有(各リポジトリの `AGENTS.md`/`docs` や専用skill)に従う。本skillは実装非依存の共通規約。** |
TOPPERS系カーネル 開発・保守の共通規約(実装非依存)
TOPPERS系RTOS(μITRON4.0系。ASP/ASP3/FMP3/HRP3 等)のカーネル・アーキ・ターゲット側を
扱うときの、ベンダ・ビルドシステムに依存しない共通規約。TOPPERSは「カーネルコア+
アーキ依存部+ターゲット依存部」の層構造で配布されるため、層を意識した作業が要となる。
- アプリ側(タスク・割込みハンドラ・周期ハンドラ・セマフォ等のCコードや
.cfg)を
書く・レビューするときは別skill toppers-asp。
- 不具合診断・トレース・適合性テストは別skill
toppers-kernel-debug。
- ビルド/テストの具体コマンド・プリセット・スクリプト・台帳ファイル名はリポジトリ固有。
各リポジトリの
AGENTS.md/CLAUDE.md/docs/ や、そのリポジトリ専用skillに従う。
本skillは「どのリポジトリでも変わらない原則」だけを述べる。
0. 着手前に必ず読むもの
派生リポジトリには規約の正本がある。作業前に必ず読む:
AGENTS.md(無ければ CLAUDE.md/README)=そのリポジトリの開発規約・手順の正本
- 上流からの乖離台帳(あれば)と、現在ベースにしている上流バージョンの記録
リポジトリ固有の正本が本skillより優先する。「動くはず」で進めない。
1. ⚠️ 二大禁則(最重要)
詳細と根拠は references/inviolable-rules.md。
禁則① カーネルコアを直接編集しない(上流追従の派生の場合)
上流TOPPERSを追従する派生では、カーネルコア(kernel/・共通ヘッダ・ライブラリ)を
上流そのままに保つ。直接編集すると上流の新バージョンとの手動マージが破綻する。
変更はアーキ依存部(arch/)・ターゲット依存部(target/)・システムサービス
(syssvc/)・新規ファイルに隔離する。
✗ カーネルコアのファイルを編集
✓ arch/<arch>/ に追加 ✓ target/<name>/ に追加 ✓ syssvc/ に追加 ✓ 新規ファイル
どうしてもコアに手を入れる必要があれば、作業を止めてユーザーに確認し、乖離台帳に
記録し、#ifdef ガードで既定動作を上流と同一に保つ(純追加を最優先)。
禁則② カーネル内で動的メモリ確保を使わない
malloc/calloc/realloc/free/C++ new/delete 禁止。静的配列または
固定長メモリプール(CRE_MPF で静的生成し get_mpf/rel_mpf)のみ。
ISO 26262 / IEC 61508 が求める静的な資源上界保証のための安全設計方針。
その他の必須ルール
- カーネル内で再帰を使わない(スタック消費の上界が静的に決まらない)。
- エラーは戻り値
ER 型で返す(例外・longjmp を使わない)。E_*(負値)は必ず確認。
- 浮動小数点はタスクコンテキストでのみ(割込み/周期/アラームハンドラ内で使わない)。
- 命名はTOPPERS流(関数=小文字+
_、型=大文字 typedef=ID/ER/PRI、定数=大文字+_、
内部関数は上流の接頭辞・命名に従う)。
2. 静的生成のみ(TOPPERSの基本)
標準パッケージではすべてのカーネルオブジェクトを静的API(.cfg)で生成する。
実行時に生成・削除する動的API(acre_*/del_*)は標準では未サポート。タスク・
セマフォ・イベントフラグ・データキュー・ミューテックス・固定長メモリプール・
周期/アラームハンドラ・ISR・割込み/例外ハンドラ・初期化/終了ルーチンは、
CRE_*/DEF_*/ATT_*/CFG_INT でコンフィギュレータがビルド時に登録する。
- 静的API構造(パラメータ・型)の正本は
kernel/kernel_api.def(接頭辞DSL:
#=ID, .=符号無し, +=符号付き, &=一般, ^=ポインタ, $=文字列、
後置 *=キー ?=オプション ...=リスト)。
- 新しい静的APIは
kernel_api.def の行追加で対応する(上流と同形式)。
- cfg は通常ビルドが自動実行する。手動起動は原則しない。
- アーキによってはC側のソースもオフセット系の生成ヘッダを取り込む(他アーキでは
アセンブラのみが取り込む)。後者を前提に組まれた上位ビルドの順序依存だと、前者のアーキで
並列ビルド時に生成ヘッダができる前にCをコンパイルするレースが起き、間欠的に失敗する。
対策は、該当するCオブジェクト群へ生成タイムスタンプへの順序専用依存を付与すること
(ヘッダを取り込まないアーキでは依存が空になる純追加で、無回帰にできる)。
〔分類: ビルド系・移植 | プロセッサ: 非依存(生成ヘッダの依存方向がアーキで異なる) | 出所: FMP3〕
3. ビルド→実行→テストの順序と鉄則
テストは必ずこの順(ハードなし→QEMU→実機):
1. ホストシミュレーション/POSIX ← 最速。まずここ
2. QEMU ← アーキの動作確認
3. 実機 ← 最後に実ハードで
検証の鉄則(厳守)
- コードを変更したら必ずビルドが通ることを確認してから報告する。
- テストは機械判定可能な形式(TAP の
ok/not ok 等)で判定する。
- 実行結果(ビルド結果・テスト出力)を根拠に報告する。「動くはず」は禁止。
具体的なビルドコマンド(上流標準は configure+make。派生によってはCMake等)・
実行オプション・テストランナはリポジトリ固有。AGENTS.md/docs/ を見る。
4. 新ターゲットへ移植するとき
- リポジトリの移植ガイドの Step 順に進め、各 Step の確認を通してから次へ。
- 既存ターゲットの実装を参照実装にする。
- メモリマップ・割込み設定・コンテキストスイッチ・ベクタ・リンカ配置を誤ると
ハードフォルトの原因になる。生成後に必ず人間の確認を求める。
- 外部のセキュアFW/モニタから制御が渡るアーキ(上位例外レベルを持つ構成)では、
FW が上位レベルのアクセストラップ(コプロセッサ/浮動小数点/拡張機能レジスタへの
アクセス禁止)を有効にしたまま引き渡すことがある。 下位レベルへ降りた RTOS が
それらレジスタに触れると同期例外になる。最上位で走る初期化フックを設け、下位
レベルへドロップする前にトラップを解除する。移植時はブート経路(どの例外レベルから
開始し、FW が何を設定済みか)を最初に確認する。
〔分類: ブート/例外・初期化 | プロセッサ: 上位例外レベルを持つアーキ(例:AArch64 の EL3/EL2/EL1) | 出所: stm32mp2_baremetal〕
- セキュリティ拡張を持つコアを Secure 状態で単独動作させる構成では、例外復帰の制御値を
Secure 用に選ぶ設定が必須。復帰値が NonSecure 用の既定のままだと、Secure 状態での
例外復帰の整合性チェックに失敗する(エミュレータ上では不正な復帰先・整合性違反として
現れる)。あわせて、コアのアーキ世代を表すマクロが開発環境で自動定義されない場合は
明示的に定義する。
〔分類: 移植/割込み・制約/アーキ構造・観測/エミュレータ | プロセッサ: セキュリティ拡張付き M-profile | 出所: FMP3〕
- ベンダ提供のリンカスクリプトへ統合する場合、cfg が生成するベクタテーブルが
orphan セクションになり、所定の割込みベクタ領域に収まらず配置エラーになることがある。
ベンダ ld をコピーして専用セクションへ明示配置し、ベクタの整列要件を満たす。
〔分類: 移植/リンカ | プロセッサ: 非依存(cfg生成ベクタ+ベンダld。ARM-M 等で顕在化) | 出所: asp3_mcuxsdk〕
- ベクタ基底レジスタを持つコアで、用途別/PE別に複数のベクタ表を生成する構成では、
各表を2のべき乗境界へ整列させる。基底レジスタは下位ビットを無視するため、表の先頭が
2のべき乗境界に乗っていないと、基底レジスタが指す実効アドレスがずれて誤った表を
指す(別用途・別PEの表をフェッチする)。整列量は表の大きさに応じた2のべき乗で、
リンカで各表へ整列指定する。
〔分類: 整列・移植/リンカ | プロセッサ: ARMv8-M | 出所: FMP3(Cortex-M)〕
- 手書きアセンブリやベクタのセクション名が、生成/統合後のリンカスクリプトの
ワイルドカードと一致しないと孤児化し、想定と違う属性の領域(実行不可・非特権不可
など)へ落ちる。配置エラーで止まればまだ良いが、通ってしまうと例外ベクタ等の
フェッチが実行時に保護フォルトする(メモリ保護有効時に顕在化しやすい)。移植時は
「セクション名がリンカスクリプトの保持規則に合っているか」を、配置エラーが無くても
確認する。
〔分類: 移植/リンカ | プロセッサ: 非依存(孤児セクション→属性違い領域→実行時フォルト) | 出所: stm32mp2_baremetal〕
- アーキ依存部を別プロファイルへ移植したとき、関数形式マクロの引数括弧不足が顕在化
することがある。仮引数を括弧で囲っていないマクロは、式を渡すと演算子優先順位で
誤展開する。元コードが単一変数でしか呼んでいないと潜在化し、式を引数に渡す別カーネル
へ移植して初めて壊れる。移植元から持ち込むマクロは、引数に式を渡す前提で括弧を点検する。
〔分類: 移植/Cマクロ | プロセッサ: 非依存 | 出所: stm32mp2_baremetal〕
- データセクションのROM化(初期値付き
.data を ROM から RAM へ起動時コピーする構成)
では、コピー元アドレスをそのセクションの LMA(ロードアドレス)から取る。「直前
セクション(.text 等)の終端=コピー元」と書くと、セクション境界の整列でロード
アドレスが繰り上がったとき数バイトずれ、初期値付き変数が破壊される(ゼロ初期化/
未初期化変数では顕在化せず、初期値を持つ変数で初めて壊れるため発見が遅れる)。リンカの
LMA 取得機能でコピー元・終端を求める。あわせて、リンカスクリプトを編集しても
再リンクされないビルドシステムがある(リンカスクリプト指定がリンク依存に入らない)ので、
ld をリンク依存に明示登録する。
〔分類: 移植/リンカ | プロセッサ: 非依存 | 出所: asp3_core〕
- 割込み入口でハードウェアが優先度スタックを push し、割込み復帰命令で pop するアーキ
(割込みコントローラが優先度のネスト退避を自動化する実装)へ移植するときは、RTOS の
ディスパッチが復帰命令を経由しない経路(コンテキスト切替で別タスクのスタックへ
直接飛ぶ等)を持つことと整合させる。復帰命令の自動 pop に任せると、ディスパッチで
復帰命令を通らないぶん pop が起きず、優先度マスクが上がりっぱなしになる(全割込みが
入らなくなりハングに見える)。優先度スタックの pop を割込み出口処理のソフトウェアで
明示的に行い、ハードウェアの自動 pop は使わない(復帰命令に pop させる制御ビットを
立てない)方式へ一本化する。
〔分類: 制約/アーキ構造・移植 | プロセッサ: 割込みコントローラが優先度スタックを持つ実装(例:一部 RISC-V コアのカスタム割込みコントローラ) | 出所: asp3_core〕
- メモリ保護プロファイル(HRP系)を新アーキへ移植する場合は、保護ドメインの分離手段
(アーキ依存)・多段変換テーブルの開始レベル・権限マッピングの安全側丸め・特権境界を
越えるサービスコール入口など、保護機構固有の追加実装がある。
→
references/memory-protection-porting.md
- マルチプロセッサ派生(FMP系)のアーキ依存部を、シングルプロセッサ派生(ASP系)へ
移植する場合は、プロセッサ制御ブロックの per-PE フィールドのグローバル化・プロセッサ
別アクセステーブルの単一化・起動同期/プロセッサ間割込み/マイグレーション/スピン
ロック経路の削除などの定型変換がある。両派生に共通して存在する別アーキの依存部の差分を
「変換規範」に使える。
→
references/mp-to-sp-porting.md
- ベンダSDK/HAL と統合する場合、GUI 生成器の出力(ボード初期化・クロック設定等)を
リポジトリに固定(コミット、または版を固定した直参照)し、必要なドライバだけを直接
ビルドする。生成器を都度実行させない=CI で再現可能・GUI 不要にできる。
〔分類: 統合/CI | プロセッサ: 非依存 | 出所: asp3_mcuxsdk〕
- ベンダのツールチェイン設定が全リンクに未参照セクション除去(
--gc-sections 相当)を
強制する場合、cfg がオフセット抽出に使う中間リンク成果物(cfg 第1パスの生成物)から、
どこからも参照されない検証用シンボル(マジックナンバー等)が除去され、cfg の検出処理が
「シンボルが見つからない」で失敗することがある。中間リンクだけ除去を無効化(構成側で
後勝ちに上書き)し、最終実行ファイルはベンダ既定のまま除去有効でよい。
〔分類: 統合/ビルド | プロセッサ: 非依存(cfg 2パス生成+リンカ最適化) | 出所: asp3_stm32cube〕
- 標準ディストリ同梱のツールチェインに、目的アーキ/ABI 向けの軽量 libc(newlib-nano
相当)の multilib が無いことがある。その場合は別の組込み向け libc(picolibc 等)へ
切替える。ただし選んだ libc の specs ファイルが、自前のリンカスクリプトを既定で
強制適用するため、カーネル/ベンダ提供のリンカスクリプトをそのまま使うには、
リンカスクリプトを明示指定(
-T 相当)して specs 既定を後勝ちで上書きする。あわせて
未参照セクション除去の扱い(cfg 2パス生成との整合〔上〕)も確認する。「軽量 libc が無い=
そのアーキでは使えない」と早合点せず、specs と ld の主従関係を意識して libc を差し替える。
〔分類: 移植/リンカ・統合/ビルド | プロセッサ: 非依存(picolibc/newlib を使う組込み一般。RISC-V rv64gc/lp64d で軽量 libc multilib 欠落により顕在化) | 出所: FMP3(polarfire)〕
- 構成生成系(コンフィギュレータ/コンポーネント記述ツール)が独自の C パーサで
ヘッダを解析する場合、コンパイラ拡張の型(広い整数型など)を解釈できず構文エラーに
なることがある。型を使うヘッダが生成系の解析対象に入ると、本来コンパイルは通るのに
生成段で全 import が連鎖失敗する。ツールが定義するシンボルで分岐する条件マクロで、
解析時のみ標準型に見せる(最終的に生成・コンパイルされる実コードには影響させない)。
〔分類: 統合/コンフィギュレータ | プロセッサ: 非依存(広い整数型を使うアーキで顕在化) | 出所: stm32mp2_baremetal〕
- 高分解能タイマ(HRT)の計数クロックを、ベンダが固定したクロックツリーの整数分周で
作る場合、正確な 1µs(1MHz)ティックが得られず小さな単調ドリフト(ppm オーダ)が残る
ことがある。実用上は許容できることが多いが「タイマは正確に 1MHz」を前提にせず、誤差を
実測して文書化する。整数分周で 1MHz を割り切れるクロック源を選べれば誤差ゼロにできる
(同系 SoC でもクロック源の選択で誤差が出る/出ないが分かれる)。
〔分類: 時間分割/タイマ・制約/アーキ構造 | プロセッサ: 非依存(timer-as-HRT 全般) | 出所: asp3_mcuxsdk〕
- チップ依存の構成ヘッダに置くハード由来の値は、ハードウェア(カウンタのビット幅・
クロック等)の設計上の根拠で記述する。たとえ特定の適合性テストを通すために選んだ値で
あっても、ヘッダにはテスト名を書かず、恒久的なハード設定としての根拠だけを残す。
テスト都合の値と恒久的なハード設定が混在するのを避ける設計規律。
〔分類: 移植/設計規律 | プロセッサ: 非依存 | 出所: FMP3〕
- 完了後、乖離台帳・プリセット/ビルド設定・CI・移植索引を更新する。
- 最初の動作確認はカーネル基本項目の検証(機械判定)で行う。
5. 上流マージを支援するとき
詳細は references/upstream-merge.md。原則:
- 現在ベースの上流バージョンを確認。
- 乖離台帳(ファイル単位の意図的変更一覧)で変更種別・影響範囲を把握。
- 上流diff × 乖離台帳を照合し、影響ファイルを列挙。
- 乖離していないファイルは上流版で上書きしてよい。
- 乖離しているファイルは「要人間確認」とマークして停止する。
- cfg関連は層(静的API定義/エンジン/生成テンプレート)ごとに難易度が違う点に注意。
- ホストsim → QEMU の順で回帰テスト。完了後にベースバージョン記録を更新。
references/
アプリのAPI/静的API/エラー辞書は toppers-asp、診断・トレース・適合性テストは toppers-kernel-debug、
実装固有の手順は各リポジトリの AGENTS.md/docs/ を参照。