リアルタイム
デッドラインを絶対に落としてはならない部分は、ネイティブの Zig タスクとして書きます。VM はその周りを指揮します。プリエンプトするタイマがあるので、暴走したスクリプトがネイティブのタスクを止めることはできません。
プリミティブ群
スケジューラは、ハード RTOS のプリミティブ群をアーキ非依存のコードとして持ちます。
| プリミティブ | 機構 |
|---|---|
| 優先度継承ミューテックス | 待たされた高優先度の待ち手が所有者を自分の優先度へ引き上げ、unlock で戻す。タスクにつきミューテックス 1 つ(ネストや連鎖継承は未実装) |
| デッドラインタイマ | タイマはナノ秒で次のイベントに合わせて張る。眠っているタスクの起床・周期タスクのリリース・ラウンドロビンのスライス、その最も早いもの。固定周期で刻むのではない |
| 時間付き待ちの有界化 | イベント発生か n ナノ秒後の早い方で起床する |
| デッドライン超過検出 | レート単調の暗黙デッドラインで、超過回数を数える |
| CPU 時間計上 | 中断されたタスクに実行 tick を課金する |
| CPU 予約 / 時間隔離 | タスク毎の予算と周期。予算を超えたタスクは補充まで抑制する |
| ソフトウェアウォッチドッグ | heartbeat の生存確認。固まったタスクを検出できる |
| RM スケジューリング解析 | 双曲線境界 Π(Cᵢ/Tᵢ + 1) ≤ 2。すべて整数演算 |
| 高分解能クロック | x86 は PIT 較正の TSC、riscv は rdtime、aarch64 は CNTVCT/CNTFRQ、ARMv6-M は µs TIMER |
| サブ µs ビジー待ち | ナノ秒クロックをスピンする |
**x86_64・riscv64・aarch64 は、この一式を起動して走らせています。**RP2350 は下の「デッドライン充足」の 2 タスクを起動します(タスク表の上限が 8 で、一式は 12 要るため)。RP2040 は 1 つも起動していません。
**RM 解析は受付ゲートではありません。**呼べば「このタスク集合が収まるか」を答える関数であって、spawn がそれを参照して生成を拒否する、という形にはなっていません。
スケジューラがデッドラインを守る
**スケジューラにとっての「いま」はナノ秒クロックで、タイマは次のデッドラインに合わせて張ります。**眠っているタスクの起床・周期タスクのリリース・ラウンドロビンのスライス、その最も早いものに。固定周期で刻むわけではないので、要求できる最短のデッドラインに、tick が下限を作りません。sleep と wait_period はナノ秒で受け、tick 版はそれを薄く包んだだけです。これに要るハードウェア——絶対値のワンショット比較器——は、5 つのターゲットが最初から持っていました。
本物の制御則が、スケジューラ配下のふつうの周期タスクとして、実機で 1 kHz で回り、スケジューラがデッドラインを守ります。
- RP2350(Hazard3):1,741,824 ジョブ中、超過 0 回、周期 948.9〜1056.5 µs——フル配送飛行、ミッションとネットワークが同じチップを共有。
- RP2040(Cortex-M0+):113,664 ジョブ中、超過 0 回、周期 998〜1002 µs——ネットワークは動くが VM ミッション無し。264 KB のチップに RT タスクとミッションは同居できず、ホバリングです。±2 µs はジッタではなく、1 µs タイマの分解能の床です。
これは本物の control()(ソフトフロートのカスケード PID + 四元数)で、OS がループの中にいます。スケジュールし、CPU 時間を計上し、ネットワークや VM 飛行アクターとチップを分け合いながら。これが RTOS かどうかを決めるのは、この数字です——スケジューラが本物の 1 kHz タスクを時間どおりに出す、実機で、ネットワークとミッションが同じチップを奪い合う中で。
同じ制御則が、HIL フライトコントローラとして、同じ実機で Wi-Fi 越しに配送ミッション(島、投下、帰投、着陸)**を飛ばします。**こちらは HIL フレームのレートで回ります。上の 1 kHz はスケジュールされた RT タスクのほうです。1 つの制御則の 2 つの実証であって、同じループではありません。
合成のタスク対(C/T = 2/10 と 5/40、利用率 32.5%。双曲線境界が schedulable と判定する集合)も、x86_64・riscv64・aarch64・RP2350 で全デッドラインを守ります。解析は走らせる前に判定を出力するので、予測と実測が互いに突き合わされます。**ただしそれは、通るように選んだ集合です。**本物の制御則は、そうではありません。
測定値
**制御則の最悪値を、両ボードで実測しました。**各ボードが起動時に、割り込みをマスクして、到達可能な飛行包絡線の 2 万入力の敵対的掃引で control() を回します。どちらも 125 MHz なので、数値は直接比較できます。
- Cortex-M0+(RP2040):190 µs——1 kHz の予算に対して 5.2 倍の余裕。
- Hazard3 RISC-V(RP2350):98 µs——10.2 倍の余裕。Hazard3 は、ソフトフロートが頼るハードウェアの整数乗除算を持つので、約 2 倍速い。
どちらのコアもキャッシュも分岐予測も投機も持たないので、実測の最大値がそのままエンジニアリング WCET です——隠れたテールがありません。掃引は決定的で、ボード上で再現できます。
スケジューラ自身の応答の床は、riscv64 で実測して、割り込み駆動で 約 1.1 µs(Sstc タイマ)、タイマがファームウェア呼び出しになる場合で 約 3.5 µs。これが「OS があなたのタスクに到達するまでの代金」であり、周期と突き合わせるべき数字です。
決定的な仮想時間(-icount shift=0)の下では、絶対デッドラインの待ちがジッタ 0 を示します。機構が厳密であり、負荷のかかったホストで見えるジッタはホストのものであって OS のものではない、ということです。
実機の x86 で残る残差は、ファームウェアのシステム管理割り込み(マスク不能)と、キャッシュやマイクロアーキの効果です。これより下の決定性には、専用ハードか FPGA ソフトコアが要ります。
制御ループの最悪実行時間
HIL(ハードウェア・イン・ザ・ループ)フライトコントローラが、Lambda OS 上で動きます。コントローラは本物です。実機、実演算、実モータ出力を、シミュレートされた機体(プラント)が駆動します。これは実機を飛ばす前にフライト制御を検証する標準的な方法です。デッドラインの挙動を、決定論的に、再現可能に詰められます。実飛行にはできないことです。ここでの検証は、設計上 HIL を軸にしています。
**飛ぶのは貨物配送のミッションです。**デモの全体——フォールト応答、プリフライト関門、HIL リグ——は 飛行制御 のページにあります。
デッドラインが安全かどうかを決めるのは、制御演算そのものの最悪実行時間、すなわちソフトフロートのカスケード PID + 四元数です。各ボードが起動時に、割り込みをマスクして純粋な演算時間だけを取り、到達可能な飛行包絡線の 2 万入力の敵対的掃引で自分の値を計測します——姿勢球面の全域、±35 rad/s のジャイロ、±400 m の位置誤差、1.0〜1.4 kg の全質量域。平方根と除算がデータ依存の最悪パスを通るよう入力を選びます。
- Cortex-M0+(RP2040):190 µs(23,782 サイクル、ベスト 180 µs)。Hazard3(RP2350):98 µs(12,353 サイクル、ベスト 85 µs)。同じコード、同じ 125 MHz——Hazard3 はハードウェアの整数乗除算を持つので約 2 倍速い。
- **分母は、デモのリンク速度ではなく制御則から取ること。**実機のマルチロータは姿勢を 1〜2 kHz で安定化します。数十 Hz では飛ばせません。1 kHz に対して、Cortex-M0+ で 5.2 倍、Hazard3 で 10.2 倍の余裕です。
- しかもこの値は、カスケード全段を 1 回の呼び出しで回したもの(位置 → 速度 → 姿勢 → 角速度 → モータミキシング)であり、実機のコントローラが fast loop で回す量より多い。つまり内側ループの保守的な上界です。
- 最悪値は平坦です。制御ループ内部のクランプが、平方根と除算に入る全オペランドを正規化された O(1) の範囲に縛るため、非正規数の低速パスに到達できない——掃引は、良性のミッションが取り逃すスパイクを見つけられません。
なぜ実測の最大値を WCET と呼べるのか
Cortex-M0+ には、**キャッシュも、分岐予測も、投機も、マスク不能な SMI もありません。**だから、実測の向こうに隠れている値がない。ばらつきの元はデータ依存のソフトフロートのコストだけで、そこはミッションが広く踏んでいます。
キャッシュ付きスーパースカラのチップでは実測 max が真の最悪値より下に出るため静的解析が要りますが、M0+ では実測の最大値がそのままエンジニアリング WCET です。これが、ハードなデッドラインに「遅いが決定的」が勝つ理由です。生のスループットは低く、fib(25) の解釈実行に 24 秒かかりますが、デッドラインを背負う制御演算の WCET は 190 µs です。その遅さは、デッドライン経路から意図的に外した VM インタプリタに閉じ込めてあります。
この測定が及ぶ範囲
- **コントローラは実機で、シミュレートされたプラントを相手に走ります。**演算も、タイミングも、モータ出力も本物で、機体の力学だけがシミュレータのものです。これが HIL の要点です。デッドラインの挙動を決定論的に測れます。実飛行にはできないことです。
- 190 µs は、割り込みをマスクして測った演算時間です。プリエンプトを含む応答時間ではありません。
- **1 kHz のデッドライン結果と、飛行は、1 つの制御則の別々の実証です。**スケジューラは 1 kHz のデッドラインを守り、演算はそこに収まります(190 µs)。配送そのものは HIL フレームのレートで閉ループとして飛びました。1 回の 1 kHz 閉ループ飛行は、その 2 つの合わせ技であって、1 回の実行として示したものではありません。
- Cortex-M0+ では、ミッションが唯一の非特権・MPU 隔離アクターです。安全包絡線と制御ループはネイティブなので、バグったミッションはそこに一切届きません。
- 完全な認証を取るなら、ソフトフロートの平方根と除算の最悪値を静的解析で固定するか、制御ループを固定小数点で書き直してデータ依存性を消すことになります。