ハードウェアを意識したプログラミングの基礎(前編)
3.ハードウェアとソフトウェアの 境界線
デバイス・ドライバの開発がアプリケーションの開発と唯一違うところは,「ハードウェアと通信する」ということだと筆者は考えます注9.デバイス・ドライバの開発からハードウェアを制御する部分を除けば,アプリケーション開発との違いはフレームワークしかありません.アプリケーション・フレームワークを使ってアプリケーションを作成する代わりに,Linuxフレームワークを使ってデバイス・ドライバを作成しているだけになります.
注9;「メモリ」というハードウェアを使っている普通のプログラミングも,突き詰めればキャッシュ・ヒット率などの楽しい話がある.
● バス幅の違い
ハードウェアとの通信とはどういうことなのか,前述のコードを使って説明します.前述のコードの中に32ビット・アクセスを行っているところがあります.もし,ハードウェアのことを考えないのであれば,リスト5のように書き換えることができます.
1: #include <stdio.h>
2: #include <linux/types.h>
3:
4: int main()
5: {
6: char fifo[] = {0x12, 0x34, 0xAB, 0xCD};
7: __u32 val;
8: char *v = (char *)&val;
9: int i;
10:
11: for (i=0; i<sizeof(val); i++)
12: v[i] = fifo[i];
13:
14: printf("0x%Xエn", val);
15: return 0;
16: }
リスト5 ハードウェアのことを考えない場合
このように書き換えてもアプリケーションの結果は同じで,リトル・エンディアンであれば0xCDAB3412と表示されます.アプリケーションを書いているときに,わざわざこのように書く人はいないと思います.コード量も増えるし,1バイトずつ取るなんて面倒なことはしないでしょう.
しかし,もしデバイスが8ビット・バスにつながっていれば,必ず上記のようにデバイス・ドライバを書かなければなりません.8ビット・バス経由では,32ビットでアクセスしても,エラーになったり正しい情報が読めなかったりします(図8,図9).
図8 8ビット・バスでCPUとデバイスがつながっている場合のアクセス
図9 32ビット・バスでCPUとデバイスがつながっている場合のアクセス
● CPUアーキテクチャの版数による命令の違い
いつの時代でも商品には,新しい機能が次々と追加されていきます.CPUアーキテクチャも例外ではなく,次々と新しくなっています.高速動作,FPU(浮動小数点演算ユニット)の追加,キャッシュの大型化,パイプライン段数の増加,分岐予測の精度向上,新しい命令の追加,そして最近では複数コア化が進んでいます.ここでは本稿の趣旨であるデバイス・ドライバの開発に関係のあるものとして,命令セットを取り上げます.
1997年,x86にMMXというSIMD(Single Instruction Stream-Multiple Data Stream:シムド)命令がPentiumに追加されました.その後もAMD(Advanced Micro Devices)社の3D Now!やIntel社のSSEなどの命令セットが追加されています.また,PowerPCではAltiVecと呼ばれるSIMD命令が追加されています.
ARMアーキテクチャもARMv1から始まり,最新のARMv7まで増えています.現在サポートされているアーキテクチャはARMv4~ARMv7です.16ビット命令セットのThumb(サム)やJavaプログラムを高速実行するJazelle(ジャゼール),新しい浮動小数点演算VFPv2,そしてSIMD命令セットなどが,バージョンを追うごとに追加されています注10
注10;以下のURLを参照.http://www.arm.com/products/CPUs/architecture.html
デバイス・ドライバを開発するときには,使える命令セットを最大限活用しつつ,移植性の考慮も頭に入れておかなければなりません.