RA2A1 シミュレーターを作っている話 — 設計・実装・検査のフローと現在地

なぜシミュレーターを自作するのか

マイコン開発の地味な苦しみのひとつが、「コードを書いてはボードに焼いて、動作を確認して、また書く」というサイクルの遅さです。

書き込み自体は数秒で終わっても、ロジックのデバッグのためだけにボードに手を伸ばし、シリアルターミナルを開き、ケーブルが抜けていないか確認する……その繰り返しに、じわじわとコストが積み上がります。

というわけで、RENESAS RA2A1 グループのマイコン用ハードウェアシミュレーターをC++で自作しています。

✏️ dencat添削: 「自作」というか、正確には AIエージェント(AntigravityとClaude code)との二人三脚 で構築を進めています。実は私、コードを一行も書いていません……!全体の方針立てとレビューが主な役割です。

目標はシンプルです。

「実機(e2 studio)のCコードを1文字も変えずに、PC上で動かしてデバッグできる環境を作る。」


シミュレーターの設計方針

実機コードをそのまま使う

e2 studio プロジェクト内の Cソースコードを「読み込み専用」で直接参照し、PC(x86_64)向けにクロスコンパイルします。FSP(Renesas Flexible Software Package)が提供するAPI(R_SCI_OpenR_ADC_ScanStart など)はPC用のモックに差し替えることで、ファームウェアのコードを一切書き換えずに動かせます。

OOPによるペリフェラル分離

GPIO、ADC、UART(SCI)などの周辺回路は、それぞれ ISimulatedPeripheral を継承した独立したクラスとして実装しています。新しいペリフェラルを追加するときも、既存モジュールに触れる必要がありません。

環境を汚さないローカルビルド

OpenGLやX11などの開発ライブラリは、Micromamba(軽量版Conda)を使ってプロジェクト内の ./env にのみインストールします。ホストの /usr は一切変更しません。


開発・検査サイクル

各ペリフェラルの追加は、以下のサイクルに従って進めています。

要求仕様の設計・合意
    ↓
インターフェース先行設計(ISimulatedPeripheral)
    ↓
レジスタ・時間シミュレーション実装
    ↓
自動テストコードの作成(Unit / Integration Test)
    ↓
実機ファームウェアとの統合実行
    ↓
GUIおよびロジックアナライザによる動作確認
    ↓(パスすれば)
リリース & ロードマップ更新

「動いた気がする」ではなく、自動テストで100%通過することを定義の完了(DoD) としています。


全体ロードマップ(4フェーズ)

フェーズ I:シミュレータ検証基盤の確立 ← 今ここ

✏️ dencat添削: 想像より進んでます!すでに ハードウェアマニュアル26章ぶんを実装完了、各種ペリフェラルをどんどん実装中というフェーズです。

まず土台を固めています。

フェーズIのDoD(Definition of Done):
- 既存の GPIO / SCI / ADC / DAC の自動テストが100%通過すること
- 実機ファームウェアのコードがエラーなくx86_64向けにビルドできること
- ELCによるイベント連鎖がテストコード上で正確に動作すること


フェーズ II:ファームウェアループ & ライフサイクル制御

while(1) のメインループを安全に走らせながら、GUIがフリーズしない実行モデルを確立。WDT(ウォッチドッグ)のリセットや、スタンバイ・スヌーズといった低消費電力モードも実装する予定です。

フェーズ III:通信 & データフローの高度化

I2C、SPI、CANなどのバス通信の精密模擬と、DTC(データトランスファコントローラー)によるCPU非介入の自動転送、MPU(メモリ保護ユニット)違反検出などを実装します。

フェーズ IV:アナログ極限 & 実機挙動一致検証

オペアンプ、コンパレータ、24ビットΣΔ ADCなどのアナログ回路の物理シミュレーションと、RFP(Renesas Flash Programmer)による仮想フラッシュ書き込みシーケンスの再現を目標にしています。


今できていること

すでに動いているもの:

UARTの文字化け再現が特にお気に入りです。GUIのBRRレジスタを変更すると、minicomやTeraTermに接続したターミナルがリアルタイムで文字化けし始めます。「実機でなぜか文字化けした」という問題をシミュレーター上で再現・調査できるのが強みです。

✏️ dencat添削: ここに挙げたのは一部分。実際には GDBデバッグで Reset_Handlerhal_entry のブレークポイント到達も確認済み で、思っていたよりずっと進んでいました!


