情報工学実験3 デバイス制御実験

担当: 函館高専情報工学科 東海林

[1] 目的

ホストPC上でデバイスドライバを作成してターゲットPCに接続されたデバイスを制御するという実験を通じ、組み込み機器開発の基礎を学ぶ。

[2] 概要

使用デバイス: 電子オルゴール ( electronic music box )
使用OS(ターゲットPC): debian Linux 5 ( カーネル 2.6.26-2-686 )
使用OS(ホストPC): Windows XP + TeraTerm

これまで、スイッチを手動で切り替えることでレジスタの値を直接変更してデバイスを制御する実験は行なってきたが、 実際にコンピュータからデバイスを制御するためにはデバイスドライバを作成する必要がある。 本実験では簡単なデバイスドライバを2週の予定で作成する。

1週目は、ターゲットPCのシリアルインターフェース(RS232C)に接続された電子オルゴールのデバイスドライバを ホストPC上で作成し、ドライバをターゲットPCに転送し、ターゲットPC上でドライバを管理者権限でカーネルに組み込んで動作チェックを行なう。

2週目は、ホストPC上でユーザーアプリケーションを作成し、それらをターゲットPCに転送し、ターゲットPC上で電子オルゴールを一般ユーザー権限で操作する。

今回利用するシステムの構成図を以下に示す(システム図の odgファイル)。 ホストPCとターゲットPCはUSB-シリアル(RS-232C)変換クロスケーブルで接続されている。電子オルゴールはターゲットPCのシリアルインターフェース(RS232C)につながっている。

チェック[2]-(a) デバイスドライバとは何か調べて簡潔にまとめよ(手書き)。 記述した内容はレポートにもワープロで清書して記述すること。


チェック[2]-(b) カーネルとは何か調べて簡潔にまとめよ(手書き)。 記述した内容はレポートにもワープロで清書して記述すること。


チェック[2]-(c) 何故ドライバとアプリケーションを分けてプログラムする必要があるのか 「デバイス」、「管理者権限」、「ユーザー権限」という言葉を使用して述べよ(手書き)。 記述した内容はレポートにもワープロで清書して記述すること。

[3] デバイス仕様

ターゲットPCのシリアルインターフェース(RS-232C)の DTRピン( Dサブ9ピンの4番ピン) に赤LEDが、RTS ピン( Dサブ9ピンの7番ピン )にオルゴール回路 ( UM-66T )と圧電ブザーが接続されている。 したがって DTRピン を H にすれば赤LEDが点灯し、RTSピン を H にすれば音楽が再生される。

なお、シリアルインターフェースの詳細については今後行なわれるシリアルインターフェースに関する実験中に学ぶ。

使用するデバイスの回路図を以下に示す。(回路図の odgファイル)


[4] 1週目: デバイスドライバの作成


(手順 1) UART(Universal Asynchronous Receiver Transmitter)とは パソコンや組み込み機器などで使われるシリアル回路のことで、PC/AT互換機 では16550 互換チップと呼ばれるチップが広く使われている。 ターゲットPCにインストールされたOS(Debian Linux)がどのようにシリアルインターフェースを認識しているかは次の様にデバイスのログを見て確認することが出来る。

$ dmesg


チェック[4]-(a) OSが実際にUARTをどのように認識しているか、教員がプロジェクタに映したdmesgコマンドの結果を手書きで記録しておく。 記述した内容はレポートにもワープロで清書して記述すること。 なお、この後の実験で行なわれるシリアルインターフェースに関する実験では8251Aというチップを用いることを覚えておくこと。


(手順 2) デバイスドライバはIOポートを経由してデバイス上にあるレジスタにデータを読み書きすることでデバイスを制御する。 OSによってデバイスごとに別々にIOボートのアドレスが割り当てられており、IOボートへの読み書きは通常のメモリへの読み書きと同様に行なわれる。 実際にどのようにIOポートのアドレスが割り当てられているか調べたい場合は /proc/ioports を見る。

$ less /proc/ioports


