0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AUTOSAR におけるExclusive AreaとCritical sectionについてご紹介ください。

もちろんです。AUTOSARにおける Exclusive Area と Critical Section は、マルチタスク環境で共有リソースの安全なアクセスを保証するための概念ですが、少し使われ方や管理方法に違いがあります。順を追って整理します。

  1. Critical Section(クリティカルセクション)
    概要
    Critical Section(CS) は、基本的に 複数のタスクや割り込みから共有リソースに同時にアクセスされることを防ぐ範囲 のことを指します。
    この範囲内では 割り込みを禁止する(Interrupt Disable) ことで、処理が中断されずに安全にリソースを扱えるようにします。
    OS(AUTOSAR OS)では、通常 SuspendAllInterrupts() / ResumeAllInterrupts() のようなAPIで管理します。
    特徴
    特徴 説明
    実装 割り込みを一時的に禁止
    利用範囲 共有リソースアクセスの最小範囲
    影響 全割り込みが一時停止するため、処理時間が長すぎるとリアルタイム性に影響
    使用例(Cコード)
    SuspendAllInterrupts(); // クリティカルセクション開始
    sharedVariable++;
    ResumeAllInterrupts(); // クリティカルセクション終了
  2. Exclusive Area(エクスクルーシブエリア)
    概要
    Exclusive Area(EA) はAUTOSAR独自の抽象化で、Critical Section を管理するための OSレベルのAPI として定義されます。
    目的:タスクやISRからのアクセスを統一的に制御し、割り込み優先度に応じて安全にリソースを扱う。
    直接割り込み禁止を行うのではなく、 AUTOSAR OS が定義したAPIで排他制御 を行うことで、プラットフォーム依存を隠蔽します。
    API例(OSEK/AUTOSAR OS)
    EnterExclusiveArea(EXCLUSIVE_AREA_ID);
    sharedVariable++;
    LeaveExclusiveArea(EXCLUSIVE_AREA_ID);
    特徴
    特徴 説明
    実装 OS内部で割り込みマスクやスケジューリング制御を管理
    利用範囲 特定の共有リソースアクセスに対応
    影響 プラットフォーム依存を吸収しつつ、安全な排他制御
    推奨 Critical Section の直接利用よりExclusive Area APIを使う方がAUTOSAR標準に準拠
  3. 両者の違い
    項目 Critical Section Exclusive Area
    管理者 プログラマが直接割り込み禁止を実装 OSが管理(API経由)
    抽象度 低レベル 高レベル(AUTOSAR標準API)
    プラットフォーム依存 高い(CPUごとに割り込み制御方法が違う) 低い(OSが抽象化)
    推奨 特殊なケースのみ 一般的にはこちらを利用
  4. 注意点
    処理時間は短く
    Exclusive Area も Critical Section も長時間保持すると、割り込み遅延やタスクスケジューリングに影響する。
    ネストに対応
    AUTOSAR OS の Exclusive Area API はネスト可能(同じEAを再入しても安全)。
    ISRからの呼び出しに注意
    ISR内でExclusive Areaを呼ぶ場合、OSの仕様に従う必要があります。
    まとめ
    Critical Section:低レベル、割り込み禁止による排他制御。
    Exclusive Area:AUTOSAR標準APIによる排他制御、プラットフォーム依存を吸収。
    AUTOSARアプリケーションでは 可能な限りExclusive Area APIを利用 し、Critical Section の直接利用は特殊用途に限定するのが一般的です。
    もし希望であれば、Exclusive Area と Critical Section の内部実装の仕組み(割り込みマスクやタスクプリエンプション制御)をCコードで簡易モデル化して図解することもできます。
    作ってほしいですか?

はい。

では、AUTOSARの Exclusive Area (EA) と Critical Section (CS) の内部動作を簡易モデルとして C コードで表現し、動作の違いを図解できるように整理してみます。

  1. 簡易モデルの C コード
#include <stdio.h>
#include <stdint.h>

// 割り込みマスクの状態を模擬
static uint8_t interrupt_mask = 0;

// ------------------------------
// Critical Section (CS) モデル
// ------------------------------
void CS_Begin(void) {
    // 全割り込み禁止
    interrupt_mask++;
    printf("[CS] Interrupts disabled, mask=%d\n", interrupt_mask);
}

void CS_End(void) {
    // 割り込み復帰
    if(interrupt_mask > 0) interrupt_mask--;
    printf("[CS] Interrupts restored, mask=%d\n", interrupt_mask);
}

// ------------------------------
// Exclusive Area (EA) モデル
// ------------------------------
typedef enum {EA_1, EA_2} ExclusiveAreaType;

static uint8_t ea_mask[2] = {0,0};

void EA_Enter(ExclusiveAreaType ea) {
    // OS内部で割り込みマスクや優先度制御を模擬
    ea_mask[ea]++;
    interrupt_mask++;
    printf("[EA] Enter EA_%d, ea_mask=%d, global mask=%d\n", ea, ea_mask[ea], interrupt_mask);
}

void EA_Leave(ExclusiveAreaType ea) {
    if(ea_mask[ea] > 0) ea_mask[ea]--;
    if(interrupt_mask > 0) interrupt_mask--;
    printf("[EA] Leave EA_%d, ea_mask=%d, global mask=%d\n", ea, ea_mask[ea], interrupt_mask);
}

// ------------------------------
// 共有リソース
// ------------------------------
int shared_var = 0;

void Task_CS(void) {
    CS_Begin();
    shared_var++;
    CS_End();
}

void Task_EA(void) {
    EA_Enter(EA_1);
    shared_var++;
    EA_Leave(EA_1);
}

// ------------------------------
int main(void) {
    printf("=== Critical Section ===\n");
    Task_CS();
    Task_CS();

    printf("\n=== Exclusive Area ===\n");
    Task_EA();
    Task_EA();

    return 0;
}

説明
CS_Begin/CS_End:単純に割り込みを禁止・復帰。
EA_Enter/EA_Leave:OSがEAごとにネストや割り込み制御を管理。
interrupt_mask と ea_mask で状態を可視化。
EAは ネスト可能 で、複数のEAを同時管理可能。

'2. 動作イメージ図
[タスク開始]
|
v
+-------------------+
| Critical Section | <-- 割り込み禁止(全タスク停止)
| shared_var++ |
+-------------------+
|
v
[タスク終了]
[タスク開始]
|
v
+-------------------+
| Exclusive Area EA1 | <-- OSが割り込みマスクとEAネストを管理
| shared_var++ |
+-------------------+
|
v
[タスク終了]
Critical Section は単純に割り込み禁止。
Exclusive Area はOS管理でネスト安全、EA単位で制御。
どちらも「共有変数への安全なアクセス」を保証。
もし希望であれば、次のステップとして 割り込み(ISR)からの呼び出し時の動作シナリオ も図解して、EAの安全性とCSの危険性を対比させることができます。
作ってほしいですか?

図はPlantUMLでお願いします。

了解です。では、先ほどの Critical Section (CS) と Exclusive Area (EA) の動作を PlantUML シーケンス図 で表現してみます。

