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




目標:

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


評価方法:

レポート点(100 点)


注意点:

ソースコードのコピペが発覚した場合はコピーをさせた側の点数を0 点とし、コピーした側はお咎め無しとする (理由はHP 参照)


演習内容:

(一週目) デバイスドライバの作成

(システム構成)

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

そこで1週目は、ターゲットPCのシリアルインターフェース(RS232C)に接続された電子オルゴールのドライバを開発用PC上で作成し、ドライバをターゲットPCで動いているOSのカーネルにインストールし、電子オルゴールを動作させるという実験を行う。

今回使用するシステムの構成は以下の通りである。

制御対象デバイス:  電子オルゴール ( electronic music box )
ターゲットPC:  debian Linux 5 ( カーネル 2.6.26-2-686 )
開発用PC:  Windows 7

電子オルゴールはターゲットPCのシリアルインターフェース(RS232C)につながっている。通常は開発用PC上でクロスコンパイルしてドライバを作成するが、今回はソースコードを実験用USBメモリでターゲットPC上に移してからターゲットPC上でドライバをコンパイルして作成する。

(電子オルゴール仕様)

ターゲットPCのシリアルインターフェース(RS-232C)の DTRピン( Dサブ9ピンの4番ピン) に電子オルゴール回路が接続されている。 したがってRTSピン を H にすれば音楽が再生され、Lにすれば停止する。

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

使用するデバイスの回路図を以下に示す。



(手順 1) UART(Universal Asynchronous Receiver Transmitter)とは パソコンや組み込み機器などで使われるシリアル回路のことで、PC/AT互換機 では16550 互換チップと呼ばれるチップが広く使われている (参考までに、この後の実験で行なわれるシリアルインターフェースに関する実験では8251Aというチップを用いる。)

ターゲットPCにインストールされたOS(Debian Linux)がどのようにシリアルインターフェースを認識しているかは次の様にデバイスのログを見て確認することが出来る。

$ dmesg

教員がターゲットPC上で実行したdmesgコマンドの結果を見てOSが実際にUARTをどのように認識しているか確認すること。


(手順 2) デバイスドライバはIOポートを経由してデバイス上にあるレジスタにデータを読み書きすることでデバイスを制御する。 OSによってデバイスごとに別々にIOボートのアドレスが割り当てられており、IOボートへの読み書きは通常のメモリへの読み書きと同様に行なわれる (なお、現在はIOポート経由でデバイスを制御する方法は若干古い方法となっており、 メモリマップドIO ( MMIO ) 方式と呼ばれる制御方式が主流となっている。詳しくは OS の講義の時間に説明される。)

実際にどのようにIOポートのアドレスが割り当てられているか調べたい場合はターゲットPC上の /proc/ioports というファイルの内容を見る。

$ cat /proc/ioports

今回はシリアルインターフェース(16550)のレジスタの値を書き換えることで電子オルゴールの操作を行う。

教員がターゲットPC上で表示した /proc/ioports の内容を見てシリアルインターフェース(16550)のIOボートアドレスを確認すること。


(手順 3) ドライバのソースが入っているアーカイバ(devmbox2014.zip)を開発用PC上にダウンロードする。

ドライバソース (.zip)


(手順 4) devmbox2014.zip を解凍し(ダブルクリックしても解凍しないので注意)、ソリューションファイルをVC++で開く。あとはソースファイル(devmbox.c)内の記述に従ってドライバを作成する。

(注意)

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

unsigned char inb ( unsigned short int port );

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

例えば現在のMCRのレジスタ内容を reg という非負8bit整数型変数に取得してそのままMCRに書き込むには次のようにする。

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

以上を下の図にまとめる。


チェック[1] ソースコードを作成し、ホストPC上でエミュレータを実行して正しく動作した。


(手順 5) デバイスドライバのソース(devmbox.c)を実験用USBメモリにコピーする。コピーに失敗するときはUSBメモリをクイックフォーマットしてから再コピーする。

(手順 6) 実験用USBメモリをターゲットPCに挿し、認識するまで数秒待ってからマウントして内容を確認する。