チェック[4]-(b) 教員がプロジェクタに映した /proc/ioports にあるシリアルインターフェースのIOボートアドレスを手書きで記録しておく。 記述した内容はレポートにもワープロで清書して記述すること。 なお、現在はIOポート経由でデバイスを制御する方法は若干レガシーな(古い)方法となっており、 主流はメモリマップドIO ( MMIO ) 方式と呼ばれる制御方式に切り替わっている。詳しくは OS の講義の時間に説明される。


(手順 3) ドライバ、ライブラリ、アプリケーションのビルド環境が入っているアーカイブファイル(device.tgz)、ドライバのソースコードをホストPC上でダウンロードする。ビルド環境とソースは後でターゲットPCに転送される。

(注意)

・IE6 で tgz ファイルをダウンロードした場合は拡張子が gz に変わるバグがある。IE6は使用しないこと。

ビルド環境 (.tgz)

ドライバソース (.c)


(手順 4) ドライバソース(devmbox.c)をホストPCの適当なエディタで開く。


(手順 5) ファイル内の記述に従ってドライバの内部を作成する。

(注意)
・16550 はモデムコントロールレジスタ(MCR) という8bitレジスタを内部に持っていて、レジスタの0bit目がDTR制御ビット、1bit目がRTS制御ビットとなっている。
・DTR制御ビットに1をセットするとDTRピンがHになる、RTS制御ビットに1をセットするとRTSピンがHになる。
・DTRピンには赤LED、RTSピンにはオルゴール回路が接続されている。
・MCRは IOポートの 0x3fc 番地に割り当てられている。
・IOボートへの8bit単位でのデータの読み書きは以下の inb()、outb()関数を用いる。

unsigned char inb ( unsigned short int port );

void outb ( unsigned char value, unsigned short int port );

例えば現在のMCRのレジスタ内容を取得してそのままMCRに書き込むには次のようにする。

unsigned char reg = inb( MCR );
outb( reg, MCR );


(手順 6) 教員のチェックを受けたらターゲットPCをホストPCに接続してログインする。

まずクロスケーブルをホストPCのRS-232Cに接続してTeraTermを起動する。最初の接続ダイアログはキャンセルし、設定メニュー→シリアルから ボートをCOM1、レートを57600にしてOKを押し、エンターキーをオスとターゲットPCと接続されてログインプロンプトが表示される。 ログインしたら ls でディレクトリに何も入っていないことを確認せよ。なおIPアドレス、ユーザー名、パスワードは実験時に知らせる。


(手順 7) ビルド環境(device.tgz)を転送する。

今回はzmodemというバイナリ転送プロトコルを用いてファイルを転送する。

まずターゲットPC上でzmodemのリシーバを起動する。

$ rz

次にTeraTermのファイル → 転送 → zmodem → 送信から device.tgz を転送する。転送したら ls で確認すること。


(手順 8) ターゲットPCでビルド環境のアーカイブを解凍してドライバのディレクトリに移動しファイルを確認する。

$ tar xvfz device.gz
$ ls
$ cd device-control/devmbox
$ ls


(手順 9) デバイスドライバのソース(device.c)を転送する。
まずターゲットPC上でzmodemのリシーバを起動する。

$ rz

次にTeraTermのファイル → 転送 → zmodem → 送信から device.c を転送する。転送したら ls で確認すること。

(注意) ファイルを転送する時に同じ名前のファイルがあると上書きで転送されないので、rz を起動する前に rm で消しておく。


(手順 10) ドライバをビルドする。ビルドが成功するとデバイスドライバ( devmbox.ko )が出来上がる。

$ make
$ ls


(注意) 実際にはドライバはターゲットPC上でビルドせずに、ホストPC上でクロスコンパイルして作成し、ソースではなくてドライバのバイナリだけをターゲットPCに 転送することが多い。


チェック[4]-(c) ビルドが通ることを確認せよ


