• 検索結果がありません。

LinuxによるPCI/CompactPCI/CardBus制御 入門編

N/A
N/A
Protected

Academic year: 2021

シェア "LinuxによるPCI/CompactPCI/CardBus制御 入門編"

Copied!
72
0
0

読み込み中.... (全文を見る)

全文

(1)
(2)

改訂履歴 改訂履歴 Ver 年 月 改 訂 内 容 1.0 2001年 9 月 初版 1.1 2001年 10 月 Linuxカーネル 2.4 に対応した記述を追加 1.2 2001年 11 月 CompactPCIボードに対応した記述を追加 insmodコマンドに関する説明を補足 1.3 2002年 4 月 Tipsを追加 1.4 2002年 7 月 Linux対応ソフトウェア製品を更新 1.5 2002年 11 月 CardBusカードに関する記述を追加 1.6 2003年 8 月 ソフトウェア製品の改版に合わせて更新 1.7 2004年 5 月 CardBusに対応した記述を追加 誤記修正 1.8 2005年 3 月 技術資料一覧更新 誤記修正 本チュートリアルをご使用の際は、必ず各製品型式の最新のドキュメント(ユーザーズマニュアル,オンライ ンヘルプ)をあわせて参照してください。また、最新のドライバソフトウェアをご使用ください。ユーザー ズマニュアル, ドライバソフトウェアは弊社 Web site からダウンロードできます。(オンラインヘルプはドラ イバソフトウェアに含まれています) 商標/登録商標

Linuxは Linus Torvalds 氏の商標です。

Kylixは米国 Borland Software Corporation の商標または登録商標です。

その他、本書に掲載されている会社名、製品名は、それぞれ各社の商標または登録商標です。 保証の内容と制限 株式会社インタフェースは本書の情報の正確さに万全を期しています。万一、誤記または誤植などがあった 場合、株式会社インタフェースは予告無く改訂する場合があります。本書または本書内の情報に起因するい かなる損害に対しても株式会社インタフェースは責任を負いません。 本書の図や表は説明のためであり、ユーザ個別の応用事例により変化する場合があります。 著作権、知的所有権 株式会社インタフェースは本書に対する権利や知的所有権を保持しています。 本書はコンピュータ ソフトウェア(プログラム)、 図、 文章、 写真などを含んでいます。 複製の禁止 株式会社インタフェースの許可なく、本書の全て、または一部に関わらず、複製、改変などを行うことはで きません。

(3)

目次

[目次]

はじめに...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

(4)

目次 ■コンパイル ...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

(5)

はじめに

はじめに

平素は格別のご高配を賜り、厚くお礼申し上げます。本冊子は Linux 上で弊社 PCI ボード、 CompactPCIボード、CardBus カード(以降、特に断らない限りボードと呼びます)を制御したい方 を対象に、Linux でのハードウェア制御、プログラミング環境からコンソールアプリケーション、 GUIアプリケーションの作成方法と、そこからハードウェアを制御するアプリケーションの作成 方法までを記載しています。Linux 上での弊社製品をはじめとするハードウェア制御のためのプ ログラミングにお役に立てれば幸いです。 なお本冊子は Linux カーネル 2.2 系、2.4系を対象に作成されています。カーネルバージョンが異 なる場合、動作保証はいたしかねますので予めご了承ください。 ●ご意見,ご要望 弊社へのご意見,ご要望がございましたら、下記までお問い合わせください。 www.interface.co.jp E-mail:[email protected] ●本書での表記について コマンドの実行例において、行頭に「%」がつく場合は一般ユーザでの実行、「#」がつく場合は rootでの実行を意味します。「%」や「#」は実際に入力する文字ではありませんのでご注意くだ さい。

(6)

第一章 Linux のハードウェア制御

第一章 Linux のハードウェア制御

基礎編

Linux

のハードウェア制御

