2005年7月28日木曜日

uClinuxでデバイスドライバを書いてみた

uClinuxがやっとブートした話のつづき。



この、某CPUの評価ボードには、プログラム中から制御できるLEDが16個ついている。こうなったら、なにはさておき、「ナイトライダー」を作らなくては、気がすまない(笑)。



PDFのハードウェアマニュアルを斜め読みしていくと、あるアドレスに16ビットデータを書き込めばLEDが点灯することがわかる。



そこで、簡単なテストプログラム数行を、C言語で書いて、実行してみると、Memory Faultとかいうようなエラーがでて、LEDの点灯状況はまったく変化しない。このエラーメッセージは、シグナルハンドラで出しているっぽい雰囲気。



組み込みネットに掲載されていたuClinuxの紹介記事によれば、uClinuxでは、MMUをサポートしていないので、メモリ・プロテクションも、アドレス変換もなにもしていない、と書いてあった。実は、これは、古い情報だったらしい。実際には、メモリ保護は実装されていた。だから、ユーザープログラムからは、LEDを制御するアドレスへの書き込みは、許可されていないらしい。



そのことを知らずに、/dev/memをつかったり、mmapしてみたりしたけど、ぜんぜんダメ。それが月曜までの状況。



今日になって、メモリ保護が実装されてんじゃないの?という疑いがムクムクっともちあがり、カーネルソースをざざーっとながめる。やっぱり、実装されてんじゃん。。。と、ようやく気が付く。てゆーか、そのCPUアーキ用にかかれたドキュメントをみれば、すぐわかったことだった。



じゃあどうしようかな、ってことで、LEDを制御するデバドラを書いてみることにした。デバイスドライバを書くのは、MS-DOS以来だ。



procfsを使うと簡単らしいことが、グーグルしてみてすぐわかった。



適当にコピペ。



ググッた情報は、どのバージョンのlinuxのことだかぜんぜん書いてないものが多く、どうもそのままでは動かないっぽい。コンパイルオプションとか、コーディングの流儀とかも、微妙に違うらしい。



とりあえず、今あるカーネルソースに含まれているデバイスドライバを参考に、手直しをする。



1時間ほどして、ようやく動いた。ソースコードは100行ほど。insmodしたとき、ちょっと、わけのわかんないエラーがでるので、一部の機能は殺した。



echo "0000111111110000" >/proc/led みたいにして、LEDが点灯することを確認。



あとは、ナイトライダーするプログラムは、シェルスクリプトで書き、実行。



とりあえず、これで満足した。





0 件のコメント:

コメントを投稿