メインコンテンツまでスキップ

組み込みソフトにおけるハードウェアの知識

亀山
開発一部第6課

組み込みソフトウェアを作成する場合に必要なハードウェアの知識について、組み込みLinuxにデバイスドライバを実装する方法に添って説明しようと思います。

組み込みLinuxも、ハードウェアも説明し出すと際限がないので、簡単な事項から何回かに分けて説明したいと思います。

まず、組み込みソフトウェアについて簡単におさらいします。身近な物でもテレビ、エアコン、洗濯機、シーリングライト…、枚挙にいとまがないほど、機能の違いはありますが、ほぼ全ての電化製品に搭載されていると言っても過言ではありません。
昔(※1)はマイコンが高価だったため、トランジスタ(※2)等の電子部品を組み合わせて純ハードウェアで構成されていましたが、マイコンが安価になり、マイコンを使用した組み込みモジュールが多用されるようになりました。この組み込みモジュールに搭載するソフトウェアを組み込みソフトウェアと呼んでいます。

※1:今後「昔」と言えば40年ほど前だと思ってください。
※2:ここでは詳しい説明は省きますが、スイッチのようなもので、現在のICの根幹をなす物です。今後、機会があれば説明します。

本題に入る前に、以上の範囲にソフトウェア技術者にとって聞きなれない単語が出てきたかもしれませんので、補足しておきます。本ブロクを読むのに必要な単語の説明だと思ってもらって構いません。電子工作などをされる方には釈迦に説法なので、読み飛ばして頂いて構いません。今後も、組み込みソフトウェアに必要なハードウェアの基礎知識が出てきた場合にその都度補足します。

マイコン

CPUを中心に各種I/O機能を一つのパッケージに収めた物を言います。
昔は半導体の集積技術が十分でなかったため、CPU=マイコンと呼んでいましたが、現在ではCPU、メモリ、DMA、UART、Ether、USB、GPIO等のコントローラが一つのマイコンに集積されています。

組み込みモジュール

マイコンを中心に電源回路や各種インターフェースを搭載した物を言います。
俗に基板やボードと呼ばれます。
組み込みモジュールと言ってもピンからキリまであり、性能に多大な差があります。
身近なところでは、テレビのリモコンの内部に入っている簡単な物から、スマホの内部に入っている高性能な物まで、ひっくるめて組み込みモジュールと呼んでいます。
昔も高価な製品には、組み込みモジュールが搭載されていましたが、CPU性能もメモリ容量も乏しかったので、OSを実装し、その上にアプリケーションを乗せる余裕はありませんでしたが、最近は高性能CPUと大量のメモリが安価に使用できるようになり、Linuxに限らず組み込みモジュールにOSを搭載することが一般的になっています。
OSを搭載することのメリットとして、既存の機能(USB、Ether等)が簡単に利用でき、目的のアプリを簡単に作成できることがあります。 話を分かりやすくするためにHDDレコーダを例に説明します。

図1 画像1.png

この例ですと、USB、SD(カード)、Ether、HDD、Bluetooth等はアプリから簡単に使用できるようにカーネル内に制御プログラムが存在します。そこで、アプリ開発者はチューナーやリモコンの制御に注力すればよいことになります。これが、OSを搭載することのメリットです。しかし、その反面、新規のハードウェアを作成する場合は、ハードウェア毎にデバイスドライバ(Linuxドライバ)を作成する必要があります。
このデバイスドライバを作成する場合に、Linuxカーネルの知識とハードウェアの知識が必要になり、かなり高等な知見が必要となります。

前置きが長くなりましたが、まず、どのようなハードウェアの知識があれば、デバイスドライバが記述できるようになるか、この点を主題に説明して行きたいと思います。
Linuxへのドライバ組み込みは、その後説明します。
今回は全体のさわりだけですので、組み込みソフトウェアがどのような物か理解していただければ構いません。

図1には登場しませんが、一番簡単なのでUART(シリアル通信)のハードウェアを例に説明して行きます。

UART(Universal Asynchronous Receiver/Transmitter)

シリアルの電気信号で通信するためのハードウェアを言います。RS-232C通信と意味は同じと考えて支障ありませんが、正確にはRS-232Cは通信規格のことで、信号の電圧や制御コマンド等が定義されています。他にもRS-422,RS-485等の規格があります。

図2 画像2.png

UART(※)の働きはCPUからの指令に従って、データを変換し、電気信号に変えるものです。図2ではモジュール1と2のCPU間で通信(データ交換)を行います。
※今の説明レベルではUSBやEther用の各種制御コントローラもほぼ同じ構造で「機能」や「P/S」「S/P」の規格が異なると考えて差し支えありません。
「P/S」はparallel→serial変換器で、「S/P」はserial→parallel変換器です。

パラレル⇔シリアル変換

正確ではありませんが、コンピュータ内部で信号はパラレルで扱われています。32bitCPUは32本の信号が、64bitCPUは64本の信号が平行に処理されています。
IC内部では、微細加工により多くの信号線を並べることができますが、モジュール間の橋渡しに64本も信号線を繋ぐのは大変なので、1本の信号線で接続できるようにパラレル⇔シリアル変換を行います。

図3 画像3.png

UARTの制御をCPUで行う場合、UARTのCPU I/Fを介して、制御用レジスタ群にデータを書き込みます。制御用レジスタ群は多数のレジスタで構成されていて、レジスタ毎に機能が割り当てられています。
ハードウェア制御に馴染みのない方にはわかり辛いので、プログラムで言う変数が沢山あり、変数毎に機能が割り当てられていると思ってください。
このレジスタに何らかのデータを書き込むと、機能処理ブロックがレジスタの内容を読み取り、その内容に従って処理を行います。逆に、機能処理ブロックが処理を行った結果をCPUに知らせるために、機能処理ブロックがレジスタに現在のハードウェアの状態を書き込みます。CPUはこのレジスタにある情報を読み取ることで、ハードウェアの状態を知ることができます。
では、このレジスタの内容はどのようになっているのか?
これはUARTのリファレンスマニュアルを読むことによって知ります。リファレンスマニュアルはハードウェア毎に異なりますので、今回は割愛しますが、ハードウェアの制御を行うためには必ず必要な情報です。
今後、機会がありましたら、リファレンスマニュアルの読み方を説明します。

リファレンスマニュアルから読み取った内容を元に、UARTを制御するプログラムを構築します。これが、デバイスドライバです。
デバイスドライバはLinuxカーネル(※)に密接に関係します。そのため、Linuxカーネルがデバイスドライバとインターフェースするために、色々な取り決めがあります。このルールが存在することでLinuxカーネルが多種多様なデバイスドライバとインターフェースすることができます。
※他のOSの場合でも、そのOSのカーネルに密接に関係します。

色々と書きましたが、今回のまとめです。

  • ハードウェア毎に機能が異なるので、ハードウェアのリファレンスマニュアルを読んで理解できるようになること。
  • ハードウェアの機能、目的を明確にできること。
  • Linuxにデバイスドライバを実装するためのルールをしること。

次回から、リファレンスマニュアルの読み方を説明します。