(注意) 手順6,7,8,10の作業は管理者(root)になって実行する(プロンプトが#となっていることに注目)。なお、管理者(root)がコマンドを間違えるとハードディスク全体が消えることもあるので慎重に作業を行なうこと。

# mount -t vfat /dev/sda1 ./usb/ (エラーが出たときはUSBを挿し直して数秒待ってからもう一回実行。それでもエラーが出るときはsda1をsdb1に変える)
# cd usb
# ls   (devmbox.cがあるのを確認)

(手順 7) 作業用ディレクトリにドライバソースを移動してからビルドする。ビルドが成功するとデバイスドライバ( devmbox.ko )が出来上がる。

# mv devmbox.c /root/
# cd /root/
# ls
# make
# ls   (devmbox.koがあるのを確認)

(手順 8) デバイスには通常はOS(カーネル)か管理者(root)で無ければアクセス出来ない。 よって一般ユーザは直接デバイスを制御できないので、一般ユーザがデバイスを制御するためには、 ユーザーとデバイス間の橋渡し役であるデバイスドライバをカーネルにインストールする必要がある。 一度ドライバをカーネルにインストールすればOS(カーネル)がユーザーの代わりにデバイスを制御してくれる。

# insmod devmbox.ko
# dmesg

dmesgで自分の番号と名前が表示されることを確認せよ。

(手順 9) Alt+F2を押して一般ユーザーモードに切り替える(端末のプロンプトが#から$に変わった事を確認せよ)。一般ユーザーモードからechoコマンドを使ってデバイススペシャルファイル( /dev/musicbox0 )に文字を直接書き込んで動作確認する。

$ echo '0' > /dev/musicbox0
$ echo '1' > /dev/musicbox0

(注意)
・ > はリダイレクトと呼び、echo で出力した文字をそのまま > の後のファイルに書き込むものである(3年の実験を思い出せ)
・一般ユーザはデバイスを直接制御できないが、ドライバへのアクセスはスペシャルファイルに文字を書き込むことで一般ユーザーでも可能になっていることに注目せよ。

(手順 10) Alt+F1を押して管理者モードに切り替える(端末のプロンプトが$から#に変わった事を確認せよ)。その後ドライバをアンインストールし、次の実験者のために使用したファイルを削除し、実験用USBメモリをアンマウントする。

# rmmod devmbox
# dmesg
# make clean
# rm devmbox.*
# ls
# umount ./usb/


チェック[2] 一週目の最後まで終わった。



(2週目) ユーザーアプリケーションの作成

2週目は、開発用PC上でユーザーアプリケーションを作成し、ソースをターゲットPCに移してコンパイルし、ターゲットPC上で電子オルゴールを一般ユーザー権限で操作する。


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

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


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

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

$ echo '0' > /dev/musicbox0

のようにデバイススペシャルファイル( /dev/musicbox0 ) へ 文字 '0' を直接書き込んだら演奏開始したことを思い出せ。
従って通常のファイルへの書き込みのように、プログラム内で fopen()で /dev/musicbox0 を書き込みモードでオープンしてから fwrite()又は fprintf() で '0' という文字を1バイト書き込めば演奏が開始する。最後にfclose()でファイルを閉じるのを忘れないこと。


チェック[3] ソースコードを作成し、ホストPC上でエミュレータを実行して正しく動作した。


(手順 3) アプリケーションのソース(musicbox.cpp)を実験用USBメモリにコピーする。コピーに失敗するときはUSBメモリをクイックフォーマットしてから再コピーする。

(手順 4) 実験用USBメモリをターゲットPCに挿し、認識するまで数秒待ってからマウントして内容を確認し、一般ユーザーのディレクトリにソースを移動する。

# mount -t vfat /dev/sda1 ./usb/  (エラーが出たときはUSBを挿し直して数秒待ってからもう一回実行。それでもエラーが出るときはsda1をsdb1に変える)
# cd usb
# ls   (musicbox.cppがあるのを確認)
# mv musicbox.cpp /home/jikken14



(手順 5) Alt+F2を押して一般ユーザーモードに切り替え(端末のプロンプトが#から$に変わった事を確認せよ)、一般ユーザーモードでアプリをビルドする。ビルドが成功するとアプリ(a.out)が出来上がる。

$ ls
$ g++ musicbox.cpp
$ ls   (a.outがあるのを確認)


(手順 6) アプリケーションを実行する。確認したら次の人のためにファイルを削除する。

$ ./a.out
$ rm a.out
$ rm musicbox.cpp (消すかどうか聞いてきたらyを押してエンター)

(注意)

・ ドライバは事前にインストールしておくので、アプリはそのまま実行してよい。アプリは一般ユーザモードで実行していることに着目せよ。


(手順 7) Alt+F1を押して管理者モードに切り替える(端末のプロンプトが$から#に変わった事を確認せよ)。その後実験用USBメモリをアンマウントする。

# cd
# umount ./usb/

チェック[4] 二週目の最後まで終わった。



(問題 1) デバイスドライバとは何であるかを30字以内にまとめよ。


(問題 2) カーネルとは何であるかを30字以内にまとめよ。


(問題 3) ドライバが必要な理由を「デバイス」、「カーネル」、「管理者」、「一般ユーザー」という言葉を使用して100字以内にまとめよ。


(問題 4) ドライバのソースのうち、自分がコーディングした部分をレポートに示せ。


(問題 5) ユーザーアプリケーションのソースをレポートに示せ。