Linuxの場合、Windows と同様にユーザアプリケーションから直接、PCI ボード、CompactPCI ボ ードをはじめとするハードウェアを制御することはできません。これは不用意にハードウェアリ ソースにアクセスできると、人為的なミスや悪意のあるユーザによってシステムが破壊されてし まう危険性があるからです。 そのため、システムコール※1を使ってデバイスドライバを経由してハードウェアを制御します。 弊社 Linux 製品では、より使いやすくするためにシステムコールをラップした関数を用意し、ラ イブラリとして提供しています。 その結果、ユーザアプリケーションからはライブラリ関数を使用して、ハードウェアを制御しま す(図 1-1)。 デバイスドライバ ライブラリ ユーザアプリケーション ユーザ空間 カーネル空間 ライブラリ関数の呼び出し ハードウェア 図 1-1 アプリケーションによるハードウェア制御の概念図

(7)

第一章 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]

(8)

第一章 Linux のハードウェア制御

■CardBus カードの認識と制御

CardBusは、PC カードスロットの規格の一つで、これまでの PC カードが 16 ビット幅でアクセス していたのに対し、32 ビット幅でアクセス可能であるため、より高速にアクセスできます。 CardBusは PCI バスに準拠しているため、パソコン上からは PCI/ CompactPCI ボードと同様に認 識、制御できます。

「lspci –v」コマンドの実行例(2):CBI-2701 を実装した状態

%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]

弊社 CardBus-PCI/CompactPCI/CardBus バスブリッジ CBI-PCUxx,CBI-CTUxx,CBI-CBUxx でも、 付属ソフトウェア ACD-8521 に含まれる Linux 対応ソフトウェア GBG-8521 により、デスクトッ プパソコンの PCI-PCI バスブリッジと同様に ノートパソコンから拡張した PCI/CompactPCI/CardBus製品をご利用いただけます。 CardBusコント ローラの情報 CBI-2701の情報

(9)

第一章 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 を組み込んだ状態

(10)

第一章 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

(11)

第一章 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

弊社 Linux 製品では、弊社のデバイスドライバを制御するためのデバイスノードを自動作成する プログラムdpg0101 を用意しています。このプログラムでは、弊社ボードに弊社がデバイス番号 と呼んでいるハードウェア識別のための番号を設定し、作成するデバイスノードと設定ファイル デバイスノード名 マイナー番号 メジャー番号 マイナー番号 メジャー番号 c:キャラクタ型デバイスノ ードであることを示す

(12)

第一章 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.

---  1 | PCI/PAZ-2726C | 0 | 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 の場合は、デバイス番号という考え方はありませんが、同 様にデバイスノードを作成するプログラムとして、デバイスノード作成プログラムを用意してい ます。 RSW1が「0」に設定された PCI/PAZ-2726Cがデバイス番号 1 で 登録されようとしていることを示し ます。 ソフトウェアの型式

(13)

第一章 Linux のハードウェア制御 ■デバイスファイルシステム デバイスファイルシステムは、デバイスノードを動的に扱うことができるシステムで、Linux カ ーネル 2.4 からオプションで採用されました。 今までは、デバイスノードがない場合、mknod コマンドを使ってデバイスノードを作成する必要 がありましたが、このシステムを採用すると、ユーザアプリケーションがデバイスノードをオー プンしようとしたときにカーネルが自動的にデバイスノードを作成し、クローズすると削除する ようになります。 またデバイスノードが存在する「/dev/」ディレクトリも構成が変わり、たとえばシリアル通信 用のデバイスノードでは次のようになります。 例:シリアル通信用デバイスノード ・デバイスファイルシステム無効 /dev/ttyS1 ・デバイスファイルシステム有効 /dev/tts/1 「/dev/」ディレクトリに直接存在していたデバイスノードが「/dev/tts/」ディレクトリ」に存 在し、デバイスノード名がたんなる数字に変わりました。 このことはデバイスノードへのパスが変更することを意味しており、デバイスノードを直接制御 しているプログラムを使っている場合、デバイスファイルシステムに移行するときは、注意が必 要です。 なおカーネル 2.4 系のディストリビューションでは、インストール時にデフォルトでデバイスフ ァイルシステムが無効になっているものもあり、デバイスファイルシステムを有効にしなくても カーネル 2.4 を利用することは可能です。 弊社ソフトウェアのデバイスファイルシステムへの対応については、各ソフトウェアの readme にてご確認ください。