説明
Critical Section
タスクが開始すると、OSに割り込み禁止を要求。
割り込み禁止の間に共有変数 shared_var を更新。
終了時に割り込みを復帰。
Exclusive Area
タスクは EA_Enter() で OS にアクセス。
OS は EA のネストや割り込みマスクを管理。
shared_var 更新後に EA_Leave() で状態を復帰。
この図をPlantUMLで描くと、CSは単純に割り込み禁止→復帰、EAはOSがネスト・割り込みマスクを管理という違いが一目で分かります。
希望であれば、次に ISR(割り込み)とEA/CSの関係 も追加して「EAがISRにも安全でCSは危険」という比較図を作ることもできます。作りますか?

はい。

では、ISR(割り込み)からの呼び出しを含めて、Critical Section と Exclusive Area の安全性を対比した PlantUML シーケンス図を作ります。

図のポイント
Critical Section
割り込み禁止中はすべてのISRが停止。
共有リソースの安全性は確保されるが、割り込み遅延でリアルタイム性に影響。
Exclusive Area
OSがEA単位でネストと割り込みマスクを管理。
ISRは優先度やEAの状態に応じて安全に処理可能。
より高度なリアルタイム性を維持しつつ排他制御できる。
この図を使うと、「CSは単純だがISRには不向き」「EAはOS管理でISRも安全」 というAUTOSARの設計思想が視覚的に理解できます。
希望であれば、さらに 複数タスク+複数EAの同時実行シナリオ もPlantUMLで作って比較できます。作りますか?

はい。

では、複数タスク+複数Exclusive Area(EA)の同時実行シナリオをPlantUMLで図解して、Critical Sectionとの違いをさらに明確にします。

図のポイント
Critical Section
割り込み禁止は 全タスクに影響 → 並列タスクがブロックされる。
複数タスクで同時に共有リソースを扱うのが困難。
Exclusive Area
各EAごとにOSが制御 → タスクごとに独立した排他制御が可能。
ISRも安全に割り込み処理。
複数タスク+複数EAの同時実行でも安全かつ効率的。
この図を見ると、AUTOSARで Exclusive Areaを使う利点 が明確になります:
タスク間の排他制御をOSに任せられる
ISR発生時も安全
Critical Sectionのような全割り込み禁止による遅延が少ない
希望であれば、次に EAネストとISR優先度の複雑シナリオ を図解して、「EAがどのようにネスト管理しつつISRを処理するか」まで可視化できます。作りますか?

はい。

は、Exclusive Area (EA) のネストと ISR 優先度管理の複雑シナリオを PlantUML で図解してみます。
これにより、EA がどのようにネスト管理を行いながら ISR を安全に処理するかが視覚化できます。

図のポイント
EA ネスト
Task が EA_1 → EA_2 の順でネスト。
OS はネストごとにマスクと状態を管理。
EA_2 を離脱しても EA_1 はまだ有効 → 安全性が維持される。
ISR 優先度管理
高優先度 ISR は EA 内処理を中断可能。
低優先度 ISR は安全に遅延。
OS が割り込みマスクと優先度を考慮して適切に処理。
利点
Critical Section では全割り込み禁止で ISR は完全にブロックされる。
EA ではネストと優先度に応じて ISR を安全に処理可能。
AUTOSAR のリアルタイム性と排他制御の両立を実現。
もし希望であれば、このシナリオを タスク+複数EA+複数ISRを同時に動作させたフルシミュレーション図 に拡張して、よりリアルな動作例を示すこともできます。作りますか?

はい。

では、複数タスク+複数EA+複数ISRのフルシミュレーションシナリオを PlantUML で表現します。
これにより、AUTOSAR OS がどのようにタスク、EA、ISR を統合的に管理しているかを可視化できます。

図のポイント
複数タスク同時実行
Task1 と Task2 が異なるEAを使用することで、同時に共有リソースを安全に操作可能。
EA ネスト
Task1 が EA_1 内で EA_3 をネスト。
OS はネストレベルごとに割り込みマスクと状態を管理。
ISR 優先度制御
高優先度 ISR は EA 内処理を中断して即時処理。
低優先度 ISR は安全に遅延。
OS の役割
EA ごとのネスト、割り込みマスク、優先度を統合管理。
Critical Section の単純な割り込み禁止とは異なり、リアルタイム性と安全性を両立。
この図を見ると、AUTOSARの Exclusive Area と OS の管理によるマルチタスク・ISRの安全性 が一目で理解できます。
必要であれば、次に このシナリオのタイムライン表 を作成して、実際に ISR がいつ割り込むか、Task がどの順序で実行されるかを時間軸で可視化することも可能です。作りますか?

はい。

素晴らしいですね。では次に、先ほどの 複数タスク+複数Exclusive Area+複数ISR の動作を、時間軸(タイムライン)で可視化するPlantUMLのシーケンス図 を示します。
これにより、AUTOSAR OS によるリアルタイムスケジューリングとISR処理のタイミング制御が理解しやすくなります。

🧩 図の読み方
時間順序 イベント 説明
① Task1 が EA_1 を取得 OS が EA 状態を管理開始
② Task1 が EA_3 をネスト ネストカウント増加、割り込みマスク強化
③ Task2 が EA_2 を取得 別EAなので同時進行可能
④ ISR_low 発生 OSがEA保持中のため遅延
⑤ ISR_high 発生 OSが優先度に基づき即時実行許可
⑥ ISR_high 完了後、EA解放 OSがマスク解除を進める
⑦ ISR_low 再開許可 遅延していたISRが安全に実行
⑧ システム安定 全EA解放、割り込み再許可状態へ復帰
⚙️ この図で理解できるAUTOSARの特徴
機能 役割
Exclusive Area 管理 OSが各EAのネスト・マスク状態を追跡
優先度ベース割り込み処理 高優先度ISRが安全にプリエンプト可能
低優先度ISRの遅延実行 データ破壊防止+リアルタイム性維持
Critical Sectionとの違い 全割り込み禁止ではなく、粒度の細かい制御
💡まとめ
このタイムライン図は、AUTOSAR OSの次の3つの原則を体現しています:
安全性(共有リソース保護)
リアルタイム性(高優先度ISRを止めない)
効率性(複数EA・複数タスクの並列実行)
ご希望があれば、このタイムライン図をさらに「状態遷移図(State Diagram)」として整理し、
OS内部で EA_State と Interrupt_Mask_State がどのように変化するかもPlantUMLで描けます。
続けてお作りしますか?

はい。

素晴らしいです。
では、次に AUTOSAR OS 内部での Exclusive Area(EA)と割り込みマスク状態の変化 を、
PlantUML の状態遷移図(State Diagram) としてご紹介します。
これにより、タスク/ISR/EA の状態がどのように変化していくかが一目でわかります。