規模感

項目 執筆時点の見積もり ✏️ dencat添削(実数)
言語 C++(シミュレーター本体) (変更なし)
ビルドシステム CMake + Micromamba(隔離環境) (変更なし)
テストフレームワーク Google Test (変更なし)
GUIフレームワーク OpenGL + ImGui (変更なし)
対象MCU RENESAS RA2A1グループ(ARM Cortex-M23) (変更なし)
ペリフェラル実装済み GPIO / SCI / ADC / DAC ハードウェアマニュアル26章ぶん実装済み
仕様書(*-spec.md (未記載) 約7,000行
ソースコード (未記載) 約30,000行(見積もり)
プロジェクト容量 (未記載) 約1GB
フェーズ I / IV(基盤確立中) 各種ペリフェラルを並行実装中

おわりに

フェーズI完了まではまだ作業があります。特に FSPモックの範囲をどこまで広げるかがポイントで、ここが土台になるのでじっくり進めているところです。

✏️ dencat添削: 「土台はもうほぼ固まっていて、各種ペリフェラルの実装ラッシュ中」という方が正確です。次は iodefine の検証(レジスタのヌケモレチェック)と、EK-RA2A1サンプルプロジェクトを通せるかの確認に向かいます。

進捗はこのブログで随時報告していく予定です。マイコン開発をしている方や、「シミュレーター自作おもしろそう」と思ってくれた方、フィードバックがあればぜひ。


この記事は、Yuki-System のエージェントであるユキ(Claude code)によって、管理者との対話を通じて執筆されました。


dencat's note

クォーター制限ぐぬぬ

というわけで、2週間ぶりくらいにブログを書きますが、何がおきていたかと言うと、、、
AntigravityをRA2A1シミュづくりの為に酷使して、週間クォーター制限を先週も、今週も食らっておりました。。。

あまりにもエージェントAIを使えない日々が続いたフラストレーションで、Claude code APIを25ドル消費してしまい、「そんなことならPro版使ったほうが安いじゃん」、と思い、Pro版を用意しました。

というわけで、AntigravityとClaude codeの二刀流でRA2A1シミュレーターの構築を進めています。

なぜRA2A1?

お仕事でたっぷり擦りまくっているからですね。
これからもお世話になりますし、ルネサスのRAシリーズはこれからもガンガンお世話になりそうですから。

どんな進め方をした?

  1. 要件定義。とりあえず「おもちゃ」を用意してみる
    • まずは、GUIを用意。
      • LEDに見立てた丸ポチをLチカさせたり
      • UARTでボーレートが合わないために文字化けが発生させたり
    • 最終的に求めるのは、
      • 簡易な「レジスタ」シミュレートと、
      • 高精度重視の「クロック」シミュレート。
      • 本当にできるの?って僕自身でも謎ですけど。レジスタくらいならできるでしょうね。。。多分。
  2. 全体の進行方向定義
    • ハードウェアマニュアルの解析。
    • 章毎の実装。
    • 実装結果の妥当性チェック。
    • EK-RA2A1サンプルコードをシミュレートできるか。
  3. ハードウェアマニュアルの解析
    • 約1500ページを章毎のPDFに分解。
    • *-spec.md に1章ずつ構築。
  4. ハードウェアマニュアル解析結果のレビュー
    • Antigravityに用意してもらった *-spec.md を、Claude codeにレビューしてAntigravityに突き返し
  5. 基本機能を実装。
  6. 基本的なところまで作れたところで、GDBサーバーとのやり取りデバッグ
    • Reset_Handlerhal_entry につけたブレークポイントへ到達
  7. 各種ペリフェラルをどんどん実装中。。。

どんな規模になっている?

現在、26章まで実装したところで、RA2A1シミュレーションプロジェクトは、1GBくらいの容量になりました。

*-spec.md はすべてで7000行の規模となり、ソースコードは3万行くらいと見積もって作業を勧めています。

コードは書いている?

一行も書いておらず。私がやっていることは、、、

以前作成したagentic-aiスキルがキチンと働いていますね。

今後の予定

  1. 実装の続き
  2. 作られたiodefineの検証(レジスタのヌケモレチェック)
  3. EK-RA2A1サンプルプロジェクトを全部通せるかの動作確認

でんねこ