(手順 11) デバイスには通常はOSか管理者(root)で無ければアクセス出来ない。 よって一般ユーザがデバイスにアクセスするための橋渡し役となるデバイスドライバをカーネルに組み込む(インストールする)ためには 管理者(root)権限が必要である。 su コマンドで root になり、 insmod コマンドでビルドしたドライバをカーネルに組み込む。 組み込んだらexitで管理者モードから抜けてdmsegコマンドで正しくドライバがインストールされたか確認する。

(注意)
・ rootのパスワードは実験時に知らせる。
rootになってコマンドを間違えるとハードディスク全体が消えることもあるので慎重に作業を行なうこと。
・ 端末の記号が root になると # に変わることに着目せよ。

$ su
# ls
# insmod devmbox.ko
# exit
$ dmesg


(手順 12) 一般ユーザー権限からデバイススペシャルファイル( /dev/musicbox0 )に文字列を書き込んで動作確認する。 終わったら再びrootになって rmmod コマンドでドライバを取り除く。

(注意)
・ > はリダイレクトと呼び、echo で出力した文字をそのまま > の後のファイルに書き込むものである(3年の実験を思い出せ)
・ドライバのカーネルへの組み込みにはroot権限が必要だが、ドライバへのアクセスは(スペシャルファイルに文字を書き込むことで)一般ユーザーでも可能なことに着目せよ。


$ ls /dev
$ echo '0' > /dev/musicbox0
$ echo '1' > /dev/musicbox0
$ echo '2' > /dev/musicbox0
$ echo '3' > /dev/musicbox0
$ su
# rmmod devmbox
# exit
$ dmesg


チェック[4]-(d) 動作確認した。


チェック[4]-(e) 最後のdmesg の結果をローカルコンピュータのテキストファイルにコピーしておく。 危険なので必ず exit でrootを抜けてからコピーすること


(手順 13) exit コマンドでログアウトする。



[5] 2週目: ユーザーアプリケーションの作成


(手順 1) アプリ本体のソースが入っているアーカイバ(musicbox.zip)をホストPC上にダウンロードする。

アプリケーションソース (.zip)


(手順 2) musicbox.zip を解凍し、プロジェクトをホストPC上のVC++で開く。あとはソースファイル(musicbox.cpp)内の記述に従って アプリケーションを作成する。

ここで先週ターゲットPC上で

$ echo '0' > /dev/musicbox0

のようにデバイススペシャルファイル( /dev/musicbox0 ) へ 文字 '0' を書き込んだら赤LEDが点灯したことを思い出せ。 同様にプログラム内で fopen()で /dev/musicbox0 を書き込みモードで オープンしてから fwrite()で '0' という文字を1バイト書き込めば赤LEDが点灯する。最後にfclose()でファイルを閉じるのを忘れないこと。

(手順 3) エラー無くコンパイルが通り、教員のチェックを受けたら、先週と同様にターゲットPCをホストPCに接続してログインする。

(手順 4) アプリのビルド環境があるディレクトリに移動する。

$ cd device-control/musicbox/
$ ls

(手順 5) 先週と同様にソースコード(musicbox.cpp)のみをzmodemで転送する(他のファイルは転送しなくてよい)。

まずターゲットPC上でzmodemのリシーバを起動する。

$ rz

次にTeraTermのファイル → 転送 → zmodem → 送信から musicbox.cpp を転送する。転送したら ls で確認すること。

(注意) ファイルを転送する時に同じ名前のファイルがあると上書きで転送されないので、rz を起動する前に rm で消しておく。


(手順 6) アプリをビルドする。ビルドが成功するとアプリ( musicbox )が出来上がる。

$ ls
$ make
$ ls


チェック[5]-(a) アプリケーションのビルドを確認した。


(手順 7) アプリケーションを実行する。

(注意)

・ ドライバは既に組み込んでおくので先週の様に root になる必要は無い。そのまま実行し、ユーザ権限でターゲットPC上のデバイスを操作出来たことを確認せよ。

$ ./musicbox


チェック[5]-(b) 動作確認した。


(手順 8) exit コマンドでログアウトする。