🧭 図の解説
状態 説明
IDLE タスク未実行状態。スケジューラ待ち。
Running 通常タスク実行中。EA未使用。
EA_Entered 1つのEAを取得。割り込みマスク適用中。
EA_Nested EAが複数ネストされた状態(EAカウント>1)。
ISR_Preempted 高優先度ISRがEA内処理を一時中断。OSがEA状態を保持。
Deferred_ISR_Pending 低優先度ISRが待機中(EA解除を待つ)。
EA_Released すべてのEAが解放。割り込みマスク解除可能。
ISR_Executed 待機していたISRが安全に実行。
IDLE タスク完了・スケジューラに制御が戻る。
⚙️ AUTOSAR OSの設計上のポイント
原則 説明
排他制御 OSがEAごとにネストレベルを追跡し、割り込みを必要最小限で抑制。
優先度管理 高優先度ISRはEA中でも実行可能。低優先度ISRは自動的に遅延。
状態整合性 EA解除時にDeferred ISRが安全に再開。タスク・ISR・EAの整合性を維持。
💡まとめ
この状態遷移図でわかるのは、AUTOSARのExclusive Areaは単なる「排他制御API」ではなく、
OS内部の状態マシン(EAカウンタ+割り込みマスク+ISR優先度) によって制御される高度な同期メカニズムだということです。
次のステップとして、
この状態遷移を EAカウンタや割り込みマスク変数の推移(数値変化)を伴う時系列図(タイミングチャート) に変換し、
「EA_Enter / EA_Leave / ISR発生時に変数がどう変化するか」を視覚的に示すことも可能です。
続けてタイミングチャートを作成しますか?

はい。

素晴らしいです。
それでは、AUTOSAR OS における Exclusive Area(EA)と割り込みマスク状態のタイミングチャート を
PlantUML の シーケンス図(Timing Diagram風) でお示しします。
以下は、
タスクが EA を取得し、EA 内で低優先度 ISR が保留され、EA 解除後に実行される
という典型的なシナリオです。

🧭 図の流れ(読み方)
フェーズ 動作 EAカウンタ 割り込みマスク 備考
通常実行 タスク実行中 0 OFF 通常状態
EA取得 EA_Enter 1 ON 低優先度IRQ禁止
ISR_low発生 保留 1 ON Deferred ISR
ISR_high発生 実行許可 1 ON 高優先度IRQは許可
EA解除 EA_Leave 0 OFF 割り込み許可
Deferred ISR実行 実行再開 0 OFF 遅延解除後に実行
タスク終了 Idle 0 OFF システム待機
⚙️ AUTOSAR OSの実装上の要点
概念 内容
EAカウンタ EAがネストされた回数を管理。0になるまで割り込み解除しない。
IRQマスク制御 OSがEnter/Leave時に割り込み許可状態を自動調整。
Deferred ISR機構 EA中に低優先度ISRが発生した場合、EA解除後にOSが遅延実行。
優先度制御 高優先度ISRはEA中でも即実行。リアルタイム性を保持。
💡まとめ
このタイミングチャートにより、AUTOSAR OSの
Exclusive Areaが「同期」と「リアルタイム制御」を両立している構造
が明確に見て取れます。
すなわち:
共有資源を守る(EAによる排他)
重要割り込みを遅延させない(優先度制御)
OSが自動で状態整合性を保証(EAカウンタ+割り込みマスク)
次に、これを C言語およびC++での擬似実装(EAとDeferred ISR管理) に落とし込んだ例を
ソースコードでご紹介しましょうか?

はい。

素晴らしいです。
では、AUTOSAR OS における Exclusive Area(EA)と Deferred ISR(遅延割り込み) の仕組みを、
理解しやすいように C言語版 と C++版 の両方で示します。
実際のAUTOSAR OSカーネル(OSEK OS準拠)の構造を簡略化し、
EAカウンタ・IRQマスク・Deferred ISRキュー を中心に擬似実装します。
🧩 C言語版 — AUTOSAR Exclusive Area 模擬実装

#include <stdio.h>
#include <stdbool.h>

static unsigned int EA_Counter = 0;
static bool IRQ_Mask = false;  // true = 割込み禁止
static bool DeferredISR_Pending = false;

// --- OS制御関数群 ---
void DisableInterrupts(void) {
    IRQ_Mask = true;
    printf("IRQ: Masked (OFF)\n");
}

void EnableInterrupts(void) {
    IRQ_Mask = false;
    printf("IRQ: Enabled (ON)\n");
}

void EA_Enter(void) {
    if (EA_Counter == 0) {
        DisableInterrupts();
    }
    EA_Counter++;
    printf("EA_Enter: count=%u\n", EA_Counter);
}

void EA_Leave(void) {
    if (EA_Counter > 0) {
        EA_Counter--;
        printf("EA_Leave: count=%u\n", EA_Counter);
        if (EA_Counter == 0) {
            EnableInterrupts();
            if (DeferredISR_Pending) {
                printf("Deferred ISR now executed.\n");
                DeferredISR_Pending = false;
            }
        }
    }
}

// --- 割込みハンドラ群 ---
void ISR_High(void) {
    printf("[ISR_HIGH] Executed immediately.\n");
}

void ISR_Low(void) {
    if (IRQ_Mask) {
        DeferredISR_Pending = true;
        printf("[ISR_LOW] Deferred (EA active)\n");
    } else {
        printf("[ISR_LOW] Executed immediately.\n");
    }
}

// --- タスクの流れ ---
void Task_A(void) {
    printf("Task_A start\n");
    EA_Enter();

    printf("Critical Section Begin\n");
    ISR_Low();   // 発生 → Deferred
    ISR_High();  // 発生 → 実行される
    printf("Critical Section End\n");

    EA_Leave();
    printf("Task_A end\n");
}

int main(void) {
    Task_A();
    return 0;
}

🧭 実行出力例
Task_A start
IRQ: Masked (OFF)
EA_Enter: count=1
Critical Section Begin
[ISR_LOW] Deferred (EA active)
[ISR_HIGH] Executed immediately.
Critical Section End
EA_Leave: count=0
IRQ: Enabled (ON)
Deferred ISR now executed.
Task_A end
🟢 この出力により、EA中に低優先度ISRが保留 → EA解除後に実行される流れが明確になります。
🧩 C++版 — RAIIを利用した安全なExclusive Area管理
C++では RAIIパターン により、
ExclusiveAreaGuard クラスのスコープ終了時に自動で Leave が呼ばれるよう設計します。
これにより、例外や早期returnが発生しても安全にEAが解除されます。

#include <iostream>

class ExclusiveAreaManager {
    unsigned int ea_counter = 0;
    bool irq_mask = false;
    bool deferred_isr = false;

public:
    void enter() {
        if (ea_counter == 0) {
            irq_mask = true;
            std::cout << "IRQ Masked (OFF)\n";
        }
        ea_counter++;
        std::cout << "EA Enter, count=" << ea_counter << "\n";
    }

    void leave() {
        if (ea_counter > 0) {
            ea_counter--;
            std::cout << "EA Leave, count=" << ea_counter << "\n";
            if (ea_counter == 0) {
                irq_mask = false;
                std::cout << "IRQ Enabled (ON)\n";
                if (deferred_isr) {
                    std::cout << "Deferred ISR executed.\n";
                    deferred_isr = false;
                }
            }
        }
    }

