Chapter 06
I²C と SPI — 周辺 IC との会話を盗聴し、なりすます
この章のゴール.
I²C と SPI の仕組みを押さえ、バスの通信を受動観測して意味を復元でき、 さらにマスタ/スレーブになりすまして能動テスト(偽センサ、レジスタ改変)ができるようになること。
この章で使う既出の用語(定義は各リンク先). USB(01 章 2 節)、アナログ(01 章 2 節)、オラクル(01 章 8 節)、テストダブル(02 章 7 節)、判定(02 章 1 節)、電源(02 章 2 節)、プロトコルデコーダ(04 章 4 節)、ロジックアナライザ(04 章 1 節)
1. MCU 周辺の 2 大バス
MCU はセンサ・EEPROM・ADC・ディスプレイ・無線モジュールと、たいてい I²C か SPI でつながる。 これらのバスを観測すれば、「MCU がどの IC に何を書き、何を読んでいるか」——つまりMCU の意図が読める。周辺コンポーネントの状況把握の中心である。
| I²C | SPI | |
|---|---|---|
| 線 | 2 本(SCL クロック、SDA データ)+ GND | 4 本(SCLK、MOSI、MISO、CS)+ GND |
| アドレス | 7/10 ビットアドレスで相手を選ぶ | CS(チップセレクト)線で相手を選ぶ |
| 速度 | 100k/400k/1M Hz | 数 M〜数十 MHz(速い) |
| 相手数 | 多数(アドレスで区別) | CS の数だけ |
| 特徴 | 配線少・低速・ACK あり | 高速・全二重・線が多い |
2. 受動観測 — バスを盗聴する
ロジックアナライザ(04 章)を SCL/SDA(I²C)または SCLK/MOSI/MISO/CS(SPI)に当て、プロトコルデコーダを掛ける。
I²C の 1 トランザクションは「スタート → アドレス + R/W → ACK → データ… → ストップ」。デコーダはこれを表にする。
S 0x68+W A 0x3B A ... ← アドレス 0x68(MPU-6050 等)のレジスタ 0x3B を指定
S 0x68+R A 0x01 A 0x2C A ... ← リスタートして読み出し(加速度データ)観測から分かること:
- どのチップと話しているか(アドレス → データシートで型番の見当)
- レジスタアクセスの列(初期化シーケンス、周期的な読み出し)
- ACK/NACK: NACK が続けば「相手がいない/壊れている」。AI コードが存在しないアドレスを叩いていないか
- 周期と量: どれくらいの頻度で読んでいるか(電流・タイミングと関連、03 章・14 章)
チップ専用デコーダを重ねると、生のレジスタ値が「加速度 X = 0.98 G」のように意味づけされる(04 章のデコーダスタック)。
3. 能動テスト①: MCU 側になりすます(周辺 IC を直接叩く)
バスに自分がマスタとしてアクセスし、周辺 IC を直接読み書きする。「MCU がやるべきこと」を人間が代わりにやって、周辺が正しいか、あるいは MCU が正しく設定したかを確認する。
- USB-I²C/SPI アダプタ(FT2232、Bus Pirate、Raspberry Pi の I²C)+ Python(
smbus2、spidev、pyftdi) - MCU を止めて(リセット保持)からバスを借りる。動作中の MCU と同時にマスタになるとバス競合(I²C はマルチマスタ可だが SPI は不可)
from smbus2 import SMBus
bus = SMBus(1)
who = bus.read_byte_data(0x68, 0x75) # WHO_AM_I レジスタ
assert who == 0x68, f"チップ ID 不一致: {who:#x}(配線 or はんだ不良の疑い)"用途: 周辺 IC の実装(はんだ・配線)検査、MCU が書いた設定レジスタの読み戻し確認、既知良品との比較。
4. 能動テスト②: 周辺 IC になりすます(偽センサ)
もっと強力なのが、自分がスレーブ(センサ役)になって MCU に偽の値を返すこと。これがテストダブル(02 章)の真骨頂である。
- マイコン(RP2040、Arduino など)を I²C スレーブとしてプログラムし、MCU からのレジスタ読み出しに任意の値を返す
- 「加速度 = 重力加速度の上限」「温度 = −40 ℃」「センサ応答なし(NACK)」「途中でフリーズ」——本物のセンサが出さない異常を注入できる
- MCU(AI 生成ファーム)が、その異常値をどう扱うか(クリップするか、クラッシュするか、無視するか)を観測する
これで検証できること:
- 境界・異常系(02 章): センサが極端な値・エラーを返したときの堅牢性(16 章のファジングへ)
- 状態依存: 「センサが N 回連続で異常なら安全モードに入る」といった仕様の確認
- 初期化の順序: MCU がレジスタをどの順で設定するか、リトライするか
5. SPI 特有の注意
- モード(CPOL/CPHA の 4 通り): クロックの極性と位相。合っていないとデータがずれる。デコーダで判定できるが、能動テストでは相手のモードに合わせる
- CS のタイミング: CS の立ち下がり〜立ち上がりが 1 トランザクション。複数スレーブは CS で選ぶ
- 速度: 高速なので配線・プローブの容量に敏感(04 章)
6. 何をオラクルにするか
- 通信の内容: レジスタ・データが仕様/データシートどおり
- 初期化シーケンス: 電源投入後、周辺を規定どおり設定するか
- エラー処理: 偽センサで異常を注入したときの MCU の振る舞いが仕様どおり(暴走しない)
- 周期・量: 過剰なポーリングがないか(電流に効く、03 章)
- 存在確認: 期待するチップと ACK が返る(実装検査)
7. 手を動かす
バスの会話を読み、偽の値を返す
この章のポイント
- I²C(2 線・アドレス)と SPI(4 線・CS)は MCU 周辺の 2 大バス。盗聴すれば MCU の意図が読める
- 受動観測: デコーダで「どのチップに何を読み書きしているか」。チップ専用デコーダで意味づけ
- 能動①: MCU になりすまして周辺を直接叩く(実装検査・設定確認)
- 能動②: 周辺になりすまして偽の値を返す(偽センサ)。本物が出さない異常を注入して堅牢性を試す
- オラクル: 内容・初期化順・エラー処理・周期・存在確認