(14)

第一章 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 であることを示しています。

(15)

第一章 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,オンラインヘルプをご覧下さい。

(16)

第一章 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) ※カッコ内の数値はパソコンによって変わることがあります。

(17)

第二章 Linux のプログラミング開発環境

第二章 Linux のプログラミング開発環境

基礎編:

Linux

のプログラミング開発環境

Linuxのプログラミング開発環境は比較的容易に整えることができます。 プログラミング開発環境として必要なコンパイラ、ライブラリなどが、ディストリビューション に添付されている場合がほとんどだからです。ディストリビューションのインストール時に、開 発関連のパッケージ(“開発ツール”“カーネル開発”などと表示されていることが多いですが、 ディストリビューションによって異なります)を選択しておけば、ディストリビューションのイ ンストール終了と同時(正確には一度、再起動したあと)にプログラミング開発を行うことがで きます。 インストール時にカスタムでパッケージを選ぶ際は、前述の開発関連のツールの他に、グラフィ カルな環境を利用したい場合は GNOME または KDE などの X Window System を、またエディタ として Emacs もインストールしておくと便利がいいと思います。 プログラミング開発に必要な環境 ・コンパイラ(GCC) ・ライブラリ(libc など) ・エディタ(Vi, Emacs, ほか) プログラミング開発に便利なもの ・デバッガ(gdb) ・X Window System など カーネル ライブラリ コンパイラ 図 2-1 ディストリビューションのイメージ X Window System デバッガ エディタ 各種アプリケーションソフトウェア

(18)

第二章 Linux のプログラミング開発環境

エディタ

Linuxにはプログラムを作成するために使うエディタとして Vi、Emacs、gEdit など様々あります。 ここでは、メジャーなエディタである Vi、Emacs(※Emacs を単なるエディタとして扱うことに 不満を感じる方もいらっしゃるかもしれませんが)について簡単にまとめました。 ■Vi

UNIX系で標準のエディタです。Vi を起動しても、すぐに文字を入力できません。Vi を起動する

(端末から「vi」で起動できます。)と、コマンド待ちの状態になっており、入力できる状態にする には、入力状態(INSERT)にするためのコマンド「i」(「i」キーを押す)が必要だからです。 入力状態からコマンド状態に戻るためには「Esc」キーを押します。 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)です) Tips:改行コード「^M」を削除するには

(19)

第二章 Linux のプログラミング開発環境 表 2-1 Vi で知っておくと便利なコマンド(これらはコマンド状態の時に使用) コマンド  用途 i a o 文字を入力できる状態にする。カーソルの前に文字を入力※ 文字を入力できる状態にする。カーソルの後に文字を入力※ 文字を入力できる状態にする。行のはじめから文字を入力※ x 文字の削除 文字の入力状態で「Back space」キーを押しても削除できます。 dd 行の削除 yw 単語のコピー yy (Y と同じ) 行のコピー p カーソル位置の文字または行のあとにペースト P カーソル位置の文字または行のまえにペースト u 元に戻す 1G 先頭行にジャンプ G 最終行にジャンプ H 表示されているページの先頭行にジャンプ b 1単語前にジャンプ E 1単語後にジャンプ 0 (ゼロ) 行の先頭にジャンプ $ 行の最後にジャンプ /文字列 カーソル位置の下方に向かって、文字の検索 ?文字列 カーソル位置の上方に向かって、文字の検索 :w ファイルを上書き保存 「:w ファイル名」で任意のファイル名で保存。 :w! 強制的にファイルを上書き保存。 ZZ ファイルを上書き保存して終了 :q Viを終了 :q! 強制的に(変更を行ったあとでも保存せずに)Vi を終了。 「ESC」キーで、コマンド状態に戻ります。

(20)

第二章 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 の実行画面

(21)

第二章 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 を作成

(22)