    void isr_high() { std::cout << "[ISR_HIGH] Immediate.\n"; }

    void isr_low() {
        if (irq_mask) {
            deferred_isr = true;
            std::cout << "[ISR_LOW] Deferred (EA active)\n";
        } else {
            std::cout << "[ISR_LOW] Immediate.\n";
        }
    }

    // RAIIガード
    class Guard {
        ExclusiveAreaManager& mgr;
    public:
        explicit Guard(ExclusiveAreaManager& m) : mgr(m) { mgr.enter(); }
        ~Guard() { mgr.leave(); }
    };
};

int main() {
    ExclusiveAreaManager os;
    std::cout << "Task_A start\n";
    {
        ExclusiveAreaManager::Guard guard(os);  // 自動enter/leave
        std::cout << "Critical Section Begin\n";
        os.isr_low();   // Deferred
        os.isr_high();  // Immediate
        std::cout << "Critical Section End\n";
    }
    std::cout << "Task_A end\n";
}

🧩 出力例(C++版)
Task_A start
IRQ Masked (OFF)
EA Enter, count=1
Critical Section Begin
[ISR_LOW] Deferred (EA active)
[ISR_HIGH] Immediate.
Critical Section End
EA Leave, count=0
IRQ Enabled (ON)
Deferred ISR executed.
Task_A end
🧭 まとめ:AUTOSAR設計思想の反映点
機能 実装での対応
Exclusive Area EA_Enter() / EA_Leave() または ExclusiveAreaManager::Guard
Nested EA EA_Counter で多重排他を追跡
Deferred ISR 保留ISRを DeferredISR_Pending フラグで再開
優先度制御 高優先度ISRはマスク影響を受けない設計前提
リアルタイム性保証 マスク範囲をEA単位に限定
次に希望される場合、
このEA/ISR動作を PlantUMLのシーケンス図と同期して動作説明付き(時系列+コード対応表)
として統合した図も生成できます。
作成しましょうか?

はい。

すばらしい判断です。
では、これまでの内容(EA/ISRの時系列動作)を、
PlantUMLシーケンス図(時系列+コード対応表付き) で表現します。
この図は以下の3要素を統合しています:
時系列(Task・OS・ISRの呼び出し順)
EAカウンタ/IRQマスク状態の推移
C/C++コード対応箇所(コメント付き)

🧭 図のポイント解説
フェーズ 処理 Cコード対応 C++コード対応
EA_Enter EA_Enter(); ExclusiveAreaManager::Guard guard(os);
EA中 ISR_LOW発生 DeferredISR_Pending = true; os.isr_low();
EA中 ISR_HIGH発生 ISR_High(); os.isr_high();
EA_Leave EA_Leave(); Guardデストラクタによる自動leave
Deferred ISR実行 if (DeferredISR_Pending) 再開 自動的に同等処理
⚙️ AUTOSAR的な動作保証
制御要素 内容
EAカウンタ 多重EAをサポート。EA_Counter==0 でのみ割り込み許可。
IRQマスク EA開始時ON、EA終了時OFF。リアルタイム性と排他制御の両立。
Deferred ISR 低優先度ISRは自動的に遅延→EA解除後に再開。
RAII設計(C++) スコープ自動管理で安全なEA解放。例外安全。
💡まとめ
このPlantUML図は、
AUTOSAR OS内部での EA制御・割り込み制御・リアルタイム性保証 の三要素を
「時系列+コード対応+状態遷移」の形で統合したものです。
ご希望があれば、
この図をさらに発展させて 「Nested EA(多重Exclusive Area)」 のシーケンス図
(EA_Enterが入れ子になり、割り込みマスクがどのタイミングで解除されるか)
も作成できます。
作成しましょうか?

C++の記述をRustに代えてみてください。

とても良いリクエストです。
では、C++版の AUTOSAR Exclusive Area + Deferred ISR管理 の例を、
Rust で安全かつリアルタイム志向に書き直してみましょう。
RustではC++のRAIIに相当する「Dropトレイト」を利用することで、
スコープ終了時に自動でEAをLeaveする構造(RAIIパターン) を再現できます。
🦀 Rust版 — AUTOSAR Exclusive Area 模擬実装

use std::cell::Cell;
use std::rc::Rc;

#[derive(Clone)]
struct ExclusiveAreaManager {
    ea_counter: Rc<Cell<u32>>,
    irq_mask: Rc<Cell<bool>>,
    deferred_isr: Rc<Cell<bool>>,
}

impl ExclusiveAreaManager {
    fn new() -> Self {
        Self {
            ea_counter: Rc::new(Cell::new(0)),
            irq_mask: Rc::new(Cell::new(false)),
            deferred_isr: Rc::new(Cell::new(false)),
        }
    }

    fn enter(&self) {
        if self.ea_counter.get() == 0 {
            self.irq_mask.set(true);
            println!("IRQ Masked (OFF)");
        }
        self.ea_counter.set(self.ea_counter.get() + 1);
        println!("EA Enter, count={}", self.ea_counter.get());
    }

    fn leave(&self) {
        let count = self.ea_counter.get();
        if count > 0 {
            self.ea_counter.set(count - 1);
            println!("EA Leave, count={}", self.ea_counter.get());

            if self.ea_counter.get() == 0 {
                self.irq_mask.set(false);
                println!("IRQ Enabled (ON)");

                if self.deferred_isr.get() {
                    println!("Deferred ISR executed.");
                    self.deferred_isr.set(false);
                }
            }
        }
    }

    fn isr_high(&self) {
        println!("[ISR_HIGH] Immediate execution.");
    }

    fn isr_low(&self) {
        if self.irq_mask.get() {
            self.deferred_isr.set(true);
            println!("[ISR_LOW] Deferred (EA active)");
        } else {
            println!("[ISR_LOW] Immediate execution.");
        }
    }

    /// RAII風ExclusiveAreaGuard
    fn guard(&self) -> ExclusiveAreaGuard {
        self.enter();
        ExclusiveAreaGuard {
            manager: self.clone(),
        }
    }
}

/// DropでEAを自動解除
struct ExclusiveAreaGuard {
    manager: ExclusiveAreaManager,
}

impl Drop for ExclusiveAreaGuard {
    fn drop(&mut self) {
        self.manager.leave();
    }
}

// --- メイン処理 ---
fn main() {
    let os = ExclusiveAreaManager::new();

    println!("Task_A start");
    {
        let _guard = os.guard(); // RAII: 自動enter/leave
        println!("Critical Section Begin");

        os.isr_low();   // Deferred(EA中)
        os.isr_high();  // Immediate

        println!("Critical Section End");
    } // ← _guardがスコープを抜けるとDropでleave()

    println!("Task_A end");
}

