Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ペリフェラル

ペリフェラルとは何か?

ほとんどのマイクロコントローラーは、CPU、RAM、フラッシュメモリだけで構成されているわけではありません。マイクロコントローラーの外部にあるシステムとやり取りしたり、センサー、モーターコントローラー、ディスプレイやキーボードのようなヒューマンインターフェイスを介して、外界と直接的または間接的にやり取りしたりするためのシリコン領域も含まれています。これらのコンポーネントは総称してペリフェラルと呼ばれます。

これらのペリフェラルが有用なのは、開発者が処理の一部をそれらにオフロードできるためであり、すべてをソフトウェアで処理する必要がなくなるからです。デスクトップ開発者がグラフィックス処理をビデオカードにオフロードするのと同じように、組み込み開発者も一部のタスクをペリフェラルにオフロードできます。これにより、CPU は別の重要な処理に時間を使ったり、省電力のために何もしなかったりできるようになります。

1970 年代や 1980 年代の昔ながらの家庭用コンピューターのメイン回路基板を見ると(そして実際、ひと昔前のデスクトップ PC は今日の組み込みシステムとそれほどかけ離れてはいません)、次のようなものが載っているはずです。

  • プロセッサ
  • RAMチップ
  • ROMチップ
  • I/Oコントローラー

RAM チップ、ROM チップ、I/O コントローラー(このシステムにおけるペリフェラル)は、「バス」と呼ばれる一連の並列配線を介してプロセッサに接続されます。このバスは、プロセッサがバス上のどのデバイスと通信したいかを選択するためのアドレス情報と、実際のデータを運ぶデータバスを担います。組み込みマイクロコントローラーでも同じ原理が当てはまります。違うのは、すべてが 1 枚のシリコン上に詰め込まれているという点だけです。

しかし、通常は Vulkan、Metal、OpenGL のような Software API を持つグラフィックスカードとは異なり、ペリフェラルはハードウェアインターフェイスとしてマイクロコントローラーに公開されており、それがメモリの一部にマッピングされています。

線形メモリ空間と実メモリ空間

マイクロコントローラーでは、0x4000_00000x0000_0000 のような別の任意のアドレスに何らかのデータを書き込むことも、完全に正当な操作である場合があります。

デスクトップシステムでは、メモリへのアクセスは MMU、すなわち Memory Management Unit によって厳密に制御されています。このコンポーネントには大きく 2 つの役割があります。1 つはメモリの各領域に対するアクセス権限を強制すること(あるプロセスが別のプロセスのメモリを読み取ったり変更したりするのを防ぐこと)であり、もう 1 つは物理メモリのセグメントをソフトウェアで使用する仮想メモリ範囲に再マッピングすることです。マイクロコントローラーには通常 MMU はなく、代わりにソフトウェアでは実際の物理アドレスだけを使用します。

32 ビットのマイクロコントローラーは 0x0000_0000 から 0xFFFF_FFFF までの実際かつ線形なアドレス空間を持っていますが、一般にはその範囲のうち実際のメモリに使われるのは数百キロバイト程度にすぎません。その結果、かなりの量のアドレス空間が残ります。前の章では、RAM がアドレス 0x2000_0000 に配置されていると説明しました。RAM のサイズが 64 KiB(つまり最大アドレスが 0xFFFF)であれば、0x2000_0000 から 0x2000_FFFF までのアドレスがその RAM に対応します。アドレス 0x2000_1234 に存在する変数に書き込むと、内部では何らかのロジックがアドレスの上位部分(この例では 0x2000)を検出し、続いて RAM を有効化して、アドレスの下位部分(この場合は 0x1234)を処理できるようにします。Cortex-M では、たとえば 512 KiB の Flash ROM がある場合、0x0000_0000 から 0x0007_FFFF までのアドレスにも Flash ROM がマッピングされています。マイクロコントローラーの設計者は、これら 2 つの領域の間に残る空間をすべて無視するのではなく、代わりに特定のメモリ位置にペリフェラル用のインターフェイスをマッピングしました。その結果、概ね次のような構成になります。

Nordic nRF52832 Datasheet (pdf)

メモリマップドペリフェラル

一見すると、これらのペリフェラルとのやり取りは単純です。正しいアドレスに適切なデータを書き込むだけです。たとえば、シリアルポート経由で 32 ビットのワードを送信する場合、その 32 ビットのワードを特定のメモリアドレスに書き込むだけで済むことがあります。するとシリアルポートのペリフェラルが処理を引き継ぎ、データを自動的に送信します。

これらのペリフェラルの設定も、同様の仕組みで行います。ペリフェラルを設定するために関数を呼び出す代わりに、ハードウェア API として機能するメモリ領域が公開されています。SPI の周波数設定レジスタに 0x8000_0000 を書き込むと、SPI ポートは毎秒 8 メガビットでデータを送信します。同じアドレスに 0x0200_0000 を書き込むと、SPI ポートは毎秒 125 キロビットでデータを送信します。これらの設定レジスタは、おおよそ次のようになっています。

Nordic nRF52832 Datasheet (pdf)

このインターフェイスこそが、Assembly、C、Rust のいずれを使う場合でも、ハードウェアとやり取りする方法です。