第三章 ボードを制御するプログラムの作成

第三章 ボードを制御するプログラムの作成

基礎編

弊社ボード用 Linux 対応ソフトウェアからの制御

弊社ボード用 Linux 対応ソフトウェアが提供されている場合は、そのソフトウェアを使って対象 ボードを制御することが可能です。 基本的にはXXOpen 関数(XX の部分はソフトウェア型式によって異なります)を用いて、ボードを利 用可能な状態にし、ライブラリ関数を用いて各ボードを制御します。ボードを使い終わったら XXClose 関数を実行して、ボードの利用を終了します。もし XXClose 関数を実行せずにアプリケ ーションを終了した場合でも、アプリケーション終了時に各ボードへのクローズ処理が自動的に 行われます。再度、ボードを利用する場合、XXOpen 関数を実行する必要があります。 関数体系は、デバイス番号などの一部の引数や、イベント処理など Linux と Windows との間で互 換性のないものを除き、原則として Windows 版の PCI ボード付属ソフトウェアと互換性を持たせ ており、Windows 版で制御されていた方にとっても取り組みやすいようにしています。 ●基本的な流れ (1)XXOpen 関数でボードをオープン(利用可能な状態に)する (2)ライブラリ関数を利用し、ボードを制御する (3)ボードを使い終わったらXXClose 関数でボードをクローズする

(23)

第三章 ボードを制御するプログラムの作成

汎用入出力ライブラリ 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 を作成し、組み込みます。(割り込み処 理の利用の仕方については後述)

(24)

第三章 ボードを制御するプログラムの作成

PCI

コンフィグレーションレジスタ情報の取得

ボードの I/O ポート領域やメモリ領域を直接制御する場合、ボードのリソース情報を取得する必 要があります。 このリソース取得用関数として、Linux 汎用入出力ライブラリ BPL-0804 では、UioGetConfigRegEx 関数があります。この関数によって全ての PCI コンフィグレーション空間の情報を取得すること ができます。UioGetConfigReg 関数とくらべ、全ての PCI コンフィグレーション空間の情報を取 得することができるだけでなく、第4引数にサブシステム ID を指定することにより、デバイス IDが同じでもボード型式が違う場合(たとえば PCI-2725 と PCI-2725A の関係。CompactPCI ボー ドもサブシステム ID が異なります)にボードを区別できます。

UioGetConfigRegEx関数

long unsigned long

unsigned short unsigned short unsigned short unsigned short unsigned short PPCI_CONFIG ulIndex, ven_id, dev_id, subven_id, subsys_id, *bus_info, pPciData ); ulIndex ボードのインデックス番号(同一型式が複数枚ある時、2 枚目以降のボードを指 定できます。1 枚しかないときは、1 を指定します) ven_id ベンダ ID dev_id デバイス ID subven_id サブシステムベンダ ID subsys_id サブシステム ID *bus_info バス情報を取得する変数へのポインタ pPciData PCIコンフィグレーションレジスタの値を取得する構造体へのポインタ 戻り値 エラー識別子

ベンダ ID、デバイス ID、サブシステムベンダ ID、サブシステム ID などの情報は各ボードの I/O 公開資料に記載されています。ちなみに弊社 PCI ボード、CompactPCI ボードのベンダ ID、サブ システムベンダ ID は、バスブリッジボード、Ethernet インタフェースボードなどを除き、原則と してそれぞれ 1147h です。

(25)

第三章 ボードを制御するプログラムの作成

I/O

領域へのアクセス

BPL-0804で I/O 領域にアクセスするためには、予めその領域を予約し、処理が終了したあとは、 予約した領域を解放する必要があります。各領域を予約、解放、リード、ライトするための関数 について説明します。 (1)I/O 領域の予約:UioRequestRegion 関数 UioRequestRegion関数 long

void** pReg, unsigend long ulBaseAddr, unsigned long ulSize );

pReg I/Oポート領域クレーム用ポインタ格納用変数へのポインタ

ulBaseAddr 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 設定データ(バイト単位)

(26)

