_ 2004/01/11: What's new 追加.
_ 2004/01/11: デバイスドライバ関連統合.
_ 2004/01/11: L-CardAの設定にftpdの自動起動の設定方法を追記.
_ 2004/01/11: デバイスドライバ関連でシンプルなI/Oドライバ公開.
<CD-ROOT>/monitor/src/L-CardA/vr4181a.hに以下のような記述を発見.これを元にGPIOをたたけば良いのだろうか?
#define VR4181A_INTCS_BASE 0xaa000000 #define INTCS(a) (VR4181A_INTCS_BASE+(a)) : #define VR4181A_GPMODE0 INTCS(0x00b300)
下のあやしいファイルを探訪中,<CD-ROOT>/linux/include/asm-mips/vr41xx/toadkk-tcs8000.hにI/Oアドレス空間の定義を発見.このファイルをincludeしてドライバを書けば良いらしい.
拡張バス1ピンNo. | VR4181A信号名 | レジスタ名 | I/Oアドレス |
51〜65(奇数) | GPIO40〜47 | GPMODE5 | 0x00b30a |
52〜66(偶数) | GPIO0〜7 | GPMODE0 | 0x00b300 |
67,69 | GPIO48,49 | GPMODE6 | 0x00b30c |
68,70 | GPIO8,9 | GPMODE1 | 0x00b302 |
<CD-ROOT>/linux/以下でTCS8000用の修正が入っていると思われるファイルの一覧
$ find . -type f -exec grep -q TCS8000 {} \; -print ./arch/mips/config-shared.in ./arch/mips/kernel/head.S ./arch/mips/kernel/setup.c ./arch/mips/Makefile ./arch/mips/vr41xx/common/bcu.c ./arch/mips/vr41xx/common/giu.c ./arch/mips/vr41xx/common/icu.c ./arch/mips/vr41xx/common/Makefile ./arch/mips/vr41xx/common/reset.c ./arch/mips/vr41xx/common/serial.c ./arch/mips/vr41xx/toadkk-tcs8000/init.c ./config ./drivers/mtd/maps/vr4181a-flash.c ./drivers/net/ne.c ./drivers/pcmcia/vr4181a_busops.c ./drivers/pcmcia/vr4181a_generic.c ./drivers/pcmcia/vr4181a_generic.c.XXX ./include/asm-mips/bootinfo.h ./include/asm-mips/serial.h ./include/asm-mips/vr41xx/toadkk-tcs8000.h ./include/asm-mips/vr41xx/vr4181a_pcmcia.h ./include/asm-mips/vr41xx/vr41xx.h
$ find . -type f -exec grep -q tcs8000_setup {} \; -print ./arch/mips/boot/vmlinux.binary ./arch/mips/kernel/setup.c ./arch/mips/vr41xx/toadkk-tcs8000/setup.c
arch/mips/vr41xx/common/giu.cがビンゴのような気がするが...
とりあえず備忘として。
mount -o rw,remount / mknod /dev/gpio0 c 100 0
/sbin/insmod ./tcs_gpio.o
echo -n "ABCD" > /dev/gpio0
これでLEDが無事点滅
コンパイル時のオプションをちゃんと指定しないと、デバイスのロード時に
insmod: Relocation overflow of type 4 for printkなどと文句をいわれる。Software Design 2003/7の記事を参考に以下のようなMakefileを作成。
CC = mipsel-linux-gcc LD = mipsel-linux-ld SHELL = sh KERNELDIR = /usr/src/mipsel-linux include $(KERNELDIR)/.config CFLAGS = -D__KERNEL__ -DMODULE -DLINUX -DEXPORT_SYMTAB -DCONFIG_PROC_FS CFLAGS += -mno-abicalls -fno-pic -mtune=r4600 -mips2 -mlong-calls CFLAGS += -I$(KERNELDIR)/include -O2 -pipe -Wall all: module.o tcs_gpio.o clean: rm -f *.o
L-CardAのGI[1-8]を8ビットの入力,GO[1-8]を8ビットの出力に見立てたシンプルなデバイスドライバです.東亜DKKのTCS-8000開発キット上のLEDを点滅させることが出来ます.入力用のスイッチ回路部分は自作する必要があります.上のサブタイトルからソースのtarボールがダウンロードできます.
今回の配布物にはライセンスの記述がありませんが,これは,ライセンスも含めてどう扱おうと自由であるという意思表示だと思って下さい.これはあくまで現時点での判断であり,ここで公開するドライバに,今後もずっとライセンスを付けないという意味ではありません.
tarボールを展開すると,以下のようなファイル郡が作成されます.
[tcsgpio] + Makecile ドライバのmakefile + tcsgpio.h ドライバのヘッダファイル + tcsgpio.c ドライバ本体 + rc.gpio ドライバの追加・削除用スクリプト + [user-sample] + Makefile サンプルアプリケーションのmakefile + io.c io サンプル + k2000.c LED 点滅サンプル
tcsgpioディレクトリで make を実行することにより,tcsgpio.oという名前のデバイスドライバモジュールが作成されます.また,user-sampleディレクトリで make を実行すると,サンプルプログラムが作成されます.
まず,コンパイルしたtcsgpio.oをL-CardAにコピーします.次にinsmodコマンドを使ってモジュールをロードします.
# /sbin/insmod ./tcsgpio.o
insmodコマンドが無事終了したら,デバイス用のスペシャルファイルを作成します.このドライバはデバイス番号の動的な割り当てを使っているので,まず,デバイス番号を調べます.
# cat /proc/devices | sed 's/ tcsgpio//p;/^.*/d' 253 <- tcsgpio には253番が割り当てられている # mount -o rw,remount / # mknod /dev/gpio0 c 253 0 <- メジャー番号 253, マイナー番号 0,デバイスファイル名は/dev/gpio0. # chown root:admin /dev/gpio0 # chmod g+w /dev/gpio0
これで準備は完了です.
GI[1-8]の状態を読み込んで,標準出力およびGO[1-8]に出力するプログラムです.GI[1-8]に接続したスイッチを切り替えた後に実行すると,その状態に合わせてGO[1-8]に接続されたLED等を明滅させることが出来ます.
LEDを点滅させるプログラムです.実行すると単純なパターンでの点滅を永遠に繰り返します.
以上
定番
2.2.xでの実装なので,オライリーの本と付き合わせて適宜読み替える.
L-CardAのハードと,USBを使ったデバイスドライバの作成方についての解説.
必要な部分だけ拾い読み.
必要な情報がコンパクトにまとまっていて良い.東亜DKKの開発キット付属のCD-ROMに収録されている.
Let's NoteにVine Linux 2.6r1(日経Linux2003年6月号付属)をインストール.ホスト名は「fengr」.
* 起動画面: Enter(グラフィカルモード) * Language Selection: Japanese * キーボード モデル:Japanese 106-key レイアウト: U.S. English * マウス: 2 button Mouse (PS/2) * ようこそ: 次へ * インストールの種類:インストール.ラップトップ * ディスクパーティション設定:インストーラが自動的... * 自動パーティション設定:システムのすべてのパーティションを削除 * ディスクの設定: 次へ * ブートローダの設定: 次へ * ネットワークの設定: 次へ * 追加言語サポート:English追加 * タイムゾーン: 次へ * アカウントの設定:個人アカウント追加 * パッケージグループの選択: 次へ * グラフィカルインターフェースの設定: 次へ * 起動ディスクの作成: 省略 * モニタの設定: Laptop 1024 x 768 * X設定のカスタマイズ: 次へ
# apt-get update # package list を取ってくる # apt-get udgrade # 実際に更新する
Software Design 2003年7月号 pp. 147-148を参考に作業を進める.
% cd % mkdir L-Card % cd L-Card % cd /mnt/cdrom % tar cf - . | tar xvfC - ~/L-Card
% cd ~/L-Card/toolchains/RPMS % su # rpm -ivh *.rpm
# cd ~hs/L-Card/linux # mkdir /usr/src/mipsel-linux # cp -r * /usr/src/mipsel-linux # cd /usr/src/mipsel-linux # cp config .config # make menuconfig 何も変更せずにExitしてセーブだけする. # make dep clean vmlinux
addpath $HOME/bin addpath /sbin addpath /usr/sbin
#!/bin/sh xmodmap ${HOME}/.xmodmaprc if [ -x /etc/X11/xinit/Xclients ]; then exec "/etc/X11/xinit/Xclients" fi
remove Lock = Caps_Lock (Caps_LockをCtrlに) remove Control = Control_L keysym Caps_Lock = Control_L add Control = Control_L keycode 49 = Escape (半角/全角をEscに) keycode 123 = grave asciitilde (「\」を「`」に)
telnetで接続し,パスワードを変更.
% telnet 192.168.0.5 $ su # mount -o rw,remount / # passwd admin # sync;sync;sync # mount -o ro,remount / # sync;sync;sync # poweroff (フラッシュROMなので念のため)
poweroffやhaltコマンドを実行するとtelnetは出来なくなるがpingは通るので,シングルユーザやモニタモードに落ちるわけではないようだ.ちょっと不安.
フラッシュROMがちゃんと書き換えられていることを確認するため,コンセントを抜いてから挿しなおし,telnetでパスワードを聞かれるか確認.
% telnet 192.168.0.5 $ su # mount -o rw,remount / # vi /etc/config NET_IPを変更 # sync;sync;sync # mount -o ro,remount / # sync;sync;sync # poweroff (フラッシュROMなので念のため)
これでようやく名前付きのホストとしてネットワークに参加.「loni」と命名.この時点で接続不能問題は解消.原因はルータ(FreeBSD)のproxyarp.
やり取りするファイルが増えてきたのでftpdを起動.ホストによるアクセス制限が出来ないみたい.
# mount -o rw,remount /
# vi /etc/ftpusers (admin を削除) # sync; sync; sync;
# vi /etc/config FTPD = yes
# sync; sync; sync # mount -o ro,remount / # reboot
起動後,ftpでログインできたら成功.
CF(TDK製32MB)をfengrのPCカードスロットに差し込む.dmesgのログは以下の通り.
hdc: TDK TC_H, CFA DISK drive ide1 at 0x100-0x107,0x10e on irq 3 ide-floppy driver 0.99.newide hdc: task_no_data_intr: status=0x51 { DriveReady SeekComplete Error } hdc: task_no_data_intr: error=0x04 { DriveStatusError } hdc: 62592 sectors (32 MB) w/1KiB Cache, CHS=489/4/32 hdc: hdc1 ide_cs: hdc: Vcc = 3.3, Vpp = 0.0
上記ログよりこのカードが「hdc」として認識されていることがわかるので,fdiskコマンドを使ってLinuxパーティションを作成.
# fdisk /dev/hdc コマンド (m でヘルプ): m コマンドの動作 a ブート可能フラグをつける b bsd ディスクラベルを編集する c dos 互換フラグをつける d 領域を削除する l 既知の領域タイプをリスト表示する m このメニューを表示する n 新たに領域を作成する o 新たに空の DOS 領域テーブルを作成する p 領域テーブルを表示する q 変更を保存せずに終了する s 空の Sun ディスクラベルを作成する t 領域のシステム ID を変更する u 表示/項目ユニットを変更する v 領域テーブルを照合する w テーブルをディスクに書き込み、終了する x 特別な機能 (エキスパート専用) コマンド (m でヘルプ): p ディスク /dev/hdc: ヘッド 4, セクタ 32, シリンダ 489 ユニット = シリンダ数 of 128 * 512 バイト デバイス ブート 始点 終点 ブロック ID システム /dev/hdc1 1 489 31295+ 4 FAT16 <32M コマンド (m でヘルプ): d 領域番号 (1-4): 1 コマンド (m でヘルプ): n コマンドアクション e 拡張 p 基本領域 (1-4) p 領域番号 (1-4): 1 最初 シリンダ (1-489, 初期値 1): 初期値 1 を使います 終点 シリンダ または +サイズ または +サイズM または +サイズK (1-489, 初期値 489): 初期値 489 を使います コマンド (m でヘルプ): w 領域テーブルは交換されました! ioctl() を呼び出して領域テーブルを再読込みします。 ディスクを同期させます。
※: cfdiskコマンドというのもあり,そっちのほうが分かりやすい.
fdiskを使ってパーティション情報を確認する.
# fdisk -l /dev/hdc ディスク /dev/hdc: ヘッド 4, セクタ 32, シリンダ 489 ユニット = シリンダ数 of 128 * 512 バイト デバイス ブート 始点 終点 ブロック ID システム /dev/hdc1 1 489 31280 83 Linux
上記の結果より,作成したパーティションの名前が「/dev/hdc1」であることが分かるので,mke2fsコマンドを使ってCF上にファイルシステムを構築.
引数に指定されたファイルシステムを初期化する危険なコマンドなので,デバイス(今回の場合,/dev/hdc1)を間違えないこと.
# mke2fs /dev/hdc1 mke2fs 1.29 (24-Sep-2002) Filesystem label= OS type: Linux Block size=1024 (log=0) Fragment size=1024 (log=0) 7840 inodes, 31280 blocks 1564 blocks (5.00%) reserved for the super user First data block=1 4 block groups 8192 blocks per group, 8192 fragments per group 1960 inodes per group Superblock backups stored on blocks: 8193, 24577 Writing inode tables: done Writing superblocks and filesystem accounting information: done This filesystem will be automatically checked every 39 mounts or 180 days, whichever comes first. Use tune2fs -c or -i to override.
作成したファイルシステムをマウント.
# mkdir /mnt/cf # mount /dev/hdc1 /mnt/cf # chmod 775 /mnt/cf (グループ書き込み可にする)
簡単なプログラムを作ってコンパイルし,CFカードにコピー.
% vi hello.c % mipsel-linux-gcc -o hello hello.c % cp hello /mnt/cf % su # sync;sync;sync # umount /mnt/cf
fengrからCFカードを抜きloniに挿す.
loni# tail -f /var/log/messages : cardmgr[42]: socket 0: Anonymous Memory cardmgr[42]: executing: 'modprobe memory_cs' cardmgr[42]: + insmod: memory_cs.o: no module by that name found cardmgr[42]: modprobe exited with status 1 cardmgr[42]: module /lib/modules/2.4.19-rc1/pcmcia/memory_cs.o not available cardmgr[42]: get dev info on socket 0 failed: Resource temporarily unavailable
というログを残して認識失敗./lib/modules/2.4.19-rc1/pcmcia/memory_cs.oが無いと言っているようなので,確認.
loni# ls /lib/modules/2.4.19-rc1/pcmcia/ pcnet_cs.o serial_cs.o
確かに無い.fengrのソースツリーを探してみる.
fengr# cd /usr/src/mipsel-linux/ fengr# find . -name \*memory_cs\* -print
無い.fengrの中を探すと/lib/modules/2.2.20-0vl10/pcmcia/の下にあった. 一方loniには/lib/modules/2.2.20-*というディレクトリはない.マニュアルを読むと日立製のメモリカードでは動作しないとあるので,OEMなのかな.手元にもう一枚あったPrincetonのカードを挿すと,同じログで,
hdc: Hitachi ATA Card, CFA DISK drive
と出るのでほぼ確定.手元にはこれ以上カードが無いのであきらめる.
SanDiskの64MBを購入して再挑戦.まずはloniに挿してみる.
loni# tail -f /var/log/messages : cardmgr[42]: socket 0: ATA/IDE Fixed Disk cardmgr[42]: executing: 'modprobe ide-cs' cardmgr[42]: + Using /lib/modules/2.4.19-rc1/kernel/drivers/ide/ide-cs.o cardmgr[42]: executing: 'modprobe ide-disk' cardmgr[42]: + Using /lib/modules/2.4.19-rc1/kernel/drivers/ide/ide-disk.o klogd: Trying to free nonexistent resource 2000000-b200000f> klogd: hda: SanDisk SDCFB-64, ATA DISK drive klogd: ide0 at 0xb2000000-0xb2000007,0xb200000e on irq 25 klogd: hda: 125440 sectors (64 MB) w/1KiB Cache, CHS=490/8/32 klogd: Partition check: klogd: hda1 klogd: ide_cs: hda: Vcc = 3.3, Vpp = 0.0 cardmgr[42]: executing: './ide start hda'
というわけで,認識成功\(^o^)/.fengrに挿し直し,上記手順を見ながら再び初期化(手順は省略).
fengrでファイルをコピーした後,loniに再び挿してマウント
loni# mount /dev/hda1 /mnt/flash
ファイルを確認し,テスト.
loni# ls /mnt/flash hello lost+found loni# /mnt/flash/hello Hello, world!
感無量.
ウェブサーバに実行ファイルをコピー
fengr% scp hello webserver:public_html/
loniにログインしwgetを使って実行ファイルを取得.
loni# cd /mnt/rw loni# wget http://webserver/~hs/hello hello 100% |*****************************| 8516 00:00 ETA
実行ビットを立ててテスト.
loni# chmod +x hello loni# ./hello Hello, world!
とりあえずfengr上の開発環境はうまく構築できた模様.fengrとloniだけで開発できるような体制にしないといけないが,apacheやanon ftpサーバ立ち上げるのもなぁ.