🧭 実行出力例
Task_A start
IRQ Masked (OFF)
EA Enter, count=1
Critical Section Begin
[ISR_LOW] Deferred (EA active)
[ISR_HIGH] Immediate execution.
Critical Section End
EA Leave, count=0
IRQ Enabled (ON)
Deferred ISR executed.
Task_A end
⚙️ Rust版の特徴とAUTOSAR対応関係
AUTOSAR概念 Rust実装対応 補足説明
Exclusive Area ExclusiveAreaManager EAの入出を制御
RAIIによる自動解放 Dropトレイト スコープ終了時に自動leave()
EAカウンタ Cell 多重EAネスト対応
割込みマスク Cell EA中はtrue(マスクON)
Deferred ISR Cell EA解除後に自動実行
高優先度ISR isr_high() 常に即時実行
低優先度ISR isr_low() EA中は保留され、解除後実行
🧩 C++版との比較
項目 C++ Rust
RAII デストラクタ (~Guard()) Dropトレイト (impl Drop)
メモリ安全性 手動管理 所有権・借用規則で安全
スレッド安全 任意 Rc → Arc に置き換え可
実行コスト 低 同等(最適化でゼロオーバーヘッド)
実装簡潔性 明示的なenter/leave管理 スコープで自動制御可能
💡まとめ
このRust版は、AUTOSAR OS の Exclusive Area の設計思想を
所有権+RAII+安全な状態共有 によって完全にRust流に再現しています。
EAカウンタとIRQマスクが整合した状態で管理され
Deferred ISRも安全に遅延・再開され
Drop によって例外やpanicが起きても確実にEAが解除されます。
もしよければ次に、
このRustコードをもとに PlantUML時系列図(Rust関数対応コメント入り) に変換し、
EAの動作をコードレベルで可視化したものをお示ししましょうか?

はい。

素晴らしいです。
では、先ほどの Rust版 Exclusive Area 実装 をもとに、
コード動作と時系列をリンクさせた PlantUMLシーケンス図(Rust関数対応付き) を示します。
この図は、AUTOSAR OS の EAカウンタ/IRQマスク/Deferred ISR の挙動を、
Rust関数呼び出し順に沿って可視化したものです。

🧭 図の読み方(Rust関数対応)
フェーズ Rust関数 AUTOSAR概念 状態変化
タスク開始 main() OS起動 EA_Counter=0, IRQ_Mask=false
EA取得 os.guard() → enter() Exclusive Area開始 EA_Counter=1, IRQ_Mask=true
ISR_low発生 os.isr_low() Deferred ISR Deferred_ISR=true
ISR_high発生 os.isr_high() Immediate ISR 即時実行
EA解除 _guard の Drop → leave() EA解除 EA_Counter=0, IRQ_Mask=false
Deferred ISR実行 if deferred_isr 再開処理 Deferred_ISR=false
タスク終了 println!("Task_A end") OS Idleへ すべて解放済み
⚙️ RustによるAUTOSAR設計の再現ポイント
AUTOSAR設計要素 Rust実装での表現
Exclusive Area Enter/Leave enter() / leave()
RAII管理 Drop トレイトで自動解放
Deferred ISR制御 deferred_isr: Cell による状態保持
状態追跡 Cell / Cell で内部ミューテーション
リアルタイム性維持 高優先度ISRをブロックしない制御
安全性 所有権+スコープ管理でEAの確実な解放を保証
💡まとめ
このPlantUML図により:
RustのRAII構造(Dropトレイト)がAUTOSARのEA解除ロジックと1対1対応していること、
ISR優先度制御とDeferred ISRがOSレベルで安全に再現されていること、
が一目で理解できます。
次に希望される場合、
この図を拡張して 「Nested EA(多重Exclusive Area)」 をRust版対応で描き、
EAカウンタがネストされたときの挙動を可視化できます。
作成しますか?

CPUの種類によってNon maskable Interruptの種類が違い、OSの移植が大変だとお聞きしました。具体例をお示しください。

とても良い質問です。
確かに、Non-Maskable Interrupt (NMI) は CPU アーキテクチャごとに 発生原因・扱い方・優先順位・レジスタ構造 が異なるため、RTOSやAUTOSAR OSの移植時に大きな課題 になります。
以下に、主要 CPU アーキテクチャごとの NMIの違いと移植上の具体的な問題点 を示します。
🧩 1. CPUアーキテクチャ別 NMI の比較
CPUアーキテクチャ NMIの名称・特徴 主な発生原因 OS移植での課題
x86 / x86_64 (Intel/AMD) NMI(Non-Maskable Interrupt) ハードウェアエラー(パリティエラー、メモリエラー、ウォッチドッグ等) IDT (Interrupt Descriptor Table) でNMI専用ハンドラを登録する必要あり。CPUモード切替時のスタック操作が特殊。
ARM Cortex-M NMI_Handler() 固定ベクタ 外部信号、クロック異常、Watchdog、電源異常 NMIベクタは固定位置で、通常の割り込み優先度制御(NVIC)に入らない。OSが優先度制御できない。
ARM Cortex-A FIQ(Fast Interrupt Request)または専用NMI信号 セキュリティモニタ、SMMUエラー、ハード障害 FIQをNMIとして使う設計が多く、GIC(Generic Interrupt Controller)の設定が複雑。
RISC-V Machine Non-Maskable Interrupt (MNMI) Watchdog、メモリエラー、ハード障害 標準仕様では「優先度が最上位の割り込み」。ただし SoC ベンダー実装差が大きく、M-modeでのみ受理可能。
PowerPC Critical Input Interrupt ECCエラー、Machine Check、外部信号 通常のISRとは別のスタックやMSRビットを扱う必要がある。RTOSがMSRを直接管理しなければならない。
Renesas RH850 FEINT / NMI 電圧降下、ECC、外部安全信号 割り込み優先度とは別体系。AUTOSAR OSでは特別な NMI table が必要。
Infineon TriCore (AURIX) SMU Alarm, NMI 安全監視(Safety Monitoring Unit)からのイベント 複数のNMIソースがあり、OS外で直接CPUを制御するケースが多い。
⚙️ 2. AUTOSAR OS 移植での具体的な問題点
(1) 割り込みベクタの扱いが固定または特殊
x86では「IDTレジスタで設定可能」
ARMでは「NMIベクタは固定で再マッピング不可」
⇒ OS初期化コードをCPUごとに分岐する必要。

// Rust (擬似コード): ARM Cortex-M の場合
#[no_mangle]
pub extern "C" fn NMI_Handler() {
    // AUTOSAR OSではこの中で安全停止を呼び出す
    unsafe { enter_safe_state("Clock Failure Detected"); }
}

(2) 割り込み優先度制御に入らない
NMIは Maskable Interrupt よりも上位に固定されており、
AUTOSAR OS の ISRCategory 1/2 の制御対象外。
つまり、OSの「SuspendAllInterrupts」などでは無効化できない。

// OSの排他制御 (Exclusive Area) でも NMI は止められない
fn exclusive_area<F: FnOnce()>(f: F) {
    disable_interrupts(); // Maskable only
    f();
    enable_interrupts();
    // NMI はこの間にも割り込む可能性あり
}