第三章 ボードを制御するプログラムの作成

I/O領域の解放: UioReleaseRegion 関数 UioReleaseRegion関数

long UioReleaseRegion( void* pReg );

pReg I/Oポート領域クレーム用ポインタ

戻り値 エラー識別子

サンプルプログラム BPL-0804の I/O ポートにアクセスするプログラム:PCI-2726C で OUT8 ∼OUT1 に 55h 出力し、IN16∼IN9 の状態を入力する。 1 2 3 4 5 6 7 8 9 #include “fbiuio.h” int main(void) { int ret; PCI_CONFIG PciData; int bus;

unsigned int nIoAdr; unsigned char Irq; 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 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; }

(27)

第三章 ボードを制御するプログラムの作成

解説:

(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 行)。

(28)

第三章 ボードを制御するプログラムの作成

メモリ領域へのアクセス

メモリ領域にアクセスする場合も同様に、予めその領域を予約し、処理が終了したあとは、予約 した領域を解放する必要があります。各領域を予約、解放、リード、ライトするための関数につ いて説明します。 (1)メモリ領域の予約: UioMapMemory 関数 UioMapMemory関数 long

void** pMem, unsigned long ulBaseMem, unsigned long ulMemSize );

pMem 物理メモリアクセス用ポインタ格納用変数へのポインタ

ulBaseMem 物理メモリの先頭アドレス

ulMemSize メモリサイズ

戻り値 エラー識別子

(2)メモリ領域からのデータの取得(read): UioPeekXXX 関数(XXX には Byte, Word, Dword がそ れぞれあてはまります。各関数の違いは第 3 引数の取得データサイズがそれぞれbyte, word, double word になっているだけです)

UioPeekByte関数 long

void* pMem, unsigned long ulOffset, unsigned char *ucpData );

pMem 物理メモリアクセス用ポインタ

ulOffset オフセットアドレス

ucpData 取得データ(バイト単位)

戻り値 エラー識別子

(3)メモリ領域への書き込み(write):UioPokeXXX 関数(XXX には Byte, Word, Dword がそれ ぞれあてはまるあてはまります。各関数の違いは第 3 引数の設定データサイズがそれぞれ byte, word, double word になっているだけです)

UioPokeByte関数 long

void* pMem, unsigned long ulOffset, unsigned char ucData );

pMem 物理メモリアクセス用ポインタ

ulOffset オフセットアドレス

(29)

第三章 ボードを制御するプログラムの作成

(4)メモリ領域の解放:メモリ領域の解放はUioUnMapMemory 関数を使います。 UioUnMapMemory関数

long UioUnMapMemory( void* pMem );

pMem 物理メモリアクセス用ポインタ 戻り値 エラー識別子 サンプルプログラム BPL-0804のメモリ領域にアクセスするプログラム:PCI-4914 のメモリ 領域にデータの書き込み、読み込みを行う 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 #include “fbiuio.h” int main(void) { int ret;

unsigned short bus; PCI_CONFIG PciData; unsigned int nIoAdr; unsigned long ulMemAdr; unsigned char Irq; long lTimeout = 5000; void *pReg;

void *pMem;

unsigned char ucData = 0; ret = UioOpen();

if (ret) return -1;

UioGetConfigRegEx(1, 0x1147, 4914, 0x1147, 0x0001, &bus, &PciData); nIoAdr = PciData.BaseAddresses[0] & 0xFFFC;

ulMemAdr = PciData.BaseAddresses[1] & 0xFFFFFFF0; Irq = PciData.InterruptLine

UioRequestRegion( &pReg, nIoAdr, 0x0F); /* I/O 領域の予約 */ UioMapMemory( &pMem, ulMemAdr, 0x40000); /* メモリ領域の予約 */ ucData = 0x80;

UioOutpByte(nIoAdr, ucData); /* メモリ領域へのアクセスを有効にする */ ucData = 0x55; /* 初期化 */

/*メモリオフセット 0100h に 55h を出力 */ UioPokeByte( pMem, 0x0100, ucData);

(30)

