マイコン(MCU)のアーキテクチャ
CPU・フラッシュ・SRAM・ペリフェラルが1チップに載る理由が原理から腑に落ちる。ハーバード型バスとNVIC割り込みの仕組みまで押さえれば、なぜ数百円のチップが確定的に動くのか理解できる。
- 1.MCUはCPUコア・不揮発メモリ(フラッシュ)・SRAM・多数のペリフェラルを1チップに集積したSoC。外部メモリなしで単体動作でき、これがMPUとの本質的な差。
- 2.Cortex-Mは命令とデータのバスを分けたハーバード型で、アドレス空間は固定マップ。フラッシュは実行専用、SRAMは変数・スタック、ペリフェラルはメモリマップドレジスタで制御する。
- 3.NVIC(ネスト型ベクタ割り込みコントローラ)が優先度付き・ネスト可能な割り込みをハードウェアで裁く。ベクタテーブル参照からハンドラ実行までを自動化し、低レイテンシと確定性を担保する。
「コンピュータ一式」を1チップに畳み込む
PC のプロセッサ(MPU)は単体では動きません。DRAM、ストレージ、電源 IC、チップセットが揃って初めて OS が起動します。対してマイコン(MCU: Microcontroller Unit)は、CPU コア・不揮発メモリ・揮発メモリ・入出力ペリフェラルを1枚のシリコンに集積し、水晶発振子と電源を与えるだけで単体で動きます。この「自己完結性」こそが MCU の定義であり、家電・自動車 ECU・IoT センサノードといった、外部メモリを載せる余裕もコストもない領域を支える理由です。
具体的には、STM32・RP2040・nRF52 のような Arm Cortex-M 系 MCU は次の要素を1チップに持ちます。CPU コアの内部動作(パイプライン等)は /hardware-components/ 、トランジスタ物理は /semiconductor/ を前提とします。
| 構成要素 | 役割 | 揮発性・特徴 |
|---|---|---|
| CPUコア | 命令フェッチ・実行(例: Cortex-M0+/M4/M7) | レジスタのみ揮発。数十〜数百MHz |
| フラッシュROM | プログラムコードと定数を格納。実行はここから直接(XIP) | 不揮発。電源断でも保持。書換え回数に上限 |
| SRAM | 変数・スタック・ヒープ。実行時の作業領域 | 揮発。高速・待ち時間ほぼゼロ・容量は数KB〜数MB |
| ペリフェラル | GPIO・UART・SPI・I2C・タイマ・ADC・DMA など | レジスタでメモリマップド制御 |
| 割り込みコントローラ | NVIC。外部・内部イベントをCPUへ通知 | コアに密結合。優先度とネストを裁く |
MPU との差は容量とアーキテクチャの両面に出ます。MPU は外部 DRAM を前提に MMU(仮想記憶)で GB 級のメモリを管理しますが、MCU の多くは MMU を持たず、物理アドレスを直接扱います。この単純さが、割り込み応答の確定性(determinism)と低消費電力を生みます。
ハーバード型バスと固定アドレスマップ
Cortex-M の内部は、命令用とデータ用のバスを物理的に分けたハーバード・アーキテクチャです。命令をフラッシュから読む経路(I-Code バス)と、データを読み書きする経路(フラッシュ上の定数は D-Code バス、SRAM やペリフェラルは System バス)が独立しているため、「次の命令のフェッチ」と「今の命令のデータアクセス」を同じサイクルで並行実行できます。命令とデータが同じバスを奪い合うフォン・ノイマン型のボトルネック(構造ハザード)を、バス分離で回避しているわけです。
もう一つの鍵が固定されたアドレスマップです。Cortex-M では 4GB のアドレス空間の使途があらかじめ規格で決まっており、どのベンダの実装でも同じ番地に同じ種類の資源が並びます。
Cortex-M 標準メモリマップ(32ビット, 4GB空間の主要区画)
0x0000_0000 - 0x1FFF_FFFF Code : フラッシュROM(コード実行, XIP)
0x2000_0000 - 0x3FFF_FFFF SRAM : 変数・スタック・ヒープ
0x4000_0000 - 0x5FFF_FFFF Peripheral : ペリフェラルレジスタ群
0x6000_0000 - 0x9FFF_FFFF External RAM : 外付けメモリ(任意)
0xE000_0000 - 0xE00F_FFFF Private Peripheral Bus : NVIC・SysTick 等コア内蔵
「メモリマップド I/O」がここで効いてきます。GPIO のオン・オフも UART の送信も、特定の物理アドレスにあるレジスタへ値を書くだけで実現します。CPU から見ればメモリアクセスと区別がなく、専用の I/O 命令は不要です。たとえば LED を点けるコードは概念的にこう書けます。
// ポート出力レジスタの該当ビットを 1 にする(メモリマップドI/O)
volatile uint32_t *GPIO_ODR = (uint32_t *)0x4002_0014;
*GPIO_ODR |= (1u << 5); // 5番ピンを High に
ペリフェラルレジスタは CPU の関知しないハードウェア側で値が変わり、また書き込み自体が副作用(送信・クリア等)を持ちます。volatile を付けないと、コンパイラは「値が変わらない」と誤認して読み書きを最適化で削除・統合し、動作が壊れます。組み込みでレジスタを触るポインタには必ず volatile を付けるのが鉄則です。
フラッシュから直接コードを実行する XIP(eXecute In Place) も MCU 特有です。PC のようにプログラムを RAM へロードせず、フラッシュ上の命令をそのままフェッチします。これで SRAM を節約できますが、フラッシュのアクセス速度が CPU より遅い高クロック品では「待ちサイクル(ウェイトステート)」や命令キャッシュが必要になります。
起動シーケンス:ベクタテーブルから main へ
電源投入後、Cortex-M はアドレス空間の先頭(0x0000_0000)に置かれたベクタテーブルの最初の2ワードを読みます。ここが MCU 起動の核心で、OS もブートローダも介さず、ハードウェアが直接実行を始めます。
リセット時のハードウェア動作(Cortex-M)
ステップ1: アドレス 0x0000_0000 の値 → MSP(メインスタックポインタ)に設定
ステップ2: アドレス 0x0000_0004 の値 → PC(プログラムカウンタ)に設定
= Reset_Handler の先頭アドレス
ステップ3: Reset_Handler が実行される
- .data セクションをフラッシュから SRAM へコピー(初期値付き変数)
- .bss セクションを 0 クリア(初期値なし変数)
- クロック・PLL 初期化
- main() へジャンプ
ここで重要なのは、.data と .bss の初期化をスタートアップコードが手作業で行う点です。PC では OS のローダがやってくれる仕事を、MCU では自分のプログラムの一部(Reset_Handler)が担います。初期値を持つグローバル変数の初期値はフラッシュに焼かれており、起動時に SRAM へコピーして初めて RAM 上の変数として機能します。
NVIC:割り込みをハードウェアで裁く
MCU の真価は割り込み駆動にあります。CPU が無駄なポーリングで待つのではなく、ペリフェラルがイベント(タイマ満了、UART 受信、GPIO エッジ等)を上げた瞬間にハードウェアが CPU を横取りし、対応するハンドラへ飛ばす。この裁定を専任で行うのが NVIC(Nested Vectored Interrupt Controller) です。Cortex-M ではコアに標準搭載され、割り込み処理の大部分をハードウェアで自動化します。
NVIC の名が示す3要素が本質です。
- Nested(ネスト): 割り込み処理中に、より高優先度の割り込みが来れば、それを割り込ませる。優先度の逆転を防ぎ、緊急イベントの遅延を抑えます。
- Vectored(ベクタ): 割り込み要因ごとに飛び先アドレスがベクタテーブルに登録済み。要因番号から即座にハンドラ番地を引ける(要因を判定する分岐ソフトが不要)。
- 優先度制御: 各割り込みに優先度レベルを設定でき、同時発生時はハードウェアが高優先度を先に処理する。
割り込み発生から復帰までのハードウェア動作は次の通りです。ソフトが書く必要があるのはハンドラ本体だけで、文脈保存・テーブル参照・復帰はコアが自動で行います。
割り込みのハードウェアシーケンス(Cortex-M / NVIC)
1. ペリフェラルが割り込み要求(IRQ)を NVIC へ送る
2. NVIC が優先度を比較し、現在の実行より高ければ受理
3. コアが自動でレジスタ8本を退避(スタッキング):
R0-R3, R12, LR, PC, xPSR をスタックへ
4. ベクタテーブルから該当ハンドラのアドレスを取得し PC へロード
5. ハンドラ(ISR)本体を実行
6. ハンドラ復帰時、退避した8本を自動で復元(アンスタッキング)
7. 元の処理を中断点から再開
ステップ3の「自動スタッキング」により、C 言語の関数をそのまま割り込みハンドラとして書けます(呼び出し規約で保存すべきレジスタをコアが退避するため)。これが割り込みレイテンシを短く・一定に保つ仕組みで、リアルタイム性の土台です。割り込みと入出力の一般論は /os/ も参照してください。
Cortex-M の割り込み優先度は、数値が小さいほど優先度が高いという逆順です。優先度 0 が最高で、リセット・NMI・HardFault はさらに上の固定優先度を持ちます。加えて優先度レジスタは上位ビットのみ実装されることが多く(例: 4ビット実装なら16段階)、下位ビットを書いても無視されます。設定値と実効優先度がずれる典型的な落とし穴です。
割り込みハンドラ(ISR)は「短く・速く」が絶対原則です。ISR 内で printf やビジーウェイト、ミューテックス待ちなどブロッキング処理を行うと、同優先度以下の割り込みが全て待たされ、システムの応答性が崩壊します。重い処理はフラグだけ立てて即座に抜け、本体はメインループや低優先度タスクへ委ねる(遅延処理・ボトムハーフの考え方)のが定石です。
ペリフェラルと DMA:CPU を介さないデータ転送
MCU に載るペリフェラルは、CPU の負荷を肩代わりする専用ハードウェアです。UART / SPI / I2C はシリアル通信を、タイマは正確な時間基準や PWM 出力を、ADC はアナログ入力のデジタル化を、それぞれ CPU と独立して行います。とりわけ DMA(Direct Memory Access)コントローラは、メモリとペリフェラル間のデータ転送を CPU を介さず実行します。
たとえば「ADC で 1000 サンプルを取得して SRAM のバッファへ格納」する場合、CPU が1サンプルごとに割り込みで介入すると負荷が跳ね上がります。DMA に転送を委ねれば、ADC の変換完了ごとに DMA が自動でバッファへ書き込み、全転送が終わった時だけ CPU へ1回割り込みを上げます。CPU はその間、別の処理に専念できます。
DMA を使った ADC 連続取得の流れ
設定: ADC → DMAチャネル → SRAMバッファ(1000語) を結線
動作:
ADC変換完了 → DMAが1語をバッファへ転送 → 転送カウンタ--
(これを1000回、CPU無介入で反復)
カウンタ=0 → DMAが「転送完了割り込み」を1回だけ発火
結果: CPU割り込み回数 1000回 → 1回。CPUは他処理へ
「MCU と MPU の違い」は『MCU は CPU・不揮発メモリ・RAM・ペリフェラルを1チップに集積し単体動作する。MPU は外部メモリ前提で MMU を持ち大規模 OS を動かす』と答えます。「NVIC の役割」は『割り込みの優先度付け・ネスト・ベクタ参照・自動スタッキングをハードウェアで行い、低レイテンシと確定性を担保する』。「ハーバード型の利点」は『命令バスとデータバスの分離で、フェッチとデータアクセスを並行でき構造ハザードを避ける』が採点ポイントです。
まとめ
- MCU は CPU コア・フラッシュ・SRAM・ペリフェラルを1チップに集積した自己完結型 SoC。外部メモリなしで単体動作し、確定性と低消費電力を両立する点が MPU との本質的な差。
- Cortex-M は 命令バスとデータバスを分けたハーバード型で、4GB の固定アドレスマップを持つ。コードはフラッシュから直接実行(XIP)し、ペリフェラルはメモリマップドレジスタ(
volatile必須)で制御する。 - 起動はハードウェアがベクタテーブルの先頭2ワード(初期 MSP と
Reset_Handler)を読むことから始まり、スタートアップコードが.dataコピーと.bssクリアを経てmainへ渡す。 - NVIC が割り込みの優先度・ネスト・ベクタ参照・レジスタ自動退避をハードウェアで裁き、低レイテンシと確定性を実現する。ISR は短く保つのが鉄則。
- DMA は CPU を介さないメモリ・ペリフェラル間転送で割り込み回数を激減させ、CPU を本来の処理へ解放する。土台となる CPU 内部は /hardware-components/、割り込みと I/O の一般論は /os/ を参照。
組込み・IoT Article
マイコン(MCU)のアーキテクチャを実務で読む
TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。
解決すること
マイコン
比較で見る軸
難易度: advanced / カテゴリ: 組込み・IoT / タグ数: 6
導入後に効く点
Cortex-Mは命令とデータのバスを分けたハーバード型で、アドレス空間は固定マップ。フラッシュは実行専用、SRAMは変数・スタック、ペリフェラルはメモリマップドレジスタで制御する。
先に潰すリスク
用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。
- 難易度
- advanced
- カテゴリ
- 組込み・IoT
- タグ数
- 6
判断チェックリスト
- 自社の用途が「マイコン / MCU」に近いか確認する。
- 強みである「MCUはCPUコア・不揮発メモリ(フラッシュ)・SRAM・多数のペリフェラルを1チップに集積したSoC。外部メモリなしで単体動作でき、これがMPUとの本質的な差。」が本当に評価軸になるか確認する。
- 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
- 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
- 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
- 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。