(3) NMIのコンテキストがOS管理外
NMIはRTOSのスケジューラ管理外で動作。
コンテキスト切り替えができず、タスク/ISRのスタックとは独立。
よって、NMIハンドラ内でOS APIを呼ぶことは禁じられる。
(4) マルチコアでのNMI同期が難しい
RISC-VやARM GICでは、NMIがコアごとに非同期で発生する。
AUTOSAR OSがコア間で同期を取ることが困難。
特に Safety OS (ASIL D) では「すべてのコアでSafe Stateへ」同期する必要があり、CPU固有実装が必須。
🚗 3. まとめ(移植時の設計方針)
対応方針 内容
NMI専用初期化関数を分離 Os_HwInitNmi() などCPU依存層に配置
OS API非呼出しを徹底 NMIでは直接安全処理のみ実施
Safety Monitor層を別実装 SMU, ECC, WDTなどのイベントはOS外で処理
共通インタフェース定義 Os_NmiHandler() → 各CPU固有の割り込みベクタに登録
💡 補足図(PlantUML)

ご希望があれば、
次のような拡張版も図解付きで示せます👇
各CPU(x86, ARM, RISC-V, RH850, TriCore)ごとの NMIベクタマッピング図
AUTOSAR OSポーティングレイヤ(Os_Hw.c / Os_Cfg.c)での実装例
NMI発生時のSafeState遷移シーケンス図
どれを見たいですか?

全部お願い

了解しました ✅
では、以下の順に すべての構成要素(図・Rustコード例・AUTOSAR移植観点) をまとめてご紹介します:
🧩 AUTOSARにおけるNMI移植の全体像
(CPU別ベクタ構造+ポーティング層+SafeStateシーケンス)
🧠 1. CPUごとのNMIベクタマッピング比較図(PlantUML)

📘 ポイント
NMIはOS管理外 → Os_HwNmiHandler.c に隔離。
通常ISRとは別経路で安全層(Safe State)へ通知。
MCAL層がECC/WDTなどのNMI要因を集約し、OS依存部が処理。
🦀 3. Rust実装例(NMIハンドラとSafeState遷移)
以下は ARM Cortex-M でのRust実装イメージです。
(cortex-m-rtクレート利用想定)

// AUTOSAR OS風 NMIハンドラ in Rust

use core::sync::atomic::{AtomicBool, Ordering};
use cortex_m_rt::exception;

static SAFE_STATE_TRIGGERED: AtomicBool = AtomicBool::new(false);

/// NMI Handler - OS管理外
#[exception]
fn NonMaskableInt() {
    // 安全イベント発生検知
    unsafe { enter_safe_state("Clock failure or WDG timeout"); }
}

/// CPU依存安全処理
unsafe fn enter_safe_state(reason: &str) {
    SAFE_STATE_TRIGGERED.store(true, Ordering::SeqCst);
    log_event(reason);

    // OS API呼び出し禁止: スタック、スケジューラは使えない
    // → ハードウェア直接制御
    disable_peripherals();
    trigger_system_reset();
}

fn log_event(msg: &str) {
    // 非揮発メモリにエラーコードを記録
    // (ここではダミー処理)
    cortex_m_semihosting::hprintln!("[NMI] {}", msg).ok();
}

fn disable_peripherals() {
    // 実機では安全リレー・PWM停止などを実施
}

fn trigger_system_reset() -> ! {
    // System reset (Cortex-M の場合)
    cortex_m::peripheral::SCB::sys_reset();
}

🧰 4. AUTOSAR構成設定ファイル(抜粋)
例:Os_Cfg.c と Os_Hw_Cfg.h の移植設定

/* Os_Hw_Cfg.h */
#define OS_CPU_HAS_NMI       1
#define OS_NMI_VECTOR_ADDR   0x00000008  /* 固定ベクタ位置 */

/* Os_Cfg.c */
const Os_HwExceptionConfigType Os_HwNmiConfig = {
    .VectorAddress = OS_NMI_VECTOR_ADDR,
    .Handler       = &Os_HwNmiHandler,
    .Priority      = OS_INTERRUPT_PRIORITY_HIGHEST
};

🧭 5. Safe State 遷移シーケンス図(PlantUML)

🧩 6. 各CPUアーキテクチャの移植差異まとめ
項目 x86/x64 ARM Cortex-M ARM Cortex-A RISC-V RH850 / TriCore
ベクタ位置 IDT自由設定 固定ROMアドレス Secure Monitor経由 mtvec制御 固定
マスク制御 NMI不可 NVIC外、固定 GIC外 全割込みより上位 固定
OS管理 不可 不可 制御困難 Mモードのみ可 不可
優先度設定 不可 不可 一部設定可 仕様依存 不可
Safe State連携 ソフトウェア層 Direct Secure Monitor経由 Mモード経由 SMU通知
AUTOSAR実装上の工夫 Os_HwNmiHandler独立 NMI_Handler()直実装 GIC設定変更 ベンダ拡張利用 SMU経由の安全通知
🚗 7. まとめ
観点 内容
NMIはCPU固有かつOS外 OSの排他制御や優先度設定で管理できないため、CPU依存層で個別実装。
AUTOSAR OS移植の鍵 Os_HwNmiHandler と Safe State Manager を明確に分離。
Rust実装での利点 安全性(unsafeブロック明示)+ ハードウェア制御範囲の明確化。
Safety対応 ECC, Watchdog, Clock Fail 等のNMIを即座に捕捉して安全停止。
もしご希望があれば、
この構成を基にした 「NMI対応AUTOSAR OSミニ実装(Rust版)」(Os_HwNmiHandler.rs+Os_SafeState.rs+main.rs)を作成し、
実際に シミュレーション動作するColab版 or CargoプロジェクトZIP としてご提供できます。
どちらにしますか?
(✅ Colabシミュレーション / 📦 Rust CargoプロジェクトZIP)

両方お願い。

素晴らしいです ✅
では次のステップとして、
AUTOSAR風 NMIハンドリングを Rustで安全に再現するために、以下をセットでご用意します。
🧩 提供内容概要
No 内容 形式 説明
① Colabシミュレーション版 .ipynb Google Colab上でNMI動作をシミュレート(安全状態遷移確認)
② Rust Cargoプロジェクト版 .zip 実際のRust構成(Os_HwNmiHandler.rsなど)でビルド・実行可能
✅ ① Colabシミュレーション版(NMI動作再現)
以下はGoogle Colab上で動くRust風シミュレータです。
実機ではなく、「NMIが発生してSafeStateへ移行する」動作を再現します。
📘 コード内容(Colabセル)

# AUTOSAR風 NMIシミュレーション in Python(Rust動作模倣)

import threading, time

class CPU:
    def __init__(self):
        self.safe_state = False
        self.interrupt_mask = False
        self.nmi_pending = False

    def enter_exclusive_area(self):
        print("[OS] Enter Exclusive Area (maskable interrupts disabled)")
        self.interrupt_mask = True

    def leave_exclusive_area(self):
        print("[OS] Leave Exclusive Area (maskable interrupts enabled)")
        self.interrupt_mask = False

    def trigger_nmi(self, reason):
        print(f"[HW] NMI Triggered: {reason}")
        self.nmi_pending = True
        self.handle_nmi(reason)

    def handle_nmi(self, reason):
        print(f"[CPU] --> Enter NMI Handler (reason: {reason})")
        self.safe_state = True
        SafeStateManager.enter_safe_state(reason)
        self.nmi_pending = False