第三章 ボードを制御するプログラムの作成 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 関数の中に記述します。

(31)

第三章 ボードを制御するプログラムの作成 サンプルプログラム uioint.cの割り込みルーチンのコードの変更例:DO ボードにおいて割り 込み発生時に OUT1 を 1 にする。gulData では DO ボードのベースアド レスが渡されているものとする) ※このプログラムでは割り込みの共有について考慮されていません。 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 /* ******************************** */ /* 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); /* ********************** */ 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; }  割り込み要因の取得  当ボードで必要な処理)  割り込みフラグの解除  該当ボードで必要な処理)  OUT1 に 1 を出力(任意の処理)

(32)

第三章 ボードを制御するプログラムの作成

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 関数を実行します。

(33)

第三章 ボードを制御するプログラムの作成

(3)割り込み処理が必要なくなったらUioReleaseIsr 関数で割り込み処理の登録を削除します。 UioReleaseIsr関数

long UioReleaseIsr( unsigned char Irq );

Irq 割り込み番号(IRQ) 戻り値 エラー識別子 弊社 PCI ボード、CompactPCI ボードでは、電源投入時の初期化状態では、割り込みがマスクされ ている(無効になっている)ことがあり、その場合、実際の処理では使用する割り込みのマスク をUioOutpByte 関数などを使って、事前に解除しておく処理が必要になります。詳細は各ボード の I/O 公開資料をご覧ください。 サンプルプログラム BPL-0804の割り込み関数を使ったプログラム:PCI-2726C で割り込 み発生を待つプログラム 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 #include “fbiuio.h” #include <error.h> int main(void) { int ret;

unsigned short bus; PCI_CONFIG PciData; unsigned int nIoAdr; unsigned char Irq; long lTimeout = 5000; void *pReg;

char *pErr; ret = UioOpen(); if (ret) return -1;

UioGetConfigRegEx(1, 0x1147, 2726, 0x1147, 0x0001, &bus, &PciData); nIoAdr = PciData.BaseAddresses[0] & 0xFFFC;

Irq = PciData.InterruptLine;

UioRequestRegion( &pReg, nIoAdr, 0x0F); /* I/O 領域の予約 */

UioOutpByte(nIoAdr + 0x0D, 0x02); /* bit1(IN2)の割り込みマスクの解除 */ ret = UioRequestIsr( Irq, nIoAdr); /* 割り込み処理の登録 */

(34)

第三章 ボードを制御するプログラムの作成 36 37 38 39 40 41 42 UioOutpByte(nIoAdr + 0x0D, 0x00); /* 全ての割り込みをマスク */ ret = UioReleaseIsr(Irq); /* 割り込み処理の解除 */ UioReleaseRegion(pReg); /* I/O 領域の解放 */ 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 行)。

(35)

第三章 ボードを制御するプログラムの作成

PCI

コンフィグレーションレジスタへの書き込み

弊社 PCI-ISA、PCI-C(98)などのバスブリッジに使用される PCI-8571 では、拡張ユニットの ISA バ ス、C バスに実装されるボードの I/O ポート領域、メモリ領域を PCI コンフィグレーション空間 の特定のレジスタに設定する必要があります。このようにボードのコンフィグレーションレジス タに書き込みをしたい場合には、Linux 汎用入出力ライブラリ BPL-0804 のUioSetConfigReg 関数 を使用します。 ※PCI-PCI バスブリッジの場合は、拡張ユニットに実装したボードをパソコンに PCI ボードを直接 実装した場合と同様に、特に意識することなく制御することができます。 UioSetConfigReg関数 long unsigned long unsigned short unsigned short unsigned short unsigned short unsigned char unsigned char unsigned long ulIndex, ven_id, dev_id, subven_id, subsys_id, offset, write_data_size, 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 書き込みを行うデータ 戻り値 エラー識別子

(36)

