TUT-0003 www.interface.co.jp Ver. 1.8 改訂履歴 改訂履歴 Ver 年 月 1.0 1.1 1.2 2001 年 9 月 2001 年 10 月 2001 年 11 月 1.3 1.4 1.5 1.6 1.7 2002 年 4 月 2002 年 7 月 2002 年 11 月 2003 年 8 月 2004 年 5 月 1.8 2005 年 3 月 改 訂 内 容 初版 Linux カーネル 2.4 に対応した記述を追加 CompactPCI ボードに対応した記述を追加 insmod コマンドに関する説明を補足 Tips を追加 Linux 対応ソフトウェア製品を更新 CardBus カードに関する記述を追加 ソフトウェア製品の改版に合わせて更新 CardBus に対応した記述を追加 誤記修正 技術資料一覧更新 誤記修正 本チュートリアルをご使用の際は、必ず各製品型式の最新のドキュメント(ユーザーズマニュアル,オンライ ンヘルプ)をあわせて参照してください。また、最新のドライバソフトウェアをご使用ください。ユーザー ズマニュアル, ドライバソフトウェアは弊社 Web site からダウンロードできます。(オンラインヘルプはドラ イバソフトウェアに含まれています) 商標/登録商標 Linux は Linus Torvalds 氏の商標です。 Kylix は米国 Borland Software Corporation の商標または登録商標です。 その他、本書に掲載されている会社名、製品名は、それぞれ各社の商標または登録商標です。 保証の内容と制限 株式会社インタフェースは本書の情報の正確さに万全を期しています。万一、誤記または誤植などがあった 場合、株式会社インタフェースは予告無く改訂する場合があります。本書または本書内の情報に起因するい かなる損害に対しても株式会社インタフェースは責任を負いません。 本書の図や表は説明のためであり、ユーザ個別の応用事例により変化する場合があります。 著作権、知的所有権 株式会社インタフェースは本書に対する権利や知的所有権を保持しています。 本書はコンピュータ ソフトウェア(プログラム)、 図、 文章、 写真などを含んでいます。 複製の禁止 株式会社インタフェースの許可なく、本書の全て、または一部に関わらず、複製、改変などを行うことはで きません。 責任の制限 株式会社インタフェースは、株式会社インタフェース または再販売者の予見の有無にかかわらず発生した いかなる特別損害、偶発的損害、間接的な損害、重大な損害について、責任を負いません。 © 2001, 2005 Interface Corporation. All rights reserved. 目次 [目次] はじめに.............................................................................................................1 第一章 Linux のハードウェア制御 .............................................................2 基礎編 ................................................................................................................................................2 Linux のハードウェア制御 .............................................................................................................2 Linux からの PCI ボード、CompactPCI ボードの認識 .............................................................3 ■CardBus カードの認識と制御.................................................4 デバイスドライバ ............................................................................................................................5 応用編 ................................................................................................................................................7 デバイスノードとデバイスファイルシステム.............................................................................7 ■デバイスノード ............................................................7 ■デバイスファイルシステム ..................................................9 デバイスドライバによる I/O 領域、IRQ の予約 ......................................................................10 Linux 起動時にデバイスドライバを自動的に組み込む ...........................................................11 ライブラリ ......................................................................................................................................12 第二章 Linux のプログラミング開発環境 ...............................................13 基礎編: ..........................................................................................................................................13 Linux のプログラミング開発環境 ...............................................................................................13 エディタ ..........................................................................................................................................14 ■Vi .......................................................................14 ■Emacs ....................................................................16 コンパイラ、コンパイルオプション ..........................................................................................17 第三章 ボードを制御するプログラムの作成 ..........................................18 基礎編 ..............................................................................................................................................18 弊社ボード用 Linux 対応ソフトウェアからの制御 ..................................................................18 汎用入出力ライブラリ BPL-0804 について ...............................................................................19 PCI コンフィグレーションレジスタ情報の取得.......................................................................20 I/O 領域へのアクセス....................................................................................................................21 メモリ領域へのアクセス ..............................................................................................................24 応用編 ..............................................................................................................................................26 割り込み処理 ..................................................................................................................................26 PCI コンフィグレーションレジスタへの書き込み...................................................................31 第四章 GTK+を使った GUI アプリケーションの作成..........................33 基礎編 ..............................................................................................................................................33 ソースコードの雛形 ......................................................................................................................33 © 2001, 2005 Interface Corporation. All rights reserved. 目次 ■コンパイル ...............................................................35 GTK+の主な関数 ...........................................................................................................................36 応用編 ..............................................................................................................................................39 周期実行 ..........................................................................................................................................39 GTK+を使ったデジタル入力ボード用サンプルプログラム....................................................41 第五章 ツール”Glade”を使った GUI アプリケーション作成.................44 基礎編 ..............................................................................................................................................44 Glade について ...............................................................................................................................44 ■Glade の起動から実行ファイル作成までの手順................................45 ■Glade が自動作成するソースコードについて..................................46 ■ライブラリのリンク .......................................................47 Glade の操作法 ...............................................................................................................................48 応用編 ..............................................................................................................................................50 ウィジェットのハンドラを取得する ..........................................................................................50 カスタムウィジェットで自由に画面を作成する.......................................................................51 Glade を使ったデジタル出力ボード用サンプルプログラム....................................................54 第六章 Kylix を使った GUI アプリケーションの作成 ..........................57 基礎編 ..............................................................................................................................................57 Kylix の基本的な使い方 ................................................................................................................57 共有ライブラリのインポート ......................................................................................................59 応用編 ..............................................................................................................................................60 ユニットファイルの追加 ..............................................................................................................60 Kylix で作成したデジタル入力ボード用サンプルプログラム ................................................61 Linux 対応ソフトウェア製品の紹介 ...........................................................63 技術資料紹介...................................................................................................65 参考文献...........................................................................................................66 © 2001, 2005 Interface Corporation. All rights reserved. はじめに はじめに 平素は格別のご高配を賜り、厚くお礼申し上げます。本冊子は Linux 上で弊社 PCI ボード、 CompactPCI ボード、CardBus カード(以降、特に断らない限りボードと呼びます)を制御したい方 を対象に、Linux でのハードウェア制御、プログラミング環境からコンソールアプリケーション、 GUI アプリケーションの作成方法と、そこからハードウェアを制御するアプリケーションの作成 方法までを記載しています。Linux 上での弊社製品をはじめとするハードウェア制御のためのプ ログラミングにお役に立てれば幸いです。 なお本冊子は Linux カーネル 2.2 系、2.4系を対象に作成されています。カーネルバージョンが異 なる場合、動作保証はいたしかねますので予めご了承ください。 ●ご意見,ご要望 弊社へのご意見,ご要望がございましたら、下記までお問い合わせください。 www.interface.co.jp E-mail:support@interface.co.jp ●本書での表記について コマンドの実行例において、行頭に「%」がつく場合は一般ユーザでの実行、「#」がつく場合は root での実行を意味します。「%」や「#」は実際に入力する文字ではありませんのでご注意くだ さい。 © 2001, 2005 Interface Corporation. All rights reserved. 1 第一章 第一章 Linux のハードウェア制御 Linux のハードウェア制御 基礎編 Linux のハードウェア制御 Linux の場合、Windows と同様にユーザアプリケーションから直接、PCI ボード、CompactPCI ボ ードをはじめとするハードウェアを制御することはできません。これは不用意にハードウェアリ ソースにアクセスできると、人為的なミスや悪意のあるユーザによってシステムが破壊されてし まう危険性があるからです。 そのため、システムコール※1 を使ってデバイスドライバを経由してハードウェアを制御します。 弊社 Linux 製品では、より使いやすくするためにシステムコールをラップした関数を用意し、ラ イブラリとして提供しています。 その結果、ユーザアプリケーションからはライブラリ関数を使用して、ハードウェアを制御しま す(図 1-1)。 ユーザアプリケーション ライブラリ関数の呼び出し ライブラリ ユーザ空間 カーネル空間 デバイスドライバ ハードウェア 図 1-1 アプリケーションによるハードウェア制御の概念図 ※1 プロセスからカーネルが提供する機能を呼び出す命令のこと © 2001, 2005 Interface Corporation. All rights reserved. 2 第一章 Linux のハードウェア制御 Linux からの PCI ボード、CompactPCI ボードの認識 Linux はプラグアンドプレイ OS ではないため、PCI ボード、CompactPCI ボードの I/O 領域、メモ リ領域、IRQ といったリソースの割り当てはコンピュータ起動時に BIOS が行います※2。 Linux は割り当てられた結果を検索し、結果を「/proc/pci」ファイルに出力します。Linux から PCI ボード、CompactPCI ボードのリソース情報を確認したい場合は、このファイルを参照します。通 常「cat /proc/pci」コマンドを利用します。 このコマンドを実行すると、PCI ボード、CompactPCI ボードのベンダ ID、デバイス ID、I/O ポー ト領域のベースアドレス、IRQ などをボードごとに取得できます。 「cat /proc/pci」コマンドの実行例:PCI-2702C を実装した状態(1) ※3 %cat /proc/pci PCI device found: (中略) Bus 0, device 16, function 0: Class ff00: PCI device 1147:0a8e (Interface Corp) (rev1). IRQ 11. I/O at 0xccd0 [0xccdf]. ※ PCI-2702C はベンダ ID(Vendor ID)が 1147h、デバイス ID(Device ID)が 0a8eh(2702)です。 この結果から、PCI-2702C は、PCI バス番号 0、デバイス番号 16 に存在し、 リソースとして IRQ:11、 I/O ポートのベースアドレス:CCD0h が割り振られていることがわかります。 また「lspci –v」コマンドでも同様に PCI ボードのリソース情報を確認できます。 「lspci –v」コマンドの実行例(1):PCI-2702C を実装した状態 %lspci –v 00:00.0 Host Bridge: Intel (中略) 00:10.0 Class ff00: Interface Corp: Unknown device 0a8e (rev01) Subsystem: Interface Corp: Unknown device 0001 Flags: medium devsel, IRQ 11 I/O ports at ccd0 [size=16] ※2 BIOS に「プラグアンドプレイ OS かどうか」、の設定がある場合は「No」にします。「Yes」 に設定していると IRQ が正しく割り当てられない場合があります。 ※3 画面はカーネルバージョン 2.4 で実行したときのものです。 © 2001, 2005 Interface Corporation. All rights reserved. 3 第一章 Linux のハードウェア制御 ■CardBus カードの認識と制御 CardBus は、PC カードスロットの規格の一つで、これまでの PC カードが 16 ビット幅でアクセス していたのに対し、32 ビット幅でアクセス可能であるため、より高速にアクセスできます。 CardBus は PCI バスに準拠しているため、パソコン上からは PCI/ CompactPCI ボードと同様に認 識、制御できます。 「lspci –v」コマンドの実行例(2):CBI-2701 を実装した状態 CardBus コント %lspci –v ローラの情報 00:00.0 Host Bridge: Intel Corp. 85845 845 (Brookdale) Chipset Host (中略) 02:04.0 CardBus bridge: 02 Micro, Inc.: Unknown device 6972 Subsystem: Dell Computer Corporation: Unknown device 00f3 Flags: bus master, slow devsel, latency 32, IRQ 10 Memory at fdf00000 (32-bit, non-prefetchable) [size=4K] Bus: primary=02, secondary=03, subordinate=03, sec-latency=32 I/O window 0: 0000e400-0000e4ff I/O window 1: 00000000-00000003 16-bit legacy interface ports at 0001 03:00.0 Class ff00: Interface Corp: Unknown device 0a8d (rev01) Subsystem: Interface Corp: Unknown device 0201 Flags: medium devsel, IRQ 10 I/O ports at e400 [size=16] CBI-2701 の情報 弊社 CardBus-PCI/CompactPCI/CardBus バスブリッジ CBI-PCUxx,CBI-CTUxx,CBI-CBUxx でも、 付属ソフトウェア ACD-8521 に含まれる Linux 対応ソフトウェア GBG-8521 により、デスクトッ プパソコンの PCI-PCI バスブリッジと同様に ノートパソコンから拡張した PCI/CompactPCI/CardBus 製品をご利用いただけます。 © 2001, 2005 Interface Corporation. All rights reserved. 4 第一章 Linux のハードウェア制御 デバイスドライバ デバイスドライバには、キャラクタ型とブロック型とがあります。キャラクタ型は、シリアルポ ートのような単純なハードウェアの制御に適しており、ブロック型はハードディスクやフロッピ ーディスクなどブロック単位でデータ転送する場合に使われています。弊社ボードを制御する場 合は、キャラクタ型デバイスドライバを使用します。 デバイスドライバを使用するには「insmod」コマンドでドライバモジュールをカーネルに組み込 む必要があります。「insmod」コマンドは、モジュールの組み込みに使うコマンドです。このコ マンドの実行は root 権限が必要です(弊社 Linux 対応ドライバソフトウェアによっては、登録用の スクリプトファイル insxx.sh を用意している場合があります)。 このときカーネルバージョンが適していないと、正常にモジュールを組み込めない場合がありま す。「insmod」コマンド実行時に「‑f」オプションを追加すると強制的にデバイスドライバを組 み込むこともできますが、弊社 Linux 対応ドライバソフトウェアではドライバモジュール再構築 用のファイルを添付していますので、該当するファイルがあるディレクトリで Make を実行し、 再構築したモジュールを使用してください。 例:DIO ボード用ドライバソフトウェア GPG-2000 のドライバモジュールを再構築 ※デフォルトのインストール先を使用していると仮定します #cd /usr/src/interface/gpg2000/i386/linux/drivers/src #make gcc -D__KERNEL__ -DMODULE -O2 -Wall -I/usr/include -c -o dio.o dio.c ld -r –o cp2000.o diosub.o dio.o デバイスドライバが正常に組み込めたことを確認するためには「lsmod」コマンドを使用します。 「lsmod」コマンドを実行すると、組み込まれているモジュール名とその大きさ、利用度数(Used) が表示されます。利用度数とは、モジュールの利用状況を確認するための数字で、デバイスをオ ープンすることに1ずつ増え、クローズすれば1ずつ減ります。利用度数が0でないとき、すな わちモジュールが使用中の時は、モジュールの登録を削除することはできません。逆にデバイス が存在していても、デバイスをオープンしていないときは、利用度数が 0 でも問題ありません。 「lsmod」コマンドの実行例:DIO ボード用ドライバ cp2000.o を組み込んだ状態 %lsmod Module Size Used by cp2000 52720 0 (unused) autofs 9476 1 (autoclean) lockd 31592 1 (autoclean) sunrpc 53540 1 (autoclean) [lockd] © 2001, 2005 Interface Corporation. All rights reserved. 5 第一章 Linux のハードウェア制御 また「cat /proc/devices」コマンドを実行するとキャラクタ型とブロック型の各デバイスドラ イバのメジャー番号がわかります。メジャー番号は、カーネルがデバイスドライバを識別する番 号です。弊社ドライバモジュールの場合は、ドライバモジュール組み込み時に自動的に割り当て られます。 「cat /proc/devices」コマンドの実行例: DIO ボード用ドライバ cp2000.o を組み込んだ状態 %cat /proc/devices Character devices: 1 mem 2 pty (中略) 254 cp2000 Block devices: 1 ramdisk (後略) ※実行例では DIO ボード用ドライバ cp2000 のメジャー番号が 254 であることを示しています。 デバイスドライバの登録を解除する場合は、「rmmod」コマンドを使います(弊社 Linux 対応ドラ イバソフトウェアによっては、登録解除用のスクリプトファイル rmxx.sh を用意している場合が あります)。 「rmmod」コマンドの実行例:DIO ボード用ドライバの場合 #rmmod cp2000 © 2001, 2005 Interface Corporation. All rights reserved. 6 第一章 Linux のハードウェア制御 応用編 デバイスノードとデバイスファイルシステム ■デバイスノード デバイスドライバはユーザ空間ではデバイスファイルとして参照されます。このデバイスファイ ルをデバイスノード呼びます。アプリケーションからこのデバイスノードを呼び出してデバイス ドライバを制御します。 従ってデバイスドライバを組み込んだら、デバイスノードを作る必要があります。デバイスノー ドは、「/dev/」ディレクトリに作成し、デバイスドライバのメジャー番号、マイナー番号を関連 づけます。「mknod /dev/(デバイスノード名) c (メジャー番号) (マイナー番号)」の実行で、 デバイスノードを作成します。ここで「c」は、キャラクタ型デバイスを作成することを意味しま す。 実行例 マイナー番号 #mknod /dev/pci4910.0001.0 c 254 1 デバイスノード名 メジャー番号 またデバイスノードのメジャー番号、マイナー番号を確かめるには、「ls -l (デバイスノード名)」 コマンドを実行します。 マイナー番号 実行例 #ls -l /dev/pci4910.0001.0 crw-rw-rw- 1 root root 254, 1 Jun 15 14:18 /dev/pci4910.0001.0 c:キャラクタ型デバイスノ ードであることを示す メジャー番号 弊社 Linux 製品では、弊社のデバイスドライバを制御するためのデバイスノードを自動作成する プログラム dpg0101 を用意しています。このプログラムでは、弊社ボードに弊社がデバイス番号 と呼んでいるハードウェア識別のための番号を設定し、作成するデバイスノードと設定ファイル (/etc/interface/gpgxxxx.conf ファイル)によって、ユーザアプリケーションから、デバイス番 号を使って各ハードウェアを識別、制御することができます。 デバイス番号は、BIOS が自動的に決める PCI のバス番号や PCI ボード上にあるロータリスイッ チの設定値などとは関係なく、あくまで論理的なものです。 © 2001, 2005 Interface Corporation. All rights reserved. 7 第一章 Linux のハードウェア制御 デバイス番号設定プログラム dpg0101 の実行例 *************************************************** Setup Utility --------------------------------------------------Version: 1.01-02 ---------------------------------------------------ソフトウェアの型式 Copyright 2002 Interface Corporation. All rights reserved. *************************************************** Enter the model number of the product:GPG/GPH-2000 ======================================= Ref.ID | Model | RSW1 | Device No. RSW1 が「0」に設定された --------------------------------------1 | PCI/PAZ-2726C | 0 | 1 PCI/PAZ-2726C がデバイス番号 1 で ======================================= ************** Command ************* 登録されようとしていることを示し 1. Change the device number. 2. Delete the device number. ます。 3. Load new device setting file. 4. Run the initialization program. 99. Exit the program. ************************************ Enter the command number: ※この例は弊社 Linux 製品に付属しているデバイス番号設定プログラムを実行したところです。 Linux 汎用入出力ライブラリ BPL-0804 の場合は、デバイス番号という考え方はありませんが、同 様にデバイスノードを作成するプログラムとして、デバイスノード作成プログラムを用意してい ます。 © 2001, 2005 Interface Corporation. All rights reserved. 8 第一章 Linux のハードウェア制御 ■デバイスファイルシステム デバイスファイルシステムは、デバイスノードを動的に扱うことができるシステムで、Linux カ ーネル 2.4 からオプションで採用されました。 今までは、デバイスノードがない場合、mknod コマンドを使ってデバイスノードを作成する必要 がありましたが、このシステムを採用すると、ユーザアプリケーションがデバイスノードをオー プンしようとしたときにカーネルが自動的にデバイスノードを作成し、クローズすると削除する ようになります。 またデバイスノードが存在する「/dev/」ディレクトリも構成が変わり、たとえばシリアル通信 用のデバイスノードでは次のようになります。 例:シリアル通信用デバイスノード ・デバイスファイルシステム無効 /dev/ttyS1 ・デバイスファイルシステム有効 /dev/tts/1 「/dev/」ディレクトリに直接存在していたデバイスノードが「/dev/tts/」ディレクトリ」に存 在し、デバイスノード名がたんなる数字に変わりました。 このことはデバイスノードへのパスが変更することを意味しており、デバイスノードを直接制御 しているプログラムを使っている場合、デバイスファイルシステムに移行するときは、注意が必 要です。 なおカーネル 2.4 系のディストリビューションでは、インストール時にデフォルトでデバイスフ ァイルシステムが無効になっているものもあり、デバイスファイルシステムを有効にしなくても カーネル 2.4 を利用することは可能です。 弊社ソフトウェアのデバイスファイルシステムへの対応については、各ソフトウェアの readme にてご確認ください。 © 2001, 2005 Interface Corporation. All rights reserved. 9 第一章 Linux のハードウェア制御 デバイスドライバによる I/O 領域、IRQ の予約 弊社ボード用 Linux 対応ソフトウェアでは、insmod コマンドによるドライバモジュールの組み込 み時にボードのリソース情報を取得し、必要に応じ I/O 領域、メモリ領域、IRQ などを予約して います※4。 デバイスドライバが予約した I/O ポート領域、割り込み番号(IRQ)は、 「cat /proc/ioports」,「cat /proc/interrupts」コマンドでそれぞれ確認できます。 「cat /proc/ioports」コマンドの実行例:PCI-2702C を実装した場合 %cat /proc/ioports 0000-001f : dma1 0020-003f : pic1 (中略) 03f6-03f6 : ide0 7000-700f : PCI device 1147:0a8e (Interface Corp) 7000-700f : cp2000 ※実行例では DIO ボード用デバイスドライバ cp2000 が I/O 領域 7000-700Fh を予約していること を示しています(画面はカーネル 2.4 上で実行したもの)。 「cat /proc/interrupts」コマンドの実行例:PCI-2702C を実装した場合 %cat /proc/interrupts 0: 4479745 XT-PIC timer 1: 5020 XT-PIC keyboard (中略) 10: 0 XT-PIC cp2000 (後略) ※実行例では DIO ボード用デバイスドライバ cp2000 が IRQ10 を予約し、その割り込み回数が 0 であることを示しています。 ※4 ソフトウェア製品によっては、オープン関数実行時に予約する場合もあります。Linux 汎用入 出力ライブラリ BPL-0804 では、同ライブラリに用意してある予約用の関数を使う必要がありま す。 © 2001, 2005 Interface Corporation. All rights reserved. 10 第一章 Linux のハードウェア制御 Linux 起動時にデバイスドライバを自動的に組み込む デバイスドライバのようなモジュールは、動的にカーネルに組み込むため、通常、使用する前に 「insmod」コマンドによって組み込む必要があります。この場合、パソコンを再起動すると、そ の都度、手動で「insmod」コマンドを実行する必要があります。 これはシステム上深刻なトラブルが発生し、パソコンの再起動を余儀なくされるような場合にも ドライバモジュールを利用するために人手が必要になり、大変面倒です。 そこで、以下の方法を利用すると、Linux 起動時にドライバモジュールを自動的に組み込むこと が可能になります。 「/etc/rc.d/rc.local」ファイルの最後に「insmod /xxx/(ファイル名)」と記述して下さい。起動時 にドライバモジュールが組み込まれます。 (/xxx/は目的のデバイスドライバが存在する絶対パスです) なお、「/etc/rc.d/rc.local」ファイルの編集は root 権限が必要です。 例:汎用入出力ライブラリのドライバモジュール uio.o を Linux 起動時に自動で組み込む場合 以下の1行を「/etc/rc.d/rc.local」ファイルに記述します。 insmod /lib/modules/(カーネルバージョン)/misc/uio.o ※ドライバモジュール組み込み時に「-f」オプションが必要な場合は、同様に「-f」オプショ ンを記述してください。 insmod -f /lib/modules/(カーネルバージョン)/misc/uio.o ※「/lib/modules/(カーネルバージョン)/misc/」ディレクトリはドライバモジュールファイルが 格納される一般的なディレクトリです(ただしカーネル 2.4 のディストリビューションには デフォルトで作成しないものもあります)。このディレクトリを指定する場合、弊社 Linu 製品では、該当ディレクトリにモジュールファイルをコピーしなければならない場合があ ります(uio.o もコピーする必要があります)。 ※ GPG-2000、GPG-4910 などでは、モジュール組み込み時にシェルスクリプトを実行する必 要があるものがあります。詳細は各製品の README,オンラインヘルプをご覧下さい。 © 2001, 2005 Interface Corporation. All rights reserved. 11 第一章 Linux のハードウェア制御 ライブラリ 弊社が提供しているライブラリではユーザアプリケーションからデバイスドライバにアクセス するためのシステムコールを実行しています。複雑なシステムコールの手続きを API 関数という 形にラップして、アプリケーションからの処理を簡便化します。 Linux のライブラリには、静的なライブラリと動的なライブラリ(共有ライブラリ)の 2 種類が 有ります。静的ライブラリは、コンパイル時にユーザアプリケーションに組み込みます。共有ラ イブラリは、ユーザアプリケーション実行時にライブラリを呼び出します。一般的に静的ライブ ラリの拡張子は「.a」、共有ライブラリの拡張子は「.so」となっています。 共有ライブラリは、アプリケーション実行時に使用するライブラリがそろっている必要がありま すが、メモリの使用量が節約できる、ライブラリがバージョンアップした場合でもユーザアプリ ケーションは再コンパイルの必要がない、などの利点があります。一方、静的ライブラリを使用 してアプリケーションを作成した場合、異なる環境(パソコン)でアプリケーションを実行する 場合でも、ライブラリの有無を気にする必要はありません。 弊社 Linux 製品では共有ライブラリを提供しています。 ユーザアプリケーション実行時に必要な共有ライブラリを知りたい場合は、 「ldd (実行ファイル)」コマンドで確認できます。 「ldd」コマンドの実行例: GPG-2000 のサンプルプログラム sample の実行時に必要なライブラリ #ldd sample libgpg2000.so => /usr/lib/libgpg2000.so (0x4001c000) libpthread.so.0 => /lib/libpthread.so.0 (0x40023000) libc.so.6 => /lib/libc.so.6 (0x40036000) /lib/ld-linux.so.2 => /lib/lc-linux.so.2 (0x40000000) ※カッコ内の数値はパソコンによって変わることがあります。 © 2001, 2005 Interface Corporation. All rights reserved. 12 第二章 Linux のプログラミング開発環境 第二章 Linux のプログラミング開発環境 基礎編: Linux のプログラミング開発環境 Linux のプログラミング開発環境は比較的容易に整えることができます。 プログラミング開発環境として必要なコンパイラ、ライブラリなどが、ディストリビューション に添付されている場合がほとんどだからです。ディストリビューションのインストール時に、開 発関連のパッケージ( 開発ツール カーネル開発 などと表示されていることが多いですが、 ディストリビューションによって異なります)を選択しておけば、ディストリビューションのイ ンストール終了と同時(正確には一度、再起動したあと)にプログラミング開発を行うことがで きます。 インストール時にカスタムでパッケージを選ぶ際は、前述の開発関連のツールの他に、グラフィ カルな環境を利用したい場合は GNOME または KDE などの X Window System を、またエディタ として Emacs もインストールしておくと便利がいいと思います。 プログラミング開発に必要な環境 コンパイラ ・コンパイラ(GCC) ライブラリ ・ライブラリ(libc など) デバッガ ・エディタ(Vi, Emacs, ほか) カーネル プログラミング開発に便利なもの ・デバッガ(gdb) エディタ ・X Window System など X Window System 各種アプリケーションソフトウェア 図 2-1 © 2001, 2005 Interface Corporation. All rights reserved. 13 ディストリビューションのイメージ 第二章 Linux のプログラミング開発環境 エディタ Linux にはプログラムを作成するために使うエディタとして Vi、Emacs、gEdit など様々あります。 ここでは、メジャーなエディタである Vi、Emacs(※Emacs を単なるエディタとして扱うことに 不満を感じる方もいらっしゃるかもしれませんが)について簡単にまとめました。 ■Vi UNIX 系で標準のエディタです。Vi を起動しても、すぐに文字を入力できません。Vi を起動する (端末から「vi」で起動できます。)と、コマンド待ちの状態になっており、入力できる状態にする には、入力状態(INSERT)にするためのコマンド「i」(「i」キーを押す)が必要だからです。 入力状態からコマンド状態に戻るためには「Esc」キーを押します。 Tips:改行コード「^M」を削除するには Windows で編集したテキストファイルを、Linux のエディタで開くと、「^M」という改行コード がついていることがあります(gEdit では「┌」と表示されます)。この改行コードは、見た目に よくないほか、場合によってはコンパイルが失敗する原因にもなります。削除するには次の方法 があります。 (1)端末からコマンドを使う場合 1 %dos2unix filename.c (2)端末からコマンド(perl)を使う場合 2 %perl -i.old -npe 's/¥r¥n/¥n/' filename.c (3)Vi の場合 対象となるファイルを Vi でオープンし、コマンド状態で以下のコマンドを入力します。 :%s/^M$// (コマンド状態では、最下位行に「:」(コロン)が表示されています。 ^M は^と M ではなく、コマンドコード(Ctrl+v と Enter)です) © 2001, 2005 Interface Corporation. All rights reserved. 14 第二章 Linux のプログラミング開発環境 表 2-1 Vi で知っておくと便利なコマンド(これらはコマンド状態の時に使用) コマンド i a o x dd yw yy (Y と同じ) p P u 1G G H 用途 文字を入力できる状態にする。カーソルの前に文字を入力※ 文字を入力できる状態にする。カーソルの後に文字を入力※ 文字を入力できる状態にする。行のはじめから文字を入力※ 文字の削除 文字の入力状態で「Back space」キーを押しても削除できます。 行の削除 単語のコピー 行のコピー カーソル位置の文字または行のあとにペースト カーソル位置の文字または行のまえにペースト 元に戻す 先頭行にジャンプ 最終行にジャンプ 表示されているページの先頭行にジャンプ b E 1 単語前にジャンプ 1 単語後にジャンプ 0 (ゼロ) $ /文字列 ?文字列 :w :w! 行の先頭にジャンプ 行の最後にジャンプ カーソル位置の下方に向かって、文字の検索 カーソル位置の上方に向かって、文字の検索 ファイルを上書き保存 「:w ファイル名」で任意のファイル名で保存。 強制的にファイルを上書き保存。 ZZ :q :q! ファイルを上書き保存して終了 Vi を終了 強制的に(変更を行ったあとでも保存せずに)Vi を終了。 「ESC」キーで、コマンド状態に戻ります。 © 2001, 2005 Interface Corporation. All rights reserved. 15 第二章 Linux のプログラミング開発環境 ■Emacs ディストリビューションによっては「XEmacs」が添付されている場合もあります。またディスト リビューションによっては、「カスタム」インストールではインストールするパッケージとして 選択されていない場合もあります。Emacs は Vi とは違い、起動したらすぐに文字の入力が可能で す。 表 2-2 Emacs で知っておくと便利なショートカット ショートカット C-w M-y C-y C-s 文字列 C-r 文字列 C-x C-s C-x C-c 用途 選択範囲の削除 選択範囲のコピー カーソル位置にペースト カーソル位置の下方に向かって、文字の検索 カーソル位置の上方に向かって、文字の検索 ファイルを上書き保存 Emacs を終了 ※表の表記について、「C」は「Ctrl」キーを、「M」は「Alt」キーを、「-」はキー を同時に押すことを示します。 ◎Emacs のデータ保存 Emacs でデータを保存(ファイルの上書き)すると、1つ前に保存したときの状態が「(元のファ イル名)〜」というファイル名に変更されて保存されます。また、編集をしてもデータ保存をせず に終了した場合、編集された内容が「#(元のファイル名)#」というファイル名で保存されます。 たとえばファイル名「Makefile」を編集して、データを保存したら「Makefile〜」というファイル が、データを保存せずに終了したら「#Makefile#」というファイルが自動作成されます。 図 2-2 Emacs の実行画面 © 2001, 2005 Interface Corporation. All rights reserved. 16 第二章 Linux のプログラミング開発環境 コンパイラ、コンパイルオプション ほとんどのディストリビュータが、コンパイラとして、GCC(GNU Compiler Collection)を添付 しています。 GCC でコンパイルするときのコマンドは「gcc」で、その基本的な実行形式は「gcc (ソースファ イル名) ‑o (実行ファイル名)」になります。「‑o」オプションで実行ファイル名を指定しない場 合は、実行ファイル名は「a.out」になります。 その他の主なコンパイルオプション ●コンパイル時に警告を出すようにする -Wall コンパイルエラーにはならないものの修正した方がいいコードを、警告として出力できます。 ●コンパイルの最適化を行う -02 (大文字の「オー」と数字の「2」) 最適化のオプションには「‑O1」、「‑O2」、「‑O3」などがありますが、O の後ろの数字が大きく なるほど、より最適化が行われます。「‑O2」オプションが行う程度の最適化がよいとされていま す。なお「‑O0」(大文字の「オー」と数字の「0」)オプションを追加した場合は最適化を行い ません。 ●ライブラリのリンクを行う ‑l(ライブラリ名) ライブラリをリンクする場合は「‑l」(小文字のエル)オプションのあとにリンクしたいライブ ラリ「lib***.so」のうち、「lib」とピリオド以下を削除した部分を指定することでリンクでき ます。たとえば、libgpg2000.so をリンクする場合、「‑lgpg2000」と記述してください。 ●インクルードファイルが存在するディレクトリを追加する「‑I(ディレクトリ名)」 ヘッダファイルとしてインクルードしたいファイルがあるディレクトリを明示的に指定するた めには、「‑I」(大文字のアイ)オプションを使用してください。GCC 2.95 では、「/usr/include」 ディレクトリをヘッダファイルの検索対象にしていないことがあります。この状態でコンパイル すると、「ヘッダファイルが見つからないという」コンパイルエラーが発生します。その場合、 オプションとして「‑I/usr/include」を追加します。 実行例:sample.c というソースファイルから実行ファイル sample を作成 %gcc sample.c -o sample -Wall -O2 -lgpg3300 -I/usr/include © 2001, 2005 Interface Corporation. All rights reserved. 17 第三章 ボードを制御するプログラムの作成 第三章 ボードを制御するプログラムの作成 基礎編 弊社ボード用 Linux 対応ソフトウェアからの制御 弊社ボード用 Linux 対応ソフトウェアが提供されている場合は、そのソフトウェアを使って対象 ボードを制御することが可能です。 基本的には XXOpen 関数(XX の部分はソフトウェア型式によって異なります)を用いて、ボードを利 用可能な状態にし、ライブラリ関数を用いて各ボードを制御します。ボードを使い終わったら XXClose 関数を実行して、ボードの利用を終了します。もし XXClose 関数を実行せずにアプリケ ーションを終了した場合でも、アプリケーション終了時に各ボードへのクローズ処理が自動的に 行われます。再度、ボードを利用する場合、XXOpen 関数を実行する必要があります。 関数体系は、デバイス番号などの一部の引数や、イベント処理など Linux と Windows との間で互 換性のないものを除き、原則として Windows 版の PCI ボード付属ソフトウェアと互換性を持たせ ており、Windows 版で制御されていた方にとっても取り組みやすいようにしています。 ●基本的な流れ (1)XXOpen 関数でボードをオープン(利用可能な状態に)する (2)ライブラリ関数を利用し、ボードを制御する (3)ボードを使い終わったら XXClose 関数でボードをクローズする © 2001, 2005 Interface Corporation. All rights reserved. 18 第三章 ボードを制御するプログラムの作成 汎用入出力ライブラリ BPL-0804 について Linux でボードを利用したくても、専用のデバイスドライバがない場合、ボードを制御すること はできません。このような時、汎用入出力ライブラリ BPL-0804 を使って、I/O ポートにアクセス することにより、ボードを制御することが可能になります。 制御方法は各ボードの I/O 公開資料を参考にしてください。BPL-0804、I/O 公開資料は、ともに 弊社 Web site ( www.interface.co.jp ) より入手できます。 ●BPL-0804 の機能 (1)I/O ポートへのリード、ライト (2)メモリ領域へのリード、ライト (3)割り込み処理の登録、解除、割り込み発生待ち (4)PCI ボード、CompactPCI ボードのリソース情報、コンフィグレーション空間の情報の取得、 コンフィグレーション空間への書き込み また BPL-0804 の各関数を実行する場合は、事前にデバイスノード作成プログラムでデバイスノ ードを作成するとともに、アプリケーション開始時に UioOpen 関数、終了時に UioClose 関数をそ れぞれ実行する必要があります。 デバイスノード作成プログラムを実行すると、BPL-0804 で同時に利用するプロセス数を尋ねられ ます。ここで入力した数のプロセス数だけ BPL-0804 をデバイスノードを作成し、このとき複数 のプロセスからその数だけ同時に利用することが可能です。このプロセス数の最大値は 255 です。 ●BPL-0804 を利用するための流れ (1) インストール:bpl0804.tgz ファイルの解凍、sh install の実行 readme の「使用方法」を参考にしてください。 (2)ドライバモジュール dpg0100.o,uio.o の組み込み ※割り込み処理を使いたい場合は、使用するボードに合わせて uioint.c をカスタマイズしてくだ さい。その後、割り込み処理用のモジュール uioint.o を作成し、組み込みます。(割り込み処 理の利用の仕方については後述) (3)デバイスノード作成プログラムの実行 ※BPL-0804 の関数を複数プロセスで同時に利用したい場合は、ここで利用したいプロセス数を 入力します(同時に複数プロセスで利用しない場合は 1)。 (4)アプリケーションの作成、実行。 ※UioOpen 関数を最初に実行し、UioClose 関数を最後に実行します。 © 2001, 2005 Interface Corporation. All rights reserved. 19 第三章 ボードを制御するプログラムの作成 PCI コンフィグレーションレジスタ情報の取得 ボードの I/O ポート領域やメモリ領域を直接制御する場合、ボードのリソース情報を取得する必 要があります。 このリソース取得用関数として、Linux 汎用入出力ライブラリ BPL-0804 では、UioGetConfigRegEx 関数があります。この関数によって全ての PCI コンフィグレーション空間の情報を取得すること ができます。UioGetConfigReg 関数とくらべ、全ての PCI コンフィグレーション空間の情報を取 得することができるだけでなく、第4引数にサブシステム ID を指定することにより、デバイス ID が同じでもボード型式が違う場合(たとえば PCI-2725 と PCI-2725A の関係。CompactPCI ボー ドもサブシステム ID が異なります)にボードを区別できます。 UioGetConfigRegEx 関数 long ven_id dev_id unsigned long ulIndex, unsigned short ven_id, unsigned short dev_id, unsigned short subven_id, unsigned short subsys_id, unsigned short *bus_info, PPCI_CONFIG pPciData ); ボードのインデックス番号(同一型式が複数枚ある時、2 枚目以降のボードを指 定できます。1 枚しかないときは、1 を指定します) ベンダ ID デバイス ID subven_id subsys_id *bus_info pPciData 戻り値 サブシステムベンダ ID サブシステム ID バス情報を取得する変数へのポインタ PCI コンフィグレーションレジスタの値を取得する構造体へのポインタ エラー識別子 ulIndex ベンダ ID、デバイス ID、サブシステムベンダ ID、サブシステム ID などの情報は各ボードの I/O 公開資料に記載されています。ちなみに弊社 PCI ボード、CompactPCI ボードのベンダ ID、サブ システムベンダ ID は、バスブリッジボード、Ethernet インタフェースボードなどを除き、原則と してそれぞれ 1147h です。 © 2001, 2005 Interface Corporation. All rights reserved. 20 第三章 ボードを制御するプログラムの作成 I/O 領域へのアクセス BPL-0804 で I/O 領域にアクセスするためには、予めその領域を予約し、処理が終了したあとは、 予約した領域を解放する必要があります。各領域を予約、解放、リード、ライトするための関数 について説明します。 (1)I/O 領域の予約:UioRequestRegion 関数 UioRequestRegion 関数 long pReg ulBaseAddr void** pReg, unsigend long ulBaseAddr, unsigned long ulSize ); I/O ポート領域クレーム用ポインタ格納用変数へのポインタ I/O ポート領域のベースアドレス ulSize 戻り値 クレーム範囲(バイト単位) エラー識別子 (2)I/O 領域からのデータ取得(read): UioInpXXX 関数(XXX には Byte, Word, Dword がそれ ぞれあてはまります。各関数の違いは第 2 引数の取得データサイズがそれぞれ byte, word, double word になっているだけです) UioInpByte 関数 long UioInpByte( unsigend long ulIoAddr, unsigned char *ucpData ); uIoAddr I/O アドレス ucpData 取得データ(バイト単位) 戻り値 エラー識別子 (3)I/O 領域への書き込み(write): UioOutpXXX 関数(XXX には Byte, Word, Dword がそれぞ れあてはまります。各関数の違いは第 2 引数の設定データサイズがそれぞれ byte, word, double word になっているだけです) UioOutpByte 関数 long UioOutpByte( unsigend long ulIoAddr, unsigned char ucData ); ulIoAddr I/O アドレス ucData 設定データ(バイト単位) 戻り値 エラー識別子 © 2001, 2005 Interface Corporation. All rights reserved. 21 第三章 ボードを制御するプログラムの作成 I/O 領域の解放: UioReleaseRegion 関数 UioReleaseRegion 関数 long UioReleaseRegion( void* pReg ); pReg I/O ポート領域クレーム用ポインタ 戻り値 エラー識別子 サンプルプログラム 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 BPL-0804 の I/O ポートにアクセスするプログラム:PCI-2726C で OUT8 〜OUT1 に 55h 出力し、IN16〜IN9 の状態を入力する。 #include “fbiuio.h” int main(void) { int ret; PCI̲CONFIG PciData; int bus; unsigned int nIoAdr; unsigned char Irq; long lTimeout = 5000; void *pReg; unsigned char ucData = 0; ret = UioOpen(); if (ret) return ‑1; UioGetConfigRegEx(1, 0x1147, 2726, 0x1147, 0x0001, &bus, &PciData); nIoAdr = PciData.BaseAddresses[0] & 0xFFFE; Irq = PciData.InterruptLine UioRequestRegion( &pReg, nIoAdr, 0x0F); /* I/O 領域の予約 */ ucData = 0x55; UioOutpByte(nIoAdr, ucData); /* OUT8〜OUT1 に 55h */ ucData = 0; /* 初期化 */ UioInpByte( nIoAdr + 0x01, &ucData); /* IN16〜IN9 の状態取得 */ printf(“IN16‑IN9 = %x¥n”, ucData); UioReleaseRegion(pReg); /* I/O 領域の解放 */ UioClose(); return 0; } © 2001, 2005 Interface Corporation. All rights reserved. 22 第三章 ボードを制御するプログラムの作成 解説: (1)UioOpen 関数を実行し、オープン処理を行います(14 行)。 (2)PCI-2726C のリソース情報を取得します。PCI-2726C は、ベンダ ID:1147h、デバイス ID:2726、 サブシステムベンダ ID:1147h、サブシステム ID:1h です。取得したリソース情報から I/O 空 間のベースアドレスを変数 nIoAdr に、割り込み番号を変数 Irq にそれぞれ代入しています (17-19 行)。 (3)PCI-2726C の I/O 領域を他のデバイスが使用できないように予約します(21 行)。 (4)PCI-2726C の接点 OUT8-OUT1 に 55h を出力します(23-24 行)。 PCI-2726C の I/O ポートについては「PCI-2726C I/O 公開資料」にてご確認ください。 (5)PCI-2726C の接点 IN16-IN9 の状態を取得し、端末に表示します(26-28 行)。 (6)予約していた PCI-2726C の I/O 領域を解放します(30 行)。 (7)クローズ処理を行います(32 行)。 © 2001, 2005 Interface Corporation. All rights reserved. 23 第三章 ボードを制御するプログラムの作成 メモリ領域へのアクセス メモリ領域にアクセスする場合も同様に、予めその領域を予約し、処理が終了したあとは、予約 した領域を解放する必要があります。各領域を予約、解放、リード、ライトするための関数につ いて説明します。 (1)メモリ領域の予約: UioMapMemory 関数 UioMapMemory 関数 long pMem ulBaseMem void** pMem, unsigned long ulBaseMem, unsigned long ulMemSize ); 物理メモリアクセス用ポインタ格納用変数へのポインタ 物理メモリの先頭アドレス ulMemSize 戻り値 メモリサイズ エラー識別子 (2)メモリ領域からのデータの取得(read): UioPeekXXX 関数(XXX には Byte, Word, Dword がそ れぞれあてはまります。各関数の違いは第 3 引数の取得データサイズがそれぞれ byte, word, double word になっているだけです) UioPeekByte 関数 long pMem ulOffset void* pMem, unsigned long ulOffset, unsigned char *ucpData ); 物理メモリアクセス用ポインタ オフセットアドレス ucpData 戻り値 取得データ(バイト単位) エラー識別子 (3)メモリ領域への書き込み(write):UioPokeXXX 関数(XXX には Byte, Word, Dword がそれ ぞれあてはまるあてはまります。各関数の違いは第 3 引数の設定データサイズがそれぞれ byte, word, double word になっているだけです) UioPokeByte 関数 long pMem ulOffset void* pMem, unsigned long ulOffset, unsigned char ucData ); 物理メモリアクセス用ポインタ オフセットアドレス ucData 戻り値 設定データ(バイト単位) エラー識別子 © 2001, 2005 Interface Corporation. All rights reserved. 24 第三章 ボードを制御するプログラムの作成 (4)メモリ領域の解放:メモリ領域の解放は UioUnMapMemory 関数を使います。 UioUnMapMemory 関数 long UioUnMapMemory( void* pMem ); pMem 物理メモリアクセス用ポインタ 戻り値 エラー識別子 サンプルプログラム BPL-0804 のメモリ領域にアクセスするプログラム:PCI-4914 のメモリ 領域にデータの書き込み、読み込みを行う #include “fbiuio.h” 1 2 int main(void) 3 { 4 int ret; 5 unsigned short bus; 6 PCI̲CONFIG PciData; 7 unsigned int nIoAdr; 8 unsigned long ulMemAdr; 9 unsigned char Irq; 10 long lTimeout = 5000; 11 void *pReg; 12 void *pMem; 13 unsigned char ucData = 0; 14 15 ret = UioOpen(); 16 if (ret) return ‑1; 17 18 UioGetConfigRegEx(1, 0x1147, 4914, 0x1147, 0x0001, &bus, &PciData); 19 nIoAdr = PciData.BaseAddresses[0] & 0xFFFC; 20 ulMemAdr = PciData.BaseAddresses[1] & 0xFFFFFFF0; 21 Irq = PciData.InterruptLine 22 23 UioRequestRegion( &pReg, nIoAdr, 0x0F); /* I/O 領域の予約 */ 24 UioMapMemory( &pMem, ulMemAdr, 0x40000); /* メモリ領域の予約 */ 25 26 ucData = 0x80; 27 UioOutpByte(nIoAdr, ucData); /* メモリ領域へのアクセスを有効にする */ 28 29 ucData = 0x55; /* 初期化 */ 30 /*メモリオフセット 0100h に 55h を出力 */ 31 UioPokeByte( pMem, 0x0100, ucData); 32 33 ucData = 0x00; /* 初期化 */ 34 /* メモリオフセット 0200h の状態取得 */ 35 UioPeekByte( pMem, 0x0200, &ucData); 36 printf(“MemoryAdr+0200h = %x¥n”, ucData); 37 38 UioReleaseRegion(pReg); /* I/O 領域の解放 */ 39 UioUnMapMemory (pMem); /* メモリ領域の解放 */ 40 UioClose(); 41 42 © 2001, 2005 Interface Corporation. All rights reserved. 25 第三章 ボードを制御するプログラムの作成 43 44 return 0; } 解説: (1)UioOpen 関数を実行し、オープン処理を行います(16 行)。 (2)PCI-4914 のリソース情報を取得します。PCI-4914 は、ベンダ ID:1147h、デバイス ID:4914、 サブシステムベンダ ID:1147h、サブシステムデバイス ID:1h です。取得したリソース情報 から I/O 領域のベースアドレスを変数 nIoAdr に、メモリ領域のベースアドレスを変数 ulMemAdr に、割り込み番号を変数 Irq にそれぞれ代入しています(19-22 行)。 (3)PCI-4914 の I/O 領域、メモリ領域を他のデバイスが使用できないように予約します(24-25 行)。 (4)PCI-4914 のメモリ領域にアクセスができるようにします(27-28 行)。PCI-4914 の I/O ポー トについては「PCI-4914 I/O 公開資料」にてご確認ください。 (5)PCI-4914 のメモリ領域のオフセット 0100h に 55h を出力します(30-32 行)。 (6)PCI-4914 のメモリ領域のオフセット 0200h の状態を取得し、表示します(34-37 行)。 (7)予約していた PCI-4914 の I/O 領域、メモリ領域を解放し、クローズ処理を行います(39-41 行)。 応用編 割り込み処理 割り込み処理を行いたい場合、BPL-0804 では、uioint.c に制御するボードに対応したプログラム コード(割り込みフラグの読み出し,クリア等)を追加してコンパイルし、割り込み処理用ドラ イバモジュール uioint.o を作成することで実現できます。 PCI ボード、CompactPCI ボードでは、割り込みが発生すると割り込みステータスレジスタに割り 込みフラグがセットされます。割り込みルーチンに、この割り込みフラグのクリアを含め、実行 したい処理を記述します。各ボードまたは割り込み要因によってフラグを処理するタイミングは 異なりますので、具体的な割り込み処理の手順は各ボードの I/O 公開資料で確認してください。 この割り込みルーチンを uioint.c の uioint̲interrupt 関数の中に記述します。 © 2001, 2005 Interface Corporation. All rights reserved. 26 第三章 ボードを制御するプログラムの作成 サンプルプログラム 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 uioint.c の割り込みルーチンのコードの変更例:DO ボードにおいて割り 込み発生時に OUT1 を 1 にする。gulData では DO ボードのベースアド レスが渡されているものとする) ※このプログラムでは割り込みの共有について考慮されていません。 /* ******************************** */ /* Interrupt Routine */ /* ******************************** */ static void uioint̲interrupt(int irq, void *dev̲id, struct pt̲regs *regs) { int i, ret; /* ***** Change Code ***** */ ret = inb(gulData+0x0c); /* if(!(ret & 0x20)){ PDEBUG1; return; }*/ 割り込み要因の取得 当ボードで必要な処理) 割り込みフラグの解除 該当ボードで必要な処理) outb(ret,gulData + 0x0c); outb(0x01,gulData); /* ********************** */ OUT1 に 1 を出力(任意の処理) for(i=0;i<INTFILE;i++){ /* ***** Wake Up ***** */ if(uiotable[i].waiting){ wake̲up̲interruptible(&(uiotable[i].wait)); uiotable[i].waiting = 2; } } /* ***** Change Code ***** */ PDEBUG2; /* ********************** */ /* ***** IRQ level ***** */ Int̲Irq = irq; } © 2001, 2005 Interface Corporation. All rights reserved. 27 第三章 ボードを制御するプログラムの作成 uioint.c の元ファイルとサンプルプログラムとの違い %diff uioint.c.bak uioint.c 70,71c70,71 < ret = inb(gulData); < if(!(ret & 0x20)){ --> ret = inb(gulData+0x0c); > /* if(!(ret & 0x20)){ 74c74,77 < } --> }*/ > > outb(ret,gulData + 0x0c); > outb(0x01,gulData); ※図中で元ファイルは uioint.c.bak、編集後のファイルは uioint.c となっています uioint̲interrupt に必要な割り込みルーチンを記述したら、uioint.c をコンパイルします。その 結果、ドライバモジュール uioint.o が作成されます。この uioint.o を「insmod」コマンドによっ て組み込むと、BPL-0804 の割り込み処理の各関数(UioRequestIsr、UioReleaseIsr、UioWaitEvent) がユーザアプリケーションから使用できるようになります。 ※uioint.o 用のデバイスノードを作成する必要があるため、デバイスノード作成プログラムは uio.o と uioint.o をどちらも組み込んだ状態で実行してください。 ●ユーザアプリケーションからの割り込み処理の使い方 (1)UioRequestIsr 関数で指定した IRQ に対する割り込み処理を登録します。この関数では、32 ビットの任意のユーザデータを設定でき、そのユーザデータは、uioint.c の変数 gulData になります。サンプルプログラムにもあるように PCI ボード、CompactPCI ボードのベース アドレスなどを指定して、そのベースアドレスを使って何かの処理をする、という使い方が できます。 UioRequestIsr 関数 long UioRequestIsr( unsigned char Irq, unsigned long ulUser ); Irq 割り込み番号(IRQ) ulUser ドライバに渡すユーザデータ 戻り値 エラー識別子 (2)UioWaitEvent 関数で指定した IRQ からの割り込み発生を待ちます。割り込みが発生した時 点で、UioWaitEvent 関数から処理が戻ってきます。非同期に割り込みの発生を待ちたい場 合、スレッドの中で UioWaitEvent 関数を実行します。 UioWaitEvent 関数 long UioWaitEvent ( long lTimeout, unsigned char *Irq ); lTimeout 割り込み待ち時間 Irq 割り込みが発生した IRQ 番号 戻り値 エラー識別子 © 2001, 2005 Interface Corporation. All rights reserved. 28 第三章 ボードを制御するプログラムの作成 (3)割り込み処理が必要なくなったら UioReleaseIsr 関数で割り込み処理の登録を削除します。 UioReleaseIsr 関数 long UioReleaseIsr( unsigned char Irq ); Irq 割り込み番号(IRQ) 戻り値 エラー識別子 弊社 PCI ボード、CompactPCI ボードでは、電源投入時の初期化状態では、割り込みがマスクされ ている(無効になっている)ことがあり、その場合、実際の処理では使用する割り込みのマスク を UioOutpByte 関数などを使って、事前に解除しておく処理が必要になります。詳細は各ボード の I/O 公開資料をご覧ください。 サンプルプログラム BPL-0804 の割り込み関数を使ったプログラム:PCI-2726C で割り込 み発生を待つプログラム #include “fbiuio.h” #include <error.h> 1 2 3 int main(void) 4 { 5 int ret; 6 unsigned short bus; 7 PCI̲CONFIG PciData; 8 unsigned int nIoAdr; 9 unsigned char Irq; 10 long lTimeout = 5000; 11 void *pReg; 12 char *pErr; 13 14 ret = UioOpen(); 15 if (ret) return ‑1; 16 17 UioGetConfigRegEx(1, 0x1147, 2726, 0x1147, 0x0001, &bus, &PciData); 18 nIoAdr = PciData.BaseAddresses[0] & 0xFFFC; 19 Irq = PciData.InterruptLine; 20 21 UioRequestRegion( &pReg, nIoAdr, 0x0F); /* I/O 領域の予約 */ 22 UioOutpByte(nIoAdr + 0x0D, 0x02); /* bit1(IN2)の割り込みマスクの解除 */ 23 24 ret = UioRequestIsr( Irq, nIoAdr); /* 割り込み処理の登録 */ 25 if (!ret) perror(pErr); 26 27 ret = UioWaitEvent(lTimeout,&Irq); /* 割り込み待ち */ 28 if (!ret) { 29 printf("Interrupt OK(IRQ:%d)¥n",Irq); 30 }else{ 31 printf("Interrupt NG(%d)¥n",ret); 32 perror(pErr); 33 } 34 35 © 2001, 2005 Interface Corporation. All rights reserved. 29 第三章 ボードを制御するプログラムの作成 UioOutpByte(nIoAdr + 0x0D, 0x00); /* 全ての割り込みをマスク */ ret = UioReleaseIsr(Irq); /* 割り込み処理の解除 */ UioReleaseRegion(pReg); /* I/O 領域の解放 */ 36 37 38 39 40 41 42 UioClose(); return 0; } 解説: (1)UioOpen 関数を実行し、オープン処理を行います(15 行)。 (2)PCI-2726C のリソース情報を取得し、PCI-2726C の I/O 領域を他のデバイスが使用できない ように予約します(18-22 行)。 (3)PCI-2726C の接点 IN2 の割り込みマスクを解除します(23 行)。 PCI-2726C の I/O ポートについては「PCI-2726C I/O 公開資料」にてご確認ください (4)割り込み処理を登録します。第 1 引数で割り込み番号(IRQ)を指定し、第 2 引数で PCI-2726C の I/O 領域のベースアドレスを渡しています。これ以後、割り込みが発生すると、uioint.c の uioint_interrupt 関数が呼び出されるようになります(25 行)。 (5)割り込みの発生を待ちます。指定した時間(lTimeout)以上経過しても指定した割り込み番 号(Irq)の割り込みが発生しない場合はエラーが返ります(28-34 行)。 (6)PCI-2726C の全ての割り込みをマスクします(36 行)。 (7)割り込み処理の登録を解除します(37 行)。 (8)予約していた PCI-2726C の I/O 領域を解放し、クローズ処理を行います(38-40 行)。 © 2001, 2005 Interface Corporation. All rights reserved. 30 第三章 ボードを制御するプログラムの作成 PCI コンフィグレーションレジスタへの書き込み 弊社 PCI-ISA、PCI-C(98)などのバスブリッジに使用される PCI-8571 では、拡張ユニットの ISA バ ス、C バスに実装されるボードの I/O ポート領域、メモリ領域を PCI コンフィグレーション空間 の特定のレジスタに設定する必要があります。このようにボードのコンフィグレーションレジス タに書き込みをしたい場合には、Linux 汎用入出力ライブラリ BPL-0804 の UioSetConfigReg 関数 を使用します。 ※PCI-PCI バスブリッジの場合は、拡張ユニットに実装したボードをパソコンに PCI ボードを直接 実装した場合と同様に、特に意識することなく制御することができます。 UioSetConfigReg 関数 long unsigned long ulIndex, unsigned short ven_id, unsigned short dev_id, unsigned short subven_id, unsigned short subsys_id, unsigned char offset, unsigned char write_data_size, unsigned long write_data); ulIndex ボードのインデックス番号 ven_id ベンダ ID dev_id デバイス ID subven_id サブシステムベンダ ID subsys_id サブシステム ID offset コンフィグレーションレジスタのオフセット write_data_size 書き込みを行うデータサイズ (UIO_DATA_BYTE:byte, UIO_DATA_WORD:word, UIO_DATA_DWORD:double word) write_data 書き込みを行うデータ 戻り値 エラー識別子 © 2001, 2005 Interface Corporation. All rights reserved. 31 第三章 ボードを制御するプログラムの作成 ●PCI-8571 を使ったバスブリッジの設定方法 (1)使用する I/O ポート領域、メモリ領域の先頭アドレスと終了アドレスをそれぞれ設定します。 (PCI コンフィグレーションレジスタ:40h〜4Bh) (2)指定した領域を有効にします。(PCI コンフィグレーションレジスタ:4Ch〜4Dh) (3)レガシーバスのリセット信号を無効にし、レガシーバスのウェイト数を設定します。(PCI コンフィグレーションレジスタ:4Eh) サンプルプログラム 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 PCI-8571 を使ったバスブリッジで I/O ポート 0280h〜029Fh を使用し たい場合 “fbiuio.h” unsigned long num = 1; unsigned char lowadd = 0x28; /* 0280h */ unsigned char highadd = 0x29; /* 029Fh */ /* 指定したい I/O ポート領域の先頭アドレスの設定※5 */ UioSetConfigReg(num, 0x1147, 8571, 0x1147, 1, 0x40, UIO̲DATA̲BYTE, lowadd); /* 指定したい I/O ポート領域の終了アドレスの設定※6 */ UioSetConfigReg(num, 0x1147, 8571, 0x1147, 1, 0x41, UIO̲DATA̲BYTE, highadd); /* 指定した I/O ポート領域を有効にする */ UioSetConfigReg(num, 0x1147, 8571, 0x1147, 1, 0x4C, UIO̲DATA̲BYTE, 0x11); /* バススロットへのリセット信号を無効にします※7 */ UioSetConfigReg(num, 0x1147, 8571, 0x1147, 1, 0x4E, UIO̲DATA̲BYTE, 0x04); ※ 設定する I/O ポート領域、メモリ領域は他のデバイスと競合しないようにしてください。も し重なった場合、デバイスを破壊する可能性があります。 ※ 各コンフィグレーションレジスタの意味、設定方法は、「PCI-8571 I/O 公開資料」にてご確 認ください。PCI-8571 の I/O 公開資料は、弊社 Web site より「PCI-98C00」もしくは「PCI-ISA00」 という型式で検索,ダウンロードしてください。 ※5 ※6 ※7 設定値はアドレスのビット 9〜ビット 4。ビット 3〜ビット 0 は 0000b になります。 設定値はアドレスのビット 9〜ビット 4。ビット 3〜ビット 0 は 1111b になります。 ビット 7 がリセット信号の有効・無効を制御し、出荷時設定では、ビット 7 は 1、リセット信 号が有効でバスへのアクセスができない状態です。これを 0 に変更し、リセット信号を無効 にします。ビット 3〜ビット 0 はバスのウェイト数を設定します。 © 2001, 2005 Interface Corporation. All rights reserved. 32 第四章 GTK+用 GUI アプリケーションの作成 第四章 GTK+を使った GUI アプリケーションの作成 基礎編 Linux 上で GUI(Graphical User Interface)アプリケーションを作成したい場合には GTK+(Gimp Tool Kit+)が有効です。GTK+は 特に X Window System 向けに設計された GUI アプリケーション作成 用のツールキットです。この章では、GTK+を使ったアプリケーションのプログラミングについ て説明します。 ソースコードの雛形 GTK+上における GUI アプリケーションのプログラミングは端的にいうと、以下の 2 点に集約さ れます。 (1)画面を作ること。 (2)任意のシグナル※8 の設定とそのシグナルが発生した時に呼び出されるコールバック関数を 作ること。 たとえばボタンがク リック(シグナル発 生)されたら コールバック関数を呼び出し、 次の処理を実行 (1)画面を作る 図 4-1 ※8 (2)シグナルとコールバック関数の設定 プログラミング内容のイメージ※9 ここでいうシグナルとは、ボタンをクリックする、テキストエントリに文字を入力するなどの イベントが発生したことを通知することです。以下同じ意味で使っています。 ※9 画面は DA ボード用 Linux 対応ソフトウェア GPG-3300 の波形出力ユーティリティソフトウェア © 2001, 2005 Interface Corporation. All rights reserved. 33 第四章 GTK+用 GUI アプリケーションの作成 ●基本的な流れは次の通りです。 (1)初期化する(gtk̲init 関数) (2)表示する画面を作成する (3)シグナルの指定とシグナル発生時に呼び出されるコールバック関数を登録する (gtk̲signal̲connect 関数) (4)画面に表示する(gtk̲widget̲show 関数) (5)GTK+に処理を移し、メインループに入る(gtk̲main 関数) (6)シグナル発生→コールバック関数の呼び出し (7)コールバック関数内でメインループの終了処理(gtk̲main̲quit 関数※10) (8)終了 サンプルプログラム 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 GTK+用 GUI アプリケーションの雛形 #include <gtk/gtk.h> GtkWidget *window1; GtkWidget *label1; /* シグナル発生時に呼び出されるコールバック関数(基本的な流れ(6)) */ gboolean on̲window1̲delete̲event(GtkWidget *widget, GdkEvent event, gpointer user̲data) /* コールバック関数 */ { gtk̲main̲quit(); /* メインループの終了処理 (基本的な流れ(7)) */ return TRUE; } int main(int argc, char *argv[]) { gtk̲init(&argc, &argv); /* GTK+の初期化 (基本的な流れ(1)) */ /* ******表示する画面の作成 (基本的な流れ(2))****** */ window1 = gtk̲window̲new(GTK̲WINDOW̲TOPLEVEL); /* ウィンドウの作成 */ /* 「×」を押されたときに呼び出される関数の登録 (基本的な流れ(3)) */ gtk̲signal̲connect(GTK̲OBJECT(window1), "delete̲event", GTK̲SIGNAL̲FUNC(on̲window1̲delete̲event), NULL); label1 = gtk̲label̲new("Hello"); /* “Hello”と表示するラベルの作成 */ /* ラベルをウィンドウにのせる */ gtk̲container̲add(GTK̲CONTAINER(window1), label1); gtk̲widget̲show(label1); /* ラベルを画面に表示(基本的な流れ(4)) */ /* ******表示する画面の作成部分の終了****** */ ※10 gtk_main_quit 関数がプログラムを終了させるのではなく、gtk_main_quit 関数を実行すると gtk_main 関数の次の処理に進みます。多くは、main 関数で gtk_main 関数が実行されたあとに 他の処理を行うことはないため、プログラムが終了することになります。 © 2001, 2005 Interface Corporation. All rights reserved. 34 第四章 GTK+用 GUI アプリケーションの作成 33 34 35 36 37 38 39 40 gtk̲widget̲show(window1); /* ウィンドウを画面に表示(基本的な流れ(4)) */ gtk̲main(); /* GTK+に処理を移し、メインループに入る(基本的な流れ(5)) */ /* シグナル発生待ち */ return 0; /* 終了 (基本的な流れ(8)) */ } 解説: このサンプルプログラムは、実行するとフォームの中央に「Hello」と書かれたウィンドウを表示 します(17〜33 行目)。 そして、ウィンドウ右上にある「×」マークを押すと、on_window1_delete_event 関数(7 行目) が呼び出され、メインループを終了させる関数 gtk_main_quit 関数を実行し(11 行目)、プログ ラムが終了します。 この「×」マークを押すと、ウィンドウ が閉じ、プログラムが終了する。 図 4-2 実行画面 ■コンパイル GTK+のアプリケーションのコンパイルに必要なライブラリ、インクルードファイルを指定する コンパイルオプションは、「gtk‑config」コマンドで確認できます。 実行例:リンクするライブラリを確認したいとき %gtk-config –libs -L/usr/lib -L/usr/X11R6/lib -lgtk -lgdk -rdynamic -lgmodule -lglib –ldl -lXi –lXext -lX11 -lm 実行例:リンクするインクルードファイルのディレクトリを確認したいとき %gtk-config –cflags -I/usr/glib/include -I/usr/X11R6/include ただしこれらのオプションをコンパイルするときに忘れずにつけるのは面倒です。そこで次のよ うに実行します。 実行例:プログラム xsample.c を実行ファイル xsample にコンパイルする場合 %gcc xsample.c -o xsample `gtk-config --libs` `gtk-config --cflags` ※「`」(バッククォート)は、キーボードが日本語 106 キーの場合、「Shift」キーを押しながら 「@」キーを押すと入力できます。 © 2001, 2005 Interface Corporation. All rights reserved. 35 第四章 GTK+用 GUI アプリケーションの作成 GTK+の主な関数 (1)ウィンドウを作成する 画面作成の時にベースとなるウィンドウは、gtk̲window̲new 関数を使って作成します。 gtk_window_new 関数 GtkWidget* gtk_window_new(GtkWindowType type); type ウィンドウのタイプ GTK_WINDOW_TOPLEVEL、GTK_WINDOW_DIALOG、 GTK_WINDOW_POPUP の 3 種から選択。通常は GTK_WINDOW_TOPLEVEL。 戻り値 ウィンドウのハンドラ (2)主なウィジェット ●ラベル gtk_label_new 関数 GtkWidget* gtk_label_new(const gchar *str); str ラベルに表示したい文字列へのポインタ 戻り値 ラベルのハンドラ ●ボタン gtk_button_new 関数 GtkWidget* gtk_button_new (void); 戻り値 ボタンのハンドラ ボタンを押したときに発生する”clicked”というシグナルを使って、コールバック関数を呼び出す ことができます。 ●トグルボタン 「押された状態」、「押されていない状態」を維持できるボタンです。 gtk_toggle_button_new 関数 GtkWidget* gtk_toggle_button_new (void); 戻り値 トグルボタンのハンドラ このほかのボタンとして、チェックボタン、ラジオボタンがあります。チェックボタンはトグル ボタンと使い方は同じですが、表示が「ボタンが押された・押されていない」から「チェックあ り・なし」に変わったものです。ラジオボタンは複数のチェックボタンをグループ化して、その 中の一つのボタンだけがチェックされた状態になるような処理を行います。 © 2001, 2005 Interface Corporation. All rights reserved. 36 第四章 GTK+用 GUI アプリケーションの作成 トグルボタン、チェックボタン、ラジオボタンでは、シグナルに シグナル toggled toggled を利用します。この は、ボタンの「押された(チェックされた)」「押されていない(チェック されていない)」の状態が変化したときに発生し、コールバック関数内でボタンの「押された(チ ェックされた)」「押されていない(チェックされていない)」の状態を if 文で判定することが できます。 ボタン系のウィジェットで関数名に「̲with̲label」がつくと、ボタンの上にラベルを表示する ことができます。これはトグルボタン、チェックボタン、ラジオボタンでも同様です。 gtk_button_new_with_label 関数 GtkWidget* gtk_button_new_with_label (const gchar *label); label ボタンの上に表示したい文字列へのポインタ 戻り値 ボタンのハンドラ ●テキストエントリ 文字列を入力するエントリを作成します。 gtk_entry_new 関数 GtkWidget* gtk_entry_new(void); 戻り値 テキストエントリのハンドラ テキストエントリに入力された文字列の取得 gtk_entry_get_text 関数 gchar* gtk_entry_get_text(GtkEntry *entry); entry テキストエントリのハンドラ 戻り値 文字列へのポインタ テキストエントリに文字列を設定する gtk_entry_set_text 関数 void gtk_entry_set_text(GtkEntry *entry, const gchar *text); entry テキストエントリのハンドラ text 設定したい文字列へのポインタ (3)ウィンドウにウィジェットを追加する ウィンドウ上にウィジェットをのせるときは gtk̲container̲add 関数を使います。 gtk_container_add 関数 void gtk_container_add(GtkContainer *container, GtkWidget *widget); container ウィンドウ名。 GtkContainer は GTK_CONTAINER でキャストする場合が多い。 widget ウィンドウに載せたいウィジェット名 © 2001, 2005 Interface Corporation. All rights reserved. 37 第四章 GTK+用 GUI アプリケーションの作成 (4)ウィジェットを表示する gtk_widget_show 関数 void gtk_widget_show(GtkWidget *widget); widget ウィジェット名。 (5)シグナルの登録 シグナルの登録には、gtk_signal_connect 関数を使用します。 gtk_signal_connect 関数 guint gtk_signal_connect( object name func func_data 戻り値 GtkObject *object, const gchar *name, GtkSignalFunc func, gpointer func_data); シグナルが発生するウィジェットの指定。 GTK_OBJECT でキャストする。 シグナル名 コールバック関数名。GTK_SIGNAL_FUNC でキャストする。 コールバック関数の引数にわたるデータ 将来参照用の識別子 ※コールバック関数のプロトタイプはシグナルによって異なります。 © 2001, 2005 Interface Corporation. All rights reserved. 38 第四章 GTK+用 GUI アプリケーションの作成 応用編 周期実行 gtk̲timeout̲add 関数を利用することにより、一定時間ごとに指定した関数を呼び出すことが可 能です。 gtk_timeout_add 関数 guint gtk_timeout_add(guint32 interval, GtkFunction function, gpointer data); interval 更新間隔(ms) function 呼び出す関数名 data 呼び出す関数に渡すデータへのポインタ 戻り値 周期実行する関数のハンドラ 更新間隔はミリ秒単位で指定できますが、呼び出す関数の実行処理が周期時間内に終了しない場 合、アプリケーションがフリーズしてしまうようにみられます。 また実時間性についても、あまり正確とはいえないようです。 gtk̲timeout̲add 関数は、戻り値に周期実行する関数のハンドラを返します。周期実行を終了し たい場合は、このハンドラを第1引数として gtk̲timeout̲remove 関数を実行します。 gtk_timeout_remove 関数 void gtk_timeout_remove(guint timeout_handler_id); timeout_ gtk_timeout_add 関数で取得した周期実行している関数のハンドラ handler_id 使用例: メモリンク用 Linux ソフトウェア GPG-4910 添付のユーティリティ xmledit の callbacks.c では、メ モリ領域の状態を更新するために gtk_timeout_add 関数を使用しています。 図 4-3 メモリエディタユーティリティ この部分を更新 © 2001, 2005 Interface Corporation. All rights reserved. 39 第四章 GTK+用 GUI アプリケーションの作成 サンプルプログラム メモリンク用 Linux ソフトウェア GPG-4910 添付のユーティリティ xmlutil の callbacks.c メニューバーの「close」をクリック 38 39 int g̲interval = 5; gint g̲timeout̲handle; 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 void on̲device̲close1̲activate (GtkMenuItem *menuitem, gpointer user̲data) { GtkWidget *entry; 272 273 309 506 507 558 559 560 561 562 563 564 すると呼び出される関数 周期実行の終了 if (nOpenflag){ gtk̲timeout̲remove(g̲timeout̲handle); entry=get̲widget(GTK̲WIDGET(window1), "entry4"); gtk̲widget̲set̲sensitive (entry, FALSE); ret = MlClose(nDevice); if(ret)perror(pErr); nOpenflag = 0; } return; } void On̲Memorydump(void) { (中略) } void OpenInit(void) { (中略) 周期的に呼び出される関数 メモリンクボードの open 時に呼び出される関数 周期実行の登録 5×1000ms ごとに On_Memorydump 関数 を実行する。 On̲Memorydump(); g̲timeout̲handle = gtk̲timeout̲add(g̲interval *1000, (GtkFunction)On̲Memorydump,NULL); return; } 解説:メモリンクボードの open 時(MlOpen 関数の実行)に、メモリ領域の状態(ダンプ結果) の更新を行う関数 On_Memorydump の周期実行(更新間隔 5000ms)を開始し、ボード close 時に 周期実行を終了しています。 © 2001, 2005 Interface Corporation. All rights reserved. 40 第四章 GTK+用 GUI アプリケーションの作成 GTK+を使ったデジタル入力ボード用サンプルプログラム GTK+を使っての PCI ボード、CompactPCI ボードの制御の例として、実行するとラベルとボタン が存在するウィンドウが表示され、ボタンをクリックすることにデジタル入力ボードの IN1-IN8 の状態を取得し、ラベルに表示するプログラムを紹介します。 ボタンを押すと、IN1 から IN8 デジタル 入力状態がラベルに表示される 図 4-4 サンプルプログラム 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 実行画面のイメージ DI ボードにおいて、ボタンをクリックしたときに IN1-IN8 の状態を 取得するプログラム #include <gtk/gtk.h> #include "fbidio.h" GtkWidget *window1; GtkWidget *label1; GtkWidget *button1; int nNum = 1; /* シグナル発生時に呼び出されるコールバック関数 */ gboolean on̲window1̲delete̲event(GtkWidget *widget, GdkEvent event, gpointer user̲data) /* コールバック関数 */ { DioClose(nNum); gtk̲main̲quit(); /* メインループの終了処理 */ return TRUE; } void /* ボタンがクリックされたときに呼び出される関数 */ on̲button1̲clicked (GtkButton *button, gpointer user̲data) { unsigned char cValue; char str[20]; int ret; ret = DioInputByte( nNum, FBIDIO̲IN1̲8, &cValue); if(ret){ printf("error:%lxh¥n",ret); return; } sprintf(str,"IN1‑IN8:%xh",cValue); gtk̲label̲set(GTK̲LABEL(label1),str); /* ラベルに表示 */ return; } int main(int argc, char © 2001, 2005 Interface Corporation. All rights reserved. 41 第四章 GTK+用 GUI アプリケーションの作成 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 GtkWidget *vbox1; int ret; gtk̲init(&argc, &argv); /* GTK+の初期化 */ /* ****** 表示する画面の作成 ****** */ window1 = gtk̲window̲new(GTK̲WINDOW̲TOPLEVEL); /* ウィンドウの作成 */ /* 「×」を押されたときに呼び出される関数の登録 */ gtk̲signal̲connect(GTK̲OBJECT(window1), "delete̲event", GTK̲SIGNAL̲FUNC(on̲window1̲delete̲event), NULL); vbox1 = gtk̲vbox̲new(FALSE, 0); /* 垂直ボックスの設定 */ gtk̲container̲add(GTK̲CONTAINER (window1), vbox1 ); gtk̲widget̲show(vbox1); /* IN1‑IN8 の状態を表示するラベルの作成 */ label1 = gtk̲label̲new("IN1‑IN8: 0h"); / * label1 を vbox1 にのせる */ gtk̲box̲pack̲start(GTK̲BOX(vbox1), label1,FALSE,FALSE,0); gtk̲widget̲show(label1); /* ラベルを画面に表示*/ button1 = gtk̲button̲new̲with̲label("PUSH"); /* button の作成 */ /* button1 を vbox1 にのせる */ gtk̲box̲pack̲start(GTK̲BOX(vbox1), button1,FALSE,FALSE,0); gtk̲widget̲show(button1); /* ボタンを画面に表示*/ /* コールバック関数の登録 */ gtk̲signal̲connect(GTK̲OBJECT(button1), "clicked", GTK̲SIGNAL̲FUNC(on̲button1̲clicked), NULL); /* ******表示する画面の作成部分の終了****** */ gtk̲widget̲show(window1); /* ウィンドウを画面に表示*/ ret = DioOpen(nNum, 0); if(ret){ printf("error=%lxh¥n",ret); return ‑1; } gtk̲main(); /* GTK+に処理を移し、メインループに入る*/ return 0; } © 2001, 2005 Interface Corporation. All rights reserved. 42 第四章 GTK+用 GUI アプリケーションの作成 解説: on_window1_delete_event 関数(9-15 行): メインウィンドウの「×」ボタンが押されたときに呼び出される関数です。 (1)DIO ボードをクローズする関数 DioClose を実行しています。 (2) gtk_main_quit 関数を実行し、GTK+のメインループを終了処理をしています。 on_button1_clicked 関数(17-33 行): ボタン button1 がクリックされたときに呼び出される関数です。 (1)DioInputByte 関数は DIO ボードの接点状態を 8 ビット単位で取得する関数です。ここで は IN1-IN8 の状態を取得しています(24-28 行)。 (2)取得した IN1-IN8 の状態をラベル label1 に表示しています(29-30 行)。 main 関数(35-82 行): プログラム実行時に最初に実行される関数です。 (1)表示する画面を作成します(41-70 行)。まずメインウィンドウを作成し、その上に垂直 ボックスを配置します。垂直ボックス上に IN1-IN8 の状態を表示するラベルとボタンを 作成します。 また 45 行と 68 行では、シグナル発生時に呼び出される関数をそれぞれ登録しています。 (2)作成した画面を実際に表示します(72 行)。 (3)デバイス番号 nNum の DIO ボードを DioOpen 関数を実行し、使用できるようにします(74 行)。 (4)GTK+のメインループに入ります。gtk_main_quit 関数が実行されるとこのループから抜け 出します(79 行)。 © 2001, 2005 Interface Corporation. All rights reserved. 43 第五章 ツール”Glade”を使った GUI アプリケーションの作成 第五章 ツール”Glade”を使った GUI アプリケーション作成 基礎編 自分で GTK+のプログラミングをすることに敷居が高いと感じた場合には、GTK+のプログラミン グ部分をサポートするユーザインタフェースビルダ「Glade」があります。この章では、Glade の 使い方と Glade を使った GUI アプリケーションの作成法について説明します。 Glade について Glade は、GTK+用のフリーのユーザインタフェースビルダです。ディストリビューションに添付 している場合もありますし、インターネットの以下の Web site からダウンロードすることもでき ます。 URL アドレス http://glade.gnome.org/ (1) (2) 図 5-1 (3) Glade 起動時の画面 (1)「Glade」メインウィンドウ:プロジェクトの設定、ファイルの保存などの設定 (2)パレット:ウィジェットを選択 (3)プロパティ:ウィジェットのサイズやシグナルとそのハンドラの登録などを設定 パレットで「ウィンドウ」や「ボタン」などのウィジェットをマウスで選択し、フォームを作成 することで、GTK+のプログラミング部分は Glade が自動作成してくれます。ユーザは、シグナル が発生することによって呼び出されるコールバック関数に自分が実行したい処理を記述するだけ で、グラフィカルな XWindow 用のアプリケーションを作成することができます。 © 2001, 2005 Interface Corporation. All rights reserved. 44 第五章 ツール”Glade”を使った GUI アプリケーションの作成 ■Glade の起動から実行ファイル作成までの手順 (1) XWindow 上の端末から次のコマンドを実行すると、Glade が起動します。 %glade (2) プロジェクトの設定を行います。 プロジェクトの設定は、「Glade」メイン ウィンドウのメニューバーの中から 「ファイル」を選び、その中にある 「プロジェクト設定」を選択します。 「プロジェクトのオプション」ウィンドウでプロジェクトディレクトリ、プログラム名 などを設定してください。 コンパイラ言語は、「C」を選んでください。 「OK」ボタンを押して、「プロジェクトのオプション」ウィンドウを閉じてください。 プロジェクト名 などの設定 C 言語 「OK」ボタン (3) 「パレット」ウィンドウにある、任意のウィジェット(ウィンドウ、ボタンなど)を 選択し、希望するデザインにフォームを作成してください(詳細は次項参照)。 (4) ソースコードの書出しを行います。 ソースコードの書出しは、「Glade」 ウィンドウのメニューバーの中から 「ファイル」を選び、その中にある 「ソースコード書出し」を選択します。 © 2001, 2005 Interface Corporation. All rights reserved. 45 第五章 ツール”Glade”を使った GUI アプリケーションの作成 (5) 端末から「プロジェクト設定」で設定した「プロジェクトディレクトリ」で、次のよう に入力し「enter」キーを押してください。 %./autogen.sh 実行すると様々なメッセージが出力されます。最後に「Now type ‘make’ to compile the package.」と表示されたら、make を実行してください。 %make 問題なくコンパイルできた場合、実行ファイルが、「/(プロジェクトディレクトリ)/src/」 ディレクトリに作成されます。 プログラムの実行(実行ファイルが「Project1」のとき) %./src/Project1 ※ 以後、フォームを修正した場合、その都度、「ソースコード書出し」と「make」の 実行が必要ですが、「./autogen.sh」は必要ありません。 ■Glade が自動作成するソースコードについて 「Glade」の「ソースコード書出し」と「./autogen.sh」の実行によって、たくさんのファイルが 生成します。そのうち、「/(プロジェクトディレクトリ)/src」ディレクトリに生成したファイルを ユーザがソースコードを追加したり、修正したりすることになります。 ●編集禁止のファイル なお「/(プロジェクトディレクトリ)/src」ディレクトリに生成したファイルのうち、 ・interface.c ・interface.h ・support.c ・support.h の4つのファイルはユーザが編集することを禁止しています。 ●編集可能なファイル 実際にユーザが編集するのは、主に ・main.c ・callbacks.c ・callbacks.h の 3 つのファイルになります。 うち、callbacks.c と callbacks.h は、コールバック関数のハンドラが設定されるたびに、その関 数のプロトタイプがファイルの最後に追加されます。 main.c は一度出力されると Glade では更新しないため、独自の編集が必要になります。 特にウィンドウ ウィジェットのポインタは、デフォルトでは main 関数の内部変数ですが、グロ ーバル宣言し、他のファイルからも参照できるようにした方がいいでしょう。 © 2001, 2005 Interface Corporation. All rights reserved. 46 第五章 ツール”Glade”を使った GUI アプリケーションの作成 ■ライブラリのリンク GTK+のライブラリは Glade が作成する Makefile の中で自動的にリンクされていますが、その他 の 弊社 Linux ソフトウェアで提供している関数を利用するなどには それらの関数が存在するラ イブラリをリンクする必要があります。 「/(プロジェクトディレクトリ)/src」ディレクトリにある「Makefile.am」ファイル(※プロジェ クトディレクトリに同名のファイルがありますが、こちらは編集しません。)に「LIBS= ‑l(ラ イブラリ名)」という1行を追加します。たとえば GPG-3300 の関数を使用するためのライブラリ libgpg3300.so をリンクに追加したい場合は、「LIBS= ‑lgpg3300」になります。 サンプルプログラム 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 「/(プロジェクトディレクトリ)/src/Makefile.am」で GPG-3300 の関数 を使用するためのライブラリ libgpg3300.so をリンクに追加する(7 行 目) ## Process this file with automake to produce Makefile.in INCLUDES = ¥ ‑I$(top̲srcdir)/intl ¥ $(GNOME̲INCLUDEDIR) LIBS = ‑lgpg3300 bin̲PROGRAMS = xdawave xdawave̲SOURCES = ¥ main.c ¥ support.c support.h ¥ interface2.c interface.h ¥ callbacks.c callbacks.h xdawave̲LDADD = $(GNOME̲LIBDIR) $(GNOMEUI̲LIBS) $(INTLLIBS) ※このソースコードは GPG-3300 添付の DA 波形出力プログラム xdawave の Makefile.Am です。 GPG-3300 インストール後に「/usr/src/interface/gpg3300/linux/util/xdawave/src」に存在します。 © 2001, 2005 Interface Corporation. All rights reserved. 47 第五章 ツール”Glade”を使った GUI アプリケーションの作成 Glade の操作法 (1)パレットでウィジェットを選択し、フォームを作成します。 前章で自分でプログラミングしたときと同様に、まずウィンドウを配置し、その上に水平 ボックス、垂直ボックス、テーブルなどでレイアウトをし、最後にラベルやテキストエン トリ、ボタンなどを設置します。 パレットと各ウィジェットの対比表(「GTK+ Basic」タグの場合) ハンドル ボックス テキスト ボックス ウィンドウ メニューバー ツールバー ラベル テキスト エントリ コンボボックス ボタン トグルボタン チェックボタン ラジオボタン リスト ツリー コラムリスト コラムツリー オプション メニュー スピンボタン プログレスバー ダイアログ ファイル選択 ダイアログ カラー選択 ダイアログ ステータス バー ドローイング エリア フォント選択 ダイアログ 水平ボックス 垂直ボックス テーブル 位置の固定 水平ボタン ボックス 垂直ボタンボッ クス 水平ペイン 垂直ペイン ノートブック フレーム スクロール ウィンドウ ビューポート 水平セパレータ 垂直セパレータ ピックスマップ 図 5-2 パレット (2)プロパティで各種設定を行う。 プロパティは「ウィジェット」、「配置」、「基本」、「シグナ ル」の 4 つのタグから構成されています。 ウィジェットにより設定できる内容が異なります。 © 2001, 2005 Interface Corporation. All rights reserved. 48 第五章 ツール”Glade”を使った GUI アプリケーションの作成 タグ 設定内容 ウィジェット ウィジェットの名前、タイトル(ラベル)などウィジェットのメインの設定。 ウィジェットがウィンドウの時に設定できる「モーダル」を「はい」にする と、そのウィンドウが表示されたとき、他のウィンドウに対するシグナル(ボ タンのクリックやテキストエントリの入力など)を無効にすることができま す。たとえばエラーが発生してポップアップを表示したときに、そのポップ アップを閉じなければ他の処理ができないようにすることが可能です。 他のウィジェットとの位置関係や隙間などの設定。 ウィジェットの幅や高さなどの設定。 シグナルとそれに伴うハンドラ(コールバック関数)の設定。 「シグナル」タグでコールバック関数の登録を行います。シグナルを指定し、 対応するハンドラ(コールバック関数の関数名)を登録すると、「ソースコ ードの書出し」で、callbacks.h ファイルにコールバック関数のプロトタイ プ宣言が、callbacks.c ファイルにコールバック関数の雛形がそれぞれ出力さ れます。 配置 基本 シグナル ※Glade で画面を作成するときの注意事項として、編集中の画面が実行時の大きさとは限らない ことがあげられます。プロパティの「基本」タグで、幅と高さを指定するか、 「位置の固定( : パレットの一番右の列の下から 3 つ目)」を利用します。「位置の固定」をウィンドウに追加 すると、その「位置の固定」上に追加するウィジェットはフォームの位置とサイズ(つまり見 たままの状態)で固定されます。 手順 (1)パレットで「 (ウィンドウ)」を選択。ウィンドウのフォームが表示される。 (2)パレットで「 (位置の固定)」を選択。ウィンドウのフォームに追加する。 (3)フォームの「位置の固定」上に任意のウィジェットを追加する。 © 2001, 2005 Interface Corporation. All rights reserved. 49 第五章 ツール”Glade”を使った GUI アプリケーションの作成 応用編 ウィジェットのハンドラを取得する テキストエントリやテキストボックスの文字列など、各ウィジェットの現在の状態を取得したい 場合、各ウィジェットのハンドラが必要になります。そのようなときは lookup̲widget 関数を使 って取得します。 lookup_widget 関数 GtkWidget* lookup_widget (GtkWidget *widget, const gchar *widget_name); widget 目的のウィジェットが存在するウィンドウ上にある、ハンドラがわかってい るウィジェット名 widget_name 目的のウィジェット名 戻り値 目的のウィジェットのハンドラ ※lookup̲widget 関数は、Glade 独自の関数です。Glade が自動作成する「(プロジェクト ディレクトリ)/src/support.c」ファイルに定義されています。 サンプルプログラム 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 GPG-4910 添付メモリエディタユーティリティ xmledit の callbacks.c より Open ダイアログで「OK」ボタンを押された場合、ダイアログ のテキストエントリ entry19 の文字列を取得し、デバイス番号として Open 関数を実行する。 void on̲Openbutton̲clicked (GtkButton *button, gpointer user̲data) { int nData; GtkWidget *entry; 目的のウィジェ ットのハンドラ を取得 entry = lookup̲widget(GTK̲WIDGET (button), "entry19"); nData = atoi(strdup(gtk̲entry̲get̲text(GTK̲ENTRY(entry)))); } ret = MlOpen(nData,0); Open 関数の実行 if(ret){ テキストエントリの文字 ErrorFunction(ret); 列の取得 } else { nDevice = nData; nOpenflag = 1; OpenInit(); gtk̲widget̲destroy(gtk̲widget̲get̲toplevel(GTK̲WIDGET(button))); } return; ダイアログ表示の 削除 © 2001, 2005 Interface Corporation. All rights reserved. 50 第五章 ツール”Glade”を使った GUI アプリケーションの作成 カスタムウィジェットで自由に画面を作成する 一部のスペースについて、Glade で用意されているウィジェットによる組み合わせではなく、自 分自身でウィジェットを組み合わせたい場合、カスタムウィジェットを選択することでそのスペ ースを自由に使えます。 (1)パレットの「GTK+ Additional」タグにある「 (カスタムウィジェット)」を選択し、編 集したいスペースをクリックします(下図左)。 (2)プロパティの「ウィジェット」タグにある「文字列 1」、「文字列 2」、「整数 1」、「整 数 2」で「作成関数」に渡す引数の値を設定できます(下図右)。 「GTK+ Additional」タグ 「作成関数」の名前、 関数に渡す引数の 設定 (2)カスタムウィジェットの プロパティ (1)パレット (3)「ソースコードの書き出し」により、callbacks.c の中に、プロパティで指定した「作成関数」 が作成されます。この関数の中で、プログラミングによって自由にウィジェットを作成す ることが可能になります。 自作用関数 GtkWidget* function_name ( gchar *widget_name, gchar *string1, gchar *string2, gint int1, gint int2); widget_name 親ウィジェットの名前(デフォルトでは”custom1”、”custom2”など) string1 (2)のパレットで指定した「文字列 1」のポインタ string2 (2)のパレットで指定した「文字列 2」のポインタ int1 (2)のパレットで指定した「整数 1」のポインタ int2 (2)のパレットで指定した「整数 2」のポインタ 戻り値 ウィジェットのハンドラ © 2001, 2005 Interface Corporation. All rights reserved. 51 第五章 ツール”Glade”を使った GUI アプリケーションの作成 使用例: メモリンク用ソフトウェア GPG-4910 のメモリエディタユーティリティ xmledit では、メモリデー タの表示部分をカスタムウィジェットを使って作成しています。 カスタムウィジ ェットの領域 callbacks.c の on_Clist 関数を作 成関数として フォーム 実行画面 実装 作成関数ではその関数が一つのウィジェットを作成するように記述します。メモリエディタユー ティリティの on̲Clist 関数では、メモリデータ表示用の「リスト」を作成しています。 サンプルプログラム 作成関数 on̲Clist (xmledit の callbacks.c) 78 79 80 81 82 83 char *clist̲titles[17] = { " ","00","01","02","03","04", "05","06","07","08","09","0A", "0B","0C","0D","0E","0F" }; 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 GtkWidget* on̲Clist (gchar *widget̲name, gchar *string1, gchar *string2, gint int1, gint int2) { unsigned long memadd; char s[9]; gchar *text[17] = { "00000000","00","00","00","00", "00","00","00","00", ウィジェット「clist1」のハ "00","00","00","00", "00","00","00","00" }; 230 行でタイトル行として 使用する文字列の宣言 ンドラを戻り値とする clist1 = gtk̲clist̲new̲with̲titles (17,clist̲titles); gtk̲widget̲ref (clist1); gtk̲object̲set̲data̲full (GTK̲OBJECT (clist1), "clist1", clist1, (GtkDestroyNotify) gtk̲widget̲unref); gtk̲widget̲show (clist1); リストの表示 gtk̲widget̲set̲usize (clist1, 450, ‑2); gtk̲clist̲column̲titles̲passive(GTK̲CLIST(clist1)); © 2001, 2005 Interface Corporation. All rights reserved. 52 タイトル行の固定化 第五章 ツール”Glade”を使った GUI アプリケーションの作成 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width gtk̲clist̲set̲column̲width (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (GTK̲CLIST (clist1), (clist1), (clist1), (clist1), (clist1), (clist1), (clist1), (clist1), (clist1), (clist1), (clist1), (clist1), (clist1), (clist1), (clist1), (clist1), (clist1), 0, 70); 1, 20); 2, 20); 3, 20); 4, 20); 5, 20); 6, 20); 7, 20); 8, 20); 9, 20); 10, 20); 11, 20); 12, 20); 13, 20); 14, 20); 15, 20); 16, 20); 列幅の指定 (for 文で短縮可) リストの初期化 gtk̲clist̲clear(GTK̲CLIST(clist1)); memadd = 0x0000; for (memadd=0; memadd <= 0x3ff0;memadd = memadd + 0x10) { sprintf (s ,"%08lX",memadd ); text[0] = s; リストに 1 行分の gtk̲clist̲append(GTK̲CLIST(clist1),text); } return clist1; } © 2001, 2005 Interface Corporation. All rights reserved. 53 データを追加 第五章 ツール”Glade”を使った GUI アプリケーションの作成 Glade を使ったデジタル出力ボード用サンプルプログラム トグルボタンが押されると、OUT1 が On,押し戻されると OUT1 が Off になるプログラム。 フォームにボタン、結果表示用のラベルを作成し、トグルボタンが”toggled”されたときのハンド ラを設定します。またハンドラに渡すユーザデータとして接点番号の 1 を渡すことにします。 トグルボタン 「プロパティ」でシグナル”toggled”に対するハンドラを 設定する。ハンドラにユーザデータとして、接点番号(こ こでは 1)を渡すようにすると、今後 接点数を増やし ても同じハンドラに接点番号を渡すだけで対応できる。 実行画面イメージ サンプルプログラム 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 プロジェクトディレクトリ/src/main.c #ifdef HAVE̲CONFIG̲H # include <config.h> #endif #include <gnome.h> #include "interface.h" #include "support.h" #include "fbidio.h" GtkWidget *window1; int main (int argc, char *argv[]) { int ret; glade が自動作成したときは main 関数内にあ る変数だが、ウィンドウのハンドラを取得する ために外部参照できるようにした方が便利 #ifdef ENABLE̲NLS bindtextdomain (PACKAGE, PACKAGE̲LOCALE̲DIR); textdomain (PACKAGE); #endif gnome̲init ("outputpoint", VERSION, argc, argv); /* * The following code was added by Glade to create one of each component * (except popup menus), just so that you see something after building * the project. Delete any components that you don't want shown initially. */ DIO ボードの Open ret = DioOpen(1,0); if (ret){ 今回はデバイス番号を固定しているが、グローバル printf("DioOpen:error¥n"); 変数にした方が便利 return 0; } window1 = create̲window1 (); © 2001, 2005 Interface Corporation. All rights reserved. 54 第五章 ツール”Glade”を使った GUI アプリケーションの作成 36 37 38 39 40 41 gtk̲widget̲show (window1); gtk̲main (); DioClose(1); return 0; } サンプルプログラム 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 DIO ボードの Close プロジェクトディレクトリ/src/callbacks.c #ifdef HAVE̲CONFIG̲H # include <config.h> #endif #include <gnome.h> #include #include #include #include "callbacks.h" "interface.h" "support.h" "fbidio.h" gboolean on̲window1̲delete̲event (GtkWidget GdkEvent gpointer *widget, *event, user̲data) { gtk̲main̲quit(); return TRUE; } void on̲togglebutton̲toggled (GtkToggleButton *togglebutton, gpointer user̲data) { int ret; int nData; unsigned long ulStartNum,ulNum; 接点番号が渡される引数 ボタンが押されたとき ulNum = 1; ulStartNum = (int) user̲data; if (GTK̲TOGGLE̲BUTTON(togglebutton)‑>active) { nData = 1; ボタンが押し戻されたとき } else { nData = 0; } ret = DioOutputPoint(1, &nData, ulStartNum, ulNum); if(ret){ printf("error:%xh¥n",ret); return; } return; } © 2001, 2005 Interface Corporation. All rights reserved. 55 第五章 ツール”Glade”を使った GUI アプリケーションの作成 解説: main 関数の存在する main.c には、DioOpen、DioClose のボードをオープン、クローズする処理を 追加しました(30-34 行、39 行)。シグナル発生から呼び出されるコールバック関数が存在する callbacks.c では、トグルボタンの”toggled”イベントから呼び出される on_togglebutton_toggled 関数 に OUT1 を On,Off する処理を追加しました。(行数の太字箇所が追加、または修正した箇所) © 2001, 2005 Interface Corporation. All rights reserved. 56 第六章 Kylix を使った GUI アプリケーションの作成 第六章 Kylix を使った GUI アプリケーションの作成 基礎編 Kylix は Borland 社が開発したビジュアル開発環境です。本書で紹介する言語は Pascal です。この 章では Kylix を使った GUI アプリケーションの作成法を説明します。 Kylix の基本的な使い方 (1) (4) (2)(3) 図 6-1 (5) Kylix の画面※11 (1)メインウィンドウ:メニュー、ツールバー、コンポーネントパレットがある。 (2)オブジェクトインスペクタ:オブジェクトのプロパティ、イベントを設定する (3)コードエクスプローラ:ユニット内のクラス、変数、ルーチンを表示する (4)コードエディタ:コードを編集する (5)フォームデザイナ:アプリケーションのユーザインタフェースを設計する コードエクスプローラ、一部のコンポーネントパレットは Kylix のエディション※12 によっては表 示されない場合があります。 ※11 画面は「BORLAND Kylix Desktop Developer」 Kylix には「Server Developer」,「Desktop Developer」,「Open Edition」という 3 つのエディ ションがあります。 © 2001, 2005 Interface Corporation. All rights reserved. ※12 57 第六章 Kylix を使った GUI アプリケーションの作成 基本的にはパレットでオブジェクトを選択し、フォームの上にのせていくことでユーザインタフ ェース(画面)を設計していきます。各オブジェクトについての設定は、オブジェクトインスペ クタの「プロパティ」タグで設定し、イベント処理を設定したい場合は同じくオブジェクトイン スペクタの「イベント」タグで任意のイベントに対する関数名を入力するとコードエディタに反 映されます。 設定例 (1)フォームの上にボタン Button1 を置く (2)オブジェクトインスペクトの「イベント」タグ でボタンをクリックされたときに呼び出される 関数を設定する。 (3)イベントハンドラの 雛形がコードエデ ィタに生成する。 ※begin〜end;の間に任意 の処理を記述します。 注意:Kylix で開発したアプリケーションを実行形式で配布する場合、Kylix 専用のライブラリも 一緒に添付しないと動作しない、という問題があります。ただしこの問題は将来的にはディスト リビューションに Kylix 専用ライブラリが添付されることで解決されるかもしれません。 © 2001, 2005 Interface Corporation. All rights reserved. 58 第六章 Kylix を使った GUI アプリケーションの作成 共有ライブラリのインポート Kylix で共有ライブラリの関数を使えるようにするためには、関数をインポートするための記述 が必要です。 雛形は次のようになります。 function 関数名 ( 引数名: 引数の型) : 戻り値の型; cdecl; external '共有ライブラリ名'; たとえば、共有ライブラリのファイル名が 「libgpg2000.so」で、そのライブラリに含まれる DioOpen 関数を利用する場合、次のように記述します。 function DioOpen ( nDevice: Integer; reserved: DWORD) : Integer; cdecl; external 'libgpg2000.so'; 参考までに C 言語の場合、DioOpen 関数のプロトタイプは次の通りです。 DioOpen 関数 int DioOpen ( int nDevice, unsigend long reserved ); nDevice デバイス番号 reserved 予約:0 を指定してください 戻り値 エラー識別子 実際に DioOpen 関数を実行するには以下のように記述します。 使用例 Button1 がクリックされたら DioOpen 関数を実行する procedure TForm1.on̲Button1̲Clicked(Sender: TObject); var nRet: Integer; begin nRet := DioOpen( 1, 0 ); end; © 2001, 2005 Interface Corporation. All rights reserved. 59 第六章 Kylix を使った GUI アプリケーションの作成 応用編 ユニットファイルの追加 弊社 Linux 汎用入出力ライブラリ BPL-0804 とメモリンクボード用 Linux 対応ソフトウェア GPG-4910 では各製品の共有ライブラリをインポートするためのユニットファイルがそれぞれ用 意されています(このほかの製品も順次提供する予定です)。 このユニットファイルを利用するためには、ファイルをプロジェクトに追加する必要があります。 プロジェクトへの追加は、メニューの「プロジェクト」-「プロジェクトに追加」を選び、現れた ダイアログボックスの中でプロジェクトに追加したいファイルを選択し、「開く」ボタンを押し ます。 図 6-2 プロジェクトに追加 メインとなるユニットの「uses」にユニットを加えると、追加したユニットの中で宣言された関 数が使えるようになります。 使用例 1 2 3 4 5 6 7 8 FbiMl.pas で宣言された関数を使いたい場合 unit Unit1; interface uses SysUtils, Types, Classes, (中略), FbiMl; type © 2001, 2005 Interface Corporation. All rights reserved. 60 第六章 Kylix を使った GUI アプリケーションの作成 Kylix で作成したデジタル入力ボード用サンプルプログラム フォームにテキストエントリとボタンを用意し、ボタンがクリックされたときにでキスとエント リに入っている文字列を取得し、その文字列を入力接点番号として、該当接点の状態をデジタル 入力し、結果をダイアログに表示するプログラムです。 DIO ボード用ライブラリ関数を使えるようにするユニットファイル fbidio.pas を前提にしていま す。 ボタンを押すと、テキスト エントリの接点番号の入 力状態を表示 図 6-3 実行画面のイメージ サンプルプログラム 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 unit InBox; interface uses SysUtils, Types, Classes, Variants, QGraphics, QControls, QForms, QDialogs, QStdCtrls, fbidio; ユニットファイルの追加 type TForm1 = class(TForm) Button1: TButton; Edit1: TEdit; procedure Button1Click(Sender: TObject); private { Private } public { Public } end; var Form1: TForm1; implementation ボタンがクリックされると呼び出される関数 {$R *.xfm} procedure TForm1.Button1Click(Sender: TObject); var dwStartNum: DWORD; var nBuffer: Integer; nRet: Integer; pStr: PChar; © 2001, 2005 Interface Corporation. All rights reserved. 61 第六章 Kylix を使った GUI アプリケーションの作成 begin dwStartNum := StrToInt(Edit1.Text); nRet := DioOpen(1,0); IF nRet<>0 Then begin Application.MessageBox('Opening the board failed','InPoint', [smbOK]); Exit; end; 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 nRet := DioInputPoint(1,nBuffer,dwStartNum,1); IF nRet<>0 Then begin Application.MessageBox('Input the data failed','InPoint',[smbOK]); DioClose(1); Exit; end; 指定した接点の pStr := PChar('Input data = '+IntToStr(nBuffer)); Application.MessageBox(pStr,'InPoint',[smbOK]); デジタル入力状態を ダイアログに表示 nRet:=DioClose(1); IF nRet<>0 Then begin Application.MessageBox('Closing the board failed','InPoint', [smbOK]); Exit; end; end; end. (行数の太字箇所が追加、または修正した行) 解説: (1)DIO ボード用のライブラリ関数をインポートするためのユニットファイル FbiDio.pas を追加 (7 行) (2)変数の宣言(28-32 行) TForm1.Button1Click(27-61 行)は、Button1 をクリックすると呼び出される関数です。 (3)テキストエントリの文字列(ここでは入力状態を調べる接点番号)を取得(34 行) (4)DioOpen 関数を実行し、デバイス番号 1 の DIO ボードを使用可能にします。 関数の実行に失敗した場合は、メッセージボックスで表示します(35-41 行)。 (5)DioInputPoint 関数を実行し、指定した接点の入力状態を取得しています(43-49 行)。この 場合、接点番号 dwStartNum から 1 点の入力状態を取得し、結果を nBuffer に格納していま す。 (6)取得した入力状態をメッセージボックスに表示します(51-52 行)。 (7)DioClose 関数を実行し、DIO ボードの使用を終了します。 関数の実行に失敗した場合は、メッセージボックスで表示します(54-60 行)。 © 2001, 2005 Interface Corporation. All rights reserved. 62 Linux 対応ソフトウェア製品の紹介 Linux 対応ソフトウェア製品の紹介 最後に弊社 Linux 対応ソフトウェア製品を紹介します。Linux 対応ソフトウェア製品の最新情報 は、以下の弊社 Web site にてご確認ください。 http://www.interface.co.jp/catalog/soft/linux_info.asp ◆Topic 1 PCI ボード、Compact PCI ボード、CardBus カードの全カテゴリをサポート。 関数体系は Windows 版と高い互換性 弊社は PCI ボード,CompactPCI ボード,CardBus カードの全カテゴリに Linux 対応します。関数体 系は Windows 版と高い互換性を維持しており、Windows 版からの移行も容易です。 ◆Topic 2 カーネル 2.4 対応 Linux のカーネル Ver.2.4 に対応しています。※ ◆Topic 3 Kylix 対応 Kylix 上でライブラリ関数をインポートするためのユニットファイルとサンプルプログラムを用 意しています。※ ◆Topic 4 サンプルプログラム、ユーティリティプログラムが付属 Linux 対応ソフトウェアには、Kylix 以外にも C 言語用のサンプルプログラム、ユーティリティプ ログラムなどが付属し、ハードウェア制御のためのプログラミングをバックアップします。 ◆Topic 5 CompactPCI ボードへの対応 弊社 CompactPCI ボードにも対応しています。Compact PCI ボードは、PCI ボードと互換性が維持 されており、PCI ボードと同様に制御することが可能です。 ◆Topic 6 CardBus カード、CardBus バスブリッジへの対応 弊社 CardBus 製品も Linux に対応しています。 ※いずれも一部製品を除きます。 ※ソフトウェア製品の仕様は予告なく変更される場合があります。 © 2001, 2005 Interface Corporation. All rights reserved. 63 Linux 対応ソフトウェア製品の紹介 主な Linux 対応ソフトウェア製品 カテゴリ メモリ ディスク RAS デジタル 入出力 アナログ 入出力 シリアル 通信 GP-IB フラッシュメモリ PC カード DIO バスマスタ ロジックアナライザ PPI アナログ入力 アナログ出力 アナログ入出力 キャラクタ同期 LAP-B HDLC 標準 COM バスマスタ FIFO CAN メモリンク 画像 カウンタ Linux 対応 RTLinux 対応 GPG-1604 GPG-1609 GPG-1900 GPG-2000 ○ ○ ○ ○ ○ ○ ○ ○ GPG-2x72C GPG-2910C GPG-2746C GPG-3100 GPG-3300 GPG-3500 GPG-4101 GPG-4115 GPG-4116 GPG-4141 GPG-4301 GPG-4304 GPG-4851 ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ − − ○ ○ − ○ ○ − ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ ○ − ○ ○ − − ○ − − ソフトウェア 製品型式 GPG-4910 エンコーダ ユニバーサル パルスカウンタ パルス出力 モータ プリンタ SH 搭載 CPU ボード SH 搭載 CPU ボード/USB 接続 SH-4 搭載 CF 型 CPU ボード 汎用入出力ライブラリ CardBus バスブリッジ GPG-5520 GPG-6204 GPG-6201 GPG-6202 GPG-6320 GPG-6106 GPG-6105 GPG-7400 GPG-7204 GPG-7302 GPG-8208 GPG-8210 GPG-SH02 GPG-SH02R GPG-SH02RU GPG-SH02U GPG-SH03 GPG-SH03R BPL-0804 GBG-8521 ※ 記載内容は 2005 年 3 月現在のものです。表に記載されていないハードウェア型式も Linux 対応 を行う予定です。最新情報は弊社 Web site にてご確認ください。 ※ ソフトウェア製品の型式、仕様、ハードウェア対応型式は予告なく変更されることがあります。 © 2001, 2005 Interface Corporation. All rights reserved. 64 技術資料紹介 技術資料紹介 弊社では下記の技術資料を提供しております。 詳しくは、弊社 Web site(www.interface.co.jp)、または弊社窓口までお問い合わせ下さい。 カタログ PRM-0058 インタフェース総合カタログ チュートリアル TUT-0014 Microsoft Visual Studio .NET 移行ガイド TUT-0006 C(98)/ISA 製品から PCI/CompactPCI 製品への移行チュートリアル(DOS 編) TUT-0007 拡張ユニット チュートリアル(入門編) TUT-0008 拡張ユニット チュートリアル(問題解決編) TUT-0009 システムユニット チュートリアル TUT-0025 Visual Basic による DIO 入門書 TUT-0016 Visual Basic による PPI 入門書 TUT-0021 Visual Basic による AD 入門書 TUT-0023 Visual Basic による DA 入門書 TUT-0029 Visual Basic による HDLC 入門書 TUT-0027 Visual Basic による GP-IB 入門書 TUT-0033 Visual Basic による メモリンク 入門書 TUT-0031 Visual Basic による エンコーダカウンタ 入門書 TUT-0019 Visual Basic による モータコントローラ 入門書 TUT-0024 Visual C++ による DIO 入門書 TUT-0034 Visual C++ による PPI 入門書 TUT-0020 Visual C++ による AD 入門書 TUT-0022 Visual C++ による DA 入門書 TUT-0028 Visual C++ による HDLC 入門書 TUT-0026 Visual C++ による GP-IB 入門書 TUT-0032 Visual C++ による メモリンク 入門書 TUT-0030 Visual C++ による エンコーダカウンタ 入門書 TUT-0018 Visual C++ による モータコントローラ 入門書 TUT-0015 モーションコントロール チュートリアル TUT-0053 モーションコントロール チュートリアル(PCI/CompactPCI) TUT-0001 弊社バスブリッジを使用した PCI バスによる C バスボード制御 手順書 TUT-0002 弊社バスブリッジを使用した PCI バスによる ISA バスボード制御 手順書 TUT-0003 Linux による PCI/CompactPCI/CardBus 制御 入門書 TUT-0017 システム事例 メモリンクを使用した負荷分散システム チュートリアル TUT-0036 RTLinux による PCI/CompactPCI/CardBus 制御入門書(導入編) TUT-0037 RTLinux による HDLC ボード制御プログラミング チュートリアル TUT-0038 RTLinux による DIO ボード制御プログラミング チュートリアル TUT-0039 RTLinux による AD ボード制御プログラミング チュートリアル TUT-0043 RTLinux による調歩同期シリアル通信ボード制御プログラミング チュートリアル TUT-0040 RTLinux による DA ボード制御プログラミング チュートリアル TUT-0041 RTLinux による GP-IB ボード制御プログラミング チュートリアル TUT-0044 RTLinux によるメモリ共有インタフェースボード制御プログラミング チュートリアル TUT-0048 RTLinux によるカウンタボード制御プログラミング チュートリアル TUT-0050 RTLinux によるモーションコントローラボード制御プログラミング チュートリアル TUT-0054 CAN チュートリアル TUT-0055 チュートリアル 画像入力ボード 技術情報資料(セミナ資料) 初めての CAN インタフェース Linux, リアルタイム Linux 移植(SH-4)経験談及び当社の今後の取り組みについて Linux から PCI/CompactPCI ボードを制御する方法 ActiveX コントロールによるシステム組み込み技術 CompactPCI への置き換え+システム構築/移行ガイド MS-DOS から PCI/CompactPCI ボードを制御する方法 © 2001, 2005 Interface Corporation. All rights reserved. 65 参考文献 参考文献 ・ ALESSANDRO RUBINI 著、山崎康宏、山崎邦子訳、「LINUX デバイスドライバ」オライリ ー・ジャパン、1998 年、ISBN4-900900-73-7 ・ Michal K. Johnson, Erik W. Troan 著、クイック訳、「プログラミング Linux」アスキー出版局、 1998 年、ISBN4-7561-2044-X ・ カート・オール著、野村純子訳、桑村潤監修、「例題で学ぶ Linux プログラミング」ピアソ ン・エデュケーション、2001 年、ISBN4-89471-286-5 ・ 竹田英二著、「GTK+ではじめる X プログラミング」技術評論社、1999 年、ISBN4-7741-0789-1 ・ 田中ひろゆき著、「GTK+入門 基礎からはじめる X プログラミング」ソフトバンク、1999 年、 ISBN4-7973-0871-0 ・ 鈴木哲哉著、「GTK+と Glade で作る Linux プログラミング超入門」すばる舎、2000 年、 ISBN4-88399-049-4 ・ 西村めぐみ著、 「図解でわかる Linux のすべて」日本実業出版社、2000 年、ISBN4-534-03096-7 ・ インタフェース、「PCI-8571 I/O 公開資料」インタフェース、1999 年 ・ Web site「Helpdesk: Tips for Linux」(http://www.zdnet.co.jp/help/tips/linux/) © 2001, 2005 Interface Corporation. All rights reserved. 66 Linux による PCI/CompactPCI/CardBus 制御 入門編 2005 年 3 月 Ver. 1.8 発行所 発行 〒732-0828 広島県広島市南区京橋町 10-21 TEL 082-262-7777 FAX 082-262-5066 ISD-7036-18 価格 ¥2,100 (定価 ¥2,000 + 消費税 ¥100) 本書の内容の一部または全部を、無断で転載することを禁止します。 本書の内容は、将来予告なく変更することがありますので、あらかじめご了承ください。 © 2001, 2005 Interface Corporation. All rights reserved. チュートリアル Linux による PCI/CompactPCI/CardBus 制御 入門編 TUT-0003 Ver. 1.8 www.interface.co.jp www.interface.co.jp
© Copyright 2024 Paperzz