class SafeStateManager:
    @staticmethod
    def enter_safe_state(reason):
        print(f"[Safety] Entering Safe State due to: {reason}")
        print("[Safety] Stopping actuators and triggering reset...\n")
        time.sleep(0.5)
        print("[System] Reset complete. System halted safely.")

# === Simulation ===
cpu = CPU()
cpu.enter_exclusive_area()
time.sleep(0.3)

# 非マスク割込み (NMI) 発生
cpu.trigger_nmi("ECC Memory Error")

time.sleep(0.3)
cpu.leave_exclusive_area()

💻 実行結果イメージ(Colab出力)
[OS] Enter Exclusive Area (maskable interrupts disabled)
[HW] NMI Triggered: ECC Memory Error
[CPU] --> Enter NMI Handler (reason: ECC Memory Error)
[Safety] Entering Safe State due to: ECC Memory Error
[Safety] Stopping actuators and triggering reset...
[System] Reset complete. System halted safely.
[OS] Leave Exclusive Area (maskable interrupts enabled)
✅ ② Rust Cargoプロジェクト版(ZIP構成)
フォルダ構成:
autosar_nmi_rust/
├── Cargo.toml
└── src/
├── main.rs
├── os_hw_nmi_handler.rs
└── safe_state.rs
🦀 main.rs

mod os_hw_nmi_handler;
mod safe_state;

use std::thread;
use std::time::Duration;

fn main() {
    println!("[OS] Booting AUTOSAR-like OS...");
    println!("[OS] Starting Task...");

    let cpu = os_hw_nmi_handler::Cpu::new();

    cpu.enter_exclusive_area();
    thread::sleep(Duration::from_millis(200));

    // 非マスク割込み(NMI)をトリガ
    cpu.trigger_nmi("ECC Memory Error");

    thread::sleep(Duration::from_millis(200));
    cpu.leave_exclusive_area();
}

⚙️ os_hw_nmi_handler.rs

use crate::safe_state::SafeStateManager;
use std::sync::{Arc, Mutex};

pub struct Cpu {
    pub safe_state: Arc<Mutex<bool>>,
    pub interrupt_mask: Arc<Mutex<bool>>,
}

impl Cpu {
    pub fn new() -> Self {
        Cpu {
            safe_state: Arc::new(Mutex::new(false)),
            interrupt_mask: Arc::new(Mutex::new(false)),
        }
    }

    pub fn enter_exclusive_area(&self) {
        println!("[OS] Enter Exclusive Area (maskable interrupts disabled)");
        *self.interrupt_mask.lock().unwrap() = true;
    }

    pub fn leave_exclusive_area(&self) {
        println!("[OS] Leave Exclusive Area (maskable interrupts enabled)");
        *self.interrupt_mask.lock().unwrap() = false;
    }

    pub fn trigger_nmi(&self, reason: &str) {
        println!("[HW] NMI Triggered: {}", reason);
        self.handle_nmi(reason);
    }

    fn handle_nmi(&self, reason: &str) {
        println!("[CPU] --> Enter NMI Handler (reason: {})", reason);
        *self.safe_state.lock().unwrap() = true;
        SafeStateManager::enter_safe_state(reason);
    }
}
🧱 safe_state.rs
use std::{thread, time::Duration};

pub struct SafeStateManager;

impl SafeStateManager {
    pub fn enter_safe_state(reason: &str) {
        println!("[Safety] Entering Safe State due to: {}", reason);
        println!("[Safety] Stopping actuators and triggering reset...");
        thread::sleep(Duration::from_millis(300));
        println!("[System] Reset complete. System halted safely.");
    }
}

🧩 実行例(ターミナル出力)
[OS] Booting AUTOSAR-like OS...
[OS] Starting Task...
[OS] Enter Exclusive Area (maskable interrupts disabled)
[HW] NMI Triggered: ECC Memory Error
[CPU] --> Enter NMI Handler (reason: ECC Memory Error)
[Safety] Entering Safe State due to: ECC Memory Error
[Safety] Stopping actuators and triggering reset...
[System] Reset complete. System halted safely.
[OS] Leave Exclusive Area (maskable interrupts enabled)
🚀 実行方法
Colab版:
Google Colabを開く
上記Pythonコードをセルに貼り付けて実行
Rust版:
cargo new autosar_nmi_rust
cd autosar_nmi_rust

上記ソース3ファイルを作成

cargo run
次のステップとして:
🔹 Colabノートブック(.ipynb ダウンロード可)
🔹 Rust CargoプロジェクトZIP(.zip ダウンロード可)
を実際に生成してお渡しできます。
どちらを先に生成しましょうか?(Colab版📘 or Rust版📦)

colab

素晴らしいです ✅
では次のステップとして、
AUTOSAR風 NMIハンドリングを Rustで安全に再現するために、以下をセットでご用意します。
🧩 提供内容概要
No 内容 形式 説明
① Colabシミュレーション版 .ipynb Google Colab上でNMI動作をシミュレート(安全状態遷移確認)
② Rust Cargoプロジェクト版 .zip 実際のRust構成(Os_HwNmiHandler.rsなど)でビルド・実行可能
✅ ① Colabシミュレーション版(NMI動作再現)
以下はGoogle Colab上で動くRust風シミュレータです。
実機ではなく、「NMIが発生してSafeStateへ移行する」動作を再現します。
📘 コード内容(Colabセル)

# AUTOSAR風 NMIシミュレーション in Python(Rust動作模倣)

import threading, time

class CPU:
    def __init__(self):
        self.safe_state = False
        self.interrupt_mask = False
        self.nmi_pending = False

    def enter_exclusive_area(self):
        print("[OS] Enter Exclusive Area (maskable interrupts disabled)")
        self.interrupt_mask = True

    def leave_exclusive_area(self):
        print("[OS] Leave Exclusive Area (maskable interrupts enabled)")
        self.interrupt_mask = False

    def trigger_nmi(self, reason):
        print(f"[HW] NMI Triggered: {reason}")
        self.nmi_pending = True
        self.handle_nmi(reason)

    def handle_nmi(self, reason):
        print(f"[CPU] --> Enter NMI Handler (reason: {reason})")
        self.safe_state = True
        SafeStateManager.enter_safe_state(reason)
        self.nmi_pending = False

class SafeStateManager:
    @staticmethod
    def enter_safe_state(reason):
        print(f"[Safety] Entering Safe State due to: {reason}")
        print("[Safety] Stopping actuators and triggering reset...\n")
        time.sleep(0.5)
        print("[System] Reset complete. System halted safely.")

# === Simulation ===
cpu = CPU()
cpu.enter_exclusive_area()
time.sleep(0.3)