第三章 ボードを制御するプログラムの作成 ●PCI-8571 を使ったバスブリッジの設定方法 (1)使用する I/O ポート領域、メモリ領域の先頭アドレスと終了アドレスをそれぞれ設定します。 (PCIコンフィグレーションレジスタ:40h∼4Bh) (2)指定した領域を有効にします。(PCI コンフィグレーションレジスタ:4Ch∼4Dh) (3)レガシーバスのリセット信号を無効にし、レガシーバスのウェイト数を設定します。(PCI コンフィグレーションレジスタ:4Eh) サンプルプログラム PCI-8571を使ったバスブリッジで I/O ポート 0280h∼029Fh を使用し たい場合 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 “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 設定値はアドレスのビット 9∼ビット 4。ビット 3∼ビット 0 は 0000b になります。 ※6 設定値はアドレスのビット 9∼ビット 4。ビット 3∼ビット 0 は 1111b になります。

(37)

第四章 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の設定とそのシグナルが発生した時に呼び出されるコールバック関数を 作ること。 図 4-1  プログラミング内容のイメージ※9 (1)画面を作る (2)シグナルとコールバック関数の設定 コールバック関数を呼び出し、 次の処理を実行 たとえばボタンがク リック(シグナル発 生)されたら

(38)

第四章 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)終了 サンプルプログラム GTK+用 GUI アプリケーションの雛形 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 #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);

(39)

第四章 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

この「×」マークを押すと、ウィンドウ が閉じ、プログラムが終了する。

(40)

第四章 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);

戻り値 トグルボタンのハンドラ

このほかのボタンとして、チェックボタン、ラジオボタンがあります。チェックボタンはトグル ボタンと使い方は同じですが、表示が「ボタンが押された・押されていない」から「チェックあ り・なし」に変わったものです。ラジオボタンは複数のチェックボタンをグループ化して、その 中の一つのボタンだけがチェックされた状態になるような処理を行います。

(41)

第四章 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)ウィンドウにウィジェットを追加する

(42)

第四章 GTK+用 GUI アプリケーションの作成

(4)ウィジェットを表示する gtk_widget_show関数

void gtk_widget_show(GtkWidget *widget);

widget ウィジェット名。 (5)シグナルの登録 シグナルの登録には、gtk_signal_connect 関数を使用します。 gtk_signal_connect関数 guint gtk_signal_connect(

GtkObject *object, const gchar *name, GtkSignalFunc func, gpointer func_data);

object シグナルが発生するウィジェットの指定。      GTK_OBJECT でキャストする。 name シグナル名 func コールバック関数名。GTK_SIGNAL_FUNC でキャストする。 func_data コールバック関数の引数にわたるデータ 戻り値 将来参照用の識別子 ※コールバック関数のプロトタイプはシグナルによって異なります。

(43)

第四章 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_

handler_id

gtk_timeout_add関数で取得した周期実行している関数のハンドラ

使用例:

メモリンク用 Linux ソフトウェア GPG-4910 添付のユーティリティ xmledit の callbacks.c では、メ モリ領域の状態を更新するために gtk_timeout_add 関数を使用しています。

      図 4-3 メモリエディタユーティリティ

参照

関連したドキュメント

   (1)  取扱説明書、 仕様書、 弊社製品カタログなどに記載された以外の不当な条件、 環境、 取り扱い、 使用方法による場合   

Key words: local area polishing, pressure-controlled, repulsive magnetic force, surface profile, pad shape.. の形状 を崩 さな

攻撃者は安定して攻撃を成功させるためにメモリ空間 の固定領域に配置された ROPgadget コードを用いようとす る.2.4 節で示した ASLR が機能している場合は困難とな

Linux Foundation とハーバード大学による CensusⅡプロジェクトの予備的レポート ~アプリケーシ ョンに最も利用されている

青色域までの波長域拡大は,GaN 基板の利用し,ELOG によって欠陥密度を低減化すること で達成された.しかしながら,波長 470

であり、最終的にどのような被害に繋がるか(どのようなウイルスに追加で感染させられる

ピアノの学習を取り入れる際に必ず提起される

・カメラには、日付 / 時刻などの設定を保持するためのリチ ウム充電池が内蔵されています。カメラにバッテリーを入