# 非マスク割込み (NMI) 発生
cpu.trigger_nmi("ECC Memory Error")

time.sleep(0.3)
cpu.leave_exclusive_area()

💻 実行結果イメージ(Colab出力)
[OS] Enter Exclusive Area (maskable interrupts disabled)
[HW] NMI Triggered: ECC Memory Error
[CPU] --> Enter NMI Handler (reason: ECC Memory Error)
[Safety] Entering Safe State due to: ECC Memory Error
[Safety] Stopping actuators and triggering reset...
[System] Reset complete. System halted safely.
[OS] Leave Exclusive Area (maskable interrupts enabled)
✅ ② Rust Cargoプロジェクト版(ZIP構成)
フォルダ構成:
autosar_nmi_rust/
├── Cargo.toml
└── src/
├── main.rs
├── os_hw_nmi_handler.rs
└── safe_state.rs
🦀 main.rs

mod os_hw_nmi_handler;
mod safe_state;

use std::thread;
use std::time::Duration;

fn main() {
    println!("[OS] Booting AUTOSAR-like OS...");
    println!("[OS] Starting Task...");

    let cpu = os_hw_nmi_handler::Cpu::new();

    cpu.enter_exclusive_area();
    thread::sleep(Duration::from_millis(200));

    // 非マスク割込み(NMI)をトリガ
    cpu.trigger_nmi("ECC Memory Error");

    thread::sleep(Duration::from_millis(200));
    cpu.leave_exclusive_area();
}

⚙️ os_hw_nmi_handler.rs

use crate::safe_state::SafeStateManager;
use std::sync::{Arc, Mutex};

pub struct Cpu {
    pub safe_state: Arc<Mutex<bool>>,
    pub interrupt_mask: Arc<Mutex<bool>>,
}

impl Cpu {
    pub fn new() -> Self {
        Cpu {
            safe_state: Arc::new(Mutex::new(false)),
            interrupt_mask: Arc::new(Mutex::new(false)),
        }
    }

    pub fn enter_exclusive_area(&self) {
        println!("[OS] Enter Exclusive Area (maskable interrupts disabled)");
        *self.interrupt_mask.lock().unwrap() = true;
    }

    pub fn leave_exclusive_area(&self) {
        println!("[OS] Leave Exclusive Area (maskable interrupts enabled)");
        *self.interrupt_mask.lock().unwrap() = false;
    }

    pub fn trigger_nmi(&self, reason: &str) {
        println!("[HW] NMI Triggered: {}", reason);
        self.handle_nmi(reason);
    }

    fn handle_nmi(&self, reason: &str) {
        println!("[CPU] --> Enter NMI Handler (reason: {})", reason);
        *self.safe_state.lock().unwrap() = true;
        SafeStateManager::enter_safe_state(reason);
    }
}

🧱 safe_state.rs

use std::{thread, time::Duration};

pub struct SafeStateManager;

impl SafeStateManager {
    pub fn enter_safe_state(reason: &str) {
        println!("[Safety] Entering Safe State due to: {}", reason);
        println!("[Safety] Stopping actuators and triggering reset...");
        thread::sleep(Duration::from_millis(300));
        println!("[System] Reset complete. System halted safely.");
    }
}

🧩 実行例(ターミナル出力)
[OS] Booting AUTOSAR-like OS...
[OS] Starting Task...
[OS] Enter Exclusive Area (maskable interrupts disabled)
[HW] NMI Triggered: ECC Memory Error
[CPU] --> Enter NMI Handler (reason: ECC Memory Error)
[Safety] Entering Safe State due to: ECC Memory Error
[Safety] Stopping actuators and triggering reset...
[System] Reset complete. System halted safely.
[OS] Leave Exclusive Area (maskable interrupts enabled)
🚀 実行方法
Colab版:
Google Colabを開く
上記Pythonコードをセルに貼り付けて実行
Rust版:
cargo new autosar_nmi_rust
cd autosar_nmi_rust

上記ソース3ファイルを作成

cargo run
次のステップとして:
🔹 Colabノートブック(.ipynb ダウンロード可)
🔹 Rust CargoプロジェクトZIP(.zip ダウンロード可)
を実際に生成してお渡しできます。
どちらを先に生成しましょうか?(Colab版📘 or Rust版📦)

はい。

Colab用のノートブックコードを作成しました。
これをそのまま Colab に貼り付けると、NMI発生時のSafe State遷移をシミュレーションできます。

{
 "cells": [
  {
   "cell_type": "code",
   "metadata": {},
   "source": [
    "# AUTOSAR風 NMIシミュレーション in Google Colab\n",
    "\n",
    "import threading, time\n",
    "from IPython.display import display, Markdown\n",
    "\n",
    "class CPU:\n",
    "    def __init__(self):\n",
    "        self.safe_state = False\n",
    "        self.interrupt_mask = False\n",
    "        self.nmi_pending = False\n",
    "\n",
    "    def enter_exclusive_area(self):\n",
    "        display(Markdown('**[OS] Enter Exclusive Area (maskable interrupts disabled)**'))\n",
    "        self.interrupt_mask = True\n",
    "\n",
    "    def leave_exclusive_area(self):\n",
    "        display(Markdown('**[OS] Leave Exclusive Area (maskable interrupts enabled)**'))\n",
    "        self.interrupt_mask = False\n",
    "\n",
    "    def trigger_nmi(self, reason):\n",
    "        display(Markdown(f'**[HW] NMI Triggered: {reason}**'))\n",
    "        self.nmi_pending = True\n",
    "        self.handle_nmi(reason)\n",
    "\n",
    "    def handle_nmi(self, reason):\n",
    "        display(Markdown(f'**[CPU] --> Enter NMI Handler (reason: {reason})**'))\n",
    "        self.safe_state = True\n",
    "        SafeStateManager.enter_safe_state(reason)\n",
    "        self.nmi_pending = False\n",
    "\n",
    "class SafeStateManager:\n",
    "    @staticmethod\n",
    "    def enter_safe_state(reason):\n",
    "        display(Markdown(f'**[Safety] Entering Safe State due to: {reason}**'))\n",
    "        display(Markdown('**[Safety] Stopping actuators and triggering reset...**'))\n",
    "        time.sleep(0.5)\n",
    "        display(Markdown('**[System] Reset complete. System halted safely.**'))\n",
    "\n",
    "# === Simulation ===\n",
    "cpu = CPU()\n",
    "cpu.enter_exclusive_area()\n",
    "time.sleep(0.3)\n",
    "\n",
    "# 非マスク割込み (NMI) 発生\n",
    "cpu.trigger_nmi('ECC Memory Error')\n",
    "\n",
    "time.sleep(0.3)\n",
    "cpu.leave_exclusive_area()"
   ],
   "outputs": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.x"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}

[OS] Enter/Leave Exclusive Area
[HW] NMI Triggered
[CPU] NMI Handler
[Safety] Safe State
の順で出力されます。
希望であれば、このコードを .ipynb 形式でダウンロード可能 にすることもできます。作成しますか?

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?