...

Ver. 1.6 - インタフェース

by user

on
Category: Documents
40

views

Report

Comments

Transcript

Ver. 1.6 - インタフェース
RTLinuxによる
PCI/CompactPCI/CardBus制御入門書(導入編)
RTLinuxによる
PCI/CompactPCI/CardBus制御入門書(導入編)
TUT-0036
www.interface.co.jp
Ver. 1.6
改訂履歴
Ver.
1.0
1.1
年 月
改 訂 内 容
2002年 3月
2002年 6月
1.2
2003年 2月
1.3
2003年 5月
1.4
2004年 1月
1.5
2004年 8月
1.6
2005年 10月
新規作成
・パフォーマンス比較資料追加
・RTLinuxプログラミング追加
・誤記修正
・URL更新
・インストールに関する説明の追加
・URL更新
・インストールに関する説明の追加
・CardBus追加
・URL,インストールに関する説明の更新
・表1-3 RTLinuxとLinuxの周期実行測定結果 指定
周期の修正
・技術資料一覧更新
・誤記修正
・URL更新
・技術資料一覧更新
本チュートリアルをご使用の際は、必ず各製品型式の最新のドキュメント(ユーザ
ーズマニュアル,オンラインヘルプ)をあわせて参照してください。また、最新のド
ライバソフトウェアをご使用ください。ユーザーズマニュアル, ドライバソフト
ウェアは弊社Web siteからダウンロードできます。(オンラインヘルプはドライバ
ソフトウェアに含まれています)
Interface Corporation
-1-
商標/登録商標
本チュートリアルに掲載されている会社名、製品名は、それぞれ各社の商標また
は登録商標です。
保障の内容と制限
株式会社インタフェースはドキュメント内の情報の正確さに万全を期しています。
万一、誤記または誤植などがあった場合、株式会社インタフェースは予告無く改
訂する場合があります。ドキュメントまたはドキュメント内の情報に起因するい
かなる損害に対しても株式会社インタフェースは責任を負いません。
ドキュメント内の図や表は説明のためであり、ユーザ個別の応用事例により変化
する場合があります。
著作権、知的所有権
株式会社インタフェースは本製品に含まれるおよび本製品に対する権利や知的所
有権を保持しています。
本製品はコンピュータ ソフトウェア(プログラム)、 図、 文章、 写真などを
含んでいます。
複製の禁止
株式会社インタフェースの許可なく、本製品(ドキュメント含む)の全て、または一
部に関わらず、複製、改変などを行うことはできません。
責任の制限
株式会社インタフェースは、株式会社インタフェース または再販売者の予見の有
無にかかわらず発生したいかなる特別損害、偶発的損害、間接的な損害、重大な
損害について、責任を負いません。
Interface Corporation
-2-
−目 次−
はじめに
6
第 1 章 RTLinux の導入
7
1.1 RTLinux とは(概要)....................................................................................7
1.2 Linux と RTLinux との違い ............................................................................9
1.3 パフォーマンス比較 .....................................................................................13
1.3.1 DIO ボードのパフォーマンス比較...................................................13
応答性のパフォーマンス比較 ...............................................................13
周期性のパフォーマンス比較 ...............................................................14
1.3.2 調歩同期シリアル通信ボードのパフォーマンス比較 ...................14
応答性のパフォーマンス比較 ...............................................................15
周期性のパフォーマンス比較 ...............................................................15
1.4 RTLinux 導入のメリット............................................................................16
第 2 章 RTLinux のインストール
17
2.1 RTLinux,Linux カーネルソースの入手(ダウンロード).....................17
2.2 作業の前に .....................................................................................................18
2.3 カーネルへのパッチあて作業 .....................................................................19
2.4 Linux カーネルイメージの構築...................................................................20
2.5 カーネルイメージを起動するローダの設定..............................................22
2.6 RTLinux のパッチをあてた Linux の起動 ..................................................23
2.7 RTLinux のコンパイル..................................................................................25
2.8 RTLinux のディレクトリ構成......................................................................28
2.9 RTLinux サンプルプログラムの紹介..........................................................30
第 3 章 初歩の RTLinux プログラミング
32
3.1 プログラミングの前に(RTLinux リアルタイムカーネルの組み込み)....32
用語解説 ..........................................................................................................34
3.2 Hello World プログラム ................................................................................35
3.3 Hello World プログラムの解説 ....................................................................38
3.4 組み込み中にも実行されるプログラムを作る..........................................39
3.5 組み込み中にも実行されるプログラムの解説..........................................41
関数&用語解説 ...............................................................................................45
3.6 Linux プロセスから RTLinux モジュールを制御する ..............................47
Interface Corporation
-3-
3.7 Linux プロセスから RTLinux モジュールを制御するプログラムの解説54
3.7.1 RT-FIFO の役割...................................................................................55
3.7.2 共通定義ファイルの役割...................................................................56
3.7.3 RTLinux モジュールの動き ...............................................................58
関数解説 ...................................................................................................62
3.7.4 Linux プロセスの動き ........................................................................62
関数&用語解説 .......................................................................................65
第 4 章 弊社 RTLinux 用ソフトウェアの導入
68
4.1 RTLinux 対応ソフトウェアの特長..............................................................68
4.2 RTLinux 対応ソフトウェアのインストール ..............................................69
4.3 テストドライバを使用した動作確認 .........................................................76
4.4 RTLinux 対応ソフトウェアのアンインストール ......................................77
第 5 章 ドライバモジュールの優先度設定
78
5.1 割り込みハンドラの優先度設定(DPG-0102) ........................................78
第 6 章 RTLinux でのソフトウェア開発
82
6.1 RTLinux プログラムのデバッグ..................................................................82
6.1.1 rtl_printf( ) + 弊社デバイスドライバのデバッグ機能を使用した方法
..........................................................................................................................82
6.1.2 デバッガ(gdb + RTDebugger)を使用する方法 ............................84
6.2 リアルタイム性の評価 .................................................................................90
6.3 I/O 公開資料(PDF)の利用........................................................................93
第 7 章 組み込み Linux 概要
94
7.1 組込み Linux 概要..........................................................................................94
第 8 章 補足資料
96
8.1 インストールに関する参考情報 .................................................................96
RTLinux 3.2 pre1 の導入について .........................................................96
RTLinux 3.2 pre2 の導入について .........................................................97
Red Hat Linux 7.3/8.0 に RTLinux を導入する際の注意点 ..................98
8.2 その他の Tips .................................................................................................99
insmod 等のコマンドが呼び出せない...................................................99
RTLinux リアルタイムカーネルを組み込もうとするとエラー ........99
ドライバを insmod しようとすると unresolved symbol ....................100
Interface Corporation
-4-
技術資料紹介
101
参考文献
102
Interface Corporation
-5-
はじめに
平素は格別のご高配を賜り、厚くお礼申し上げます。本冊子はRTLinux上で弊社
PCI/CompactPCI/CardBus製品を制御したい方を対象に、RTLinuxの環境構築、弊社
RTLinux対応ソフトウェアのセットアップ、テストドライバによる動作確認方法、
組み込みシステムに使用されるリアルタイムOSについて記載しています。
RTLinux上での弊社製品をはじめとするハードウェア制御のためのプログラミン
グにお役に立てれば幸いです。
<ご意見・ご要望>
弊社へのご意見,ご要望がございましたら、下記までお問い合わせください。
www.interface.co.jp
E-mail:[email protected]
<注意事項>
本冊子はRTLinuxバージョン3.1を対象に作成されています。
使用されるRTLinuxのバージョンが異なる場合、動作保証はいたしかねますので予
めご了承ください。
本冊子は、コマンドの実行例において、行頭に「%」がつく場合は一般ユーザで
の実行、「#」がつく場合はrootでの実行を意味します。「%」や「#」は実際に入
力する文字ではありませんのでご注意ください。
Interface Corporation
-6-
第1章 RTLinuxの導入
1.1 RTLinuxとは(概要)
RTLinux(RealTime Linux)とは、その名前が示しているように、Linuxでリアルタイ
ム処理を可能にするOSです。
RTLinux/FreeはFinite State Machine Labs, Inc.(以降、FSMLabs社と記載します)のWeb
siteから、Freeで入手することが可能です。本書では、以下特に記載がない限り
「RTLinux」は「RTLinux/Free」のことを指します。
ライセンスに関する詳細な内容については、FSMLabs社のWeb siteもしくはRTLinux
3.1のパッケージに付属するドキュメントをご確認ください。
それでは、リアルタイム処理とはどのようなものなのでしょうか?
「リアルタイム」という言葉には、実時間,同時,即時 等の意味があります。
コンピュータでの処理は基本的にCPUのクロック周波数で時間を離散化し、そのクロ
ックにあわせて命令(処理)を実行していますので、現実の実時間ではなくCPUクロ
ックが刻む時間にあわせて処理を行っていると言えます。
1つの処理のみを実行する場合は、ハードウェアの処理能力=処理の実行時間と言う関
係が成り立つため、処理が完了するまでにかかる時間を予測することが可能になりま
す。
しかし、メインとなる処理の他にも、画面表示や通信等の処理を同時に行いたい場合
には、複数実行している処理の内どれを優先的に行うのかが設定できなければ、実行
時間を予測することができません。
一般的に、リアルタイムOSとは、下記のような要項を満たすOSを示します。
・規定の時間間隔内での周期実行性が保証されていること。
・割り込みの応答速度が規定時間内で保証されていること。
加えて、弊社RTLinux対応デバイスドライバ(GPGシリーズ)では、下記の要項をリ
アルタイム保証として挙げています。
・ドライバAPIの実行時間のワースト値を保証。
・API実行中の割り込み禁止時間のワースト値を保証。
(詳細な値については、各ドライバのHelpをご確認ください。)
Interface Corporation
-7-
RTLinuxは、厳密には単体で機能するOSそのものではなく、Linuxカーネルに適用する
パッチとして提供されています。
RTLinuxのパッチを適用したカーネルを実行すると、リアルタイムカーネルが最下層
で動作します。
このリアルタイムカーネルがLinuxカーネル本体やRTLinuxモジュールと内部で動作
するRTLinuxスレッドと呼ばれるRTLinux専用のスレッド(実行単位)をスケジューリン
グすることで、任意の処理をリアルタイム制御することが可能になります。(図1-1
参照)
Linux プロセス
RT-FIFO
スケジューラ
RTLinux モジュール
Linux カーネル
RTLinux スレッド
割り込みの
ディスパッチ
スケジューラ
リアルタイムカーネル
ハードウェア割り込み
図 1-1 RTLinuxの概要
リアルタイムカーネルから見ると、Linuxカーネル本体はRTLinuxモジュール(および内
部で実行されるRTLinuxスレッド)より優先度の低いプロセスとして動作するため、リ
アルタイムで処理を行いたい作業をRTLinuxスレッドに記述することで、通常のLinux
とリアルタイム処理を共存させることを可能にしています。
通常のLinuxで使用可能な機能やアプリケーションは、RTLinux上でも同様に動作する
ため、Linuxの豊富な機能を生かしつつリアルタイム処理を行える点が特長と言えます。
また、RTLinuxのもう一つの機能として、割り込みのディスパッチがあります。
RTLinuxでは、ハードウェアからの割り込みを受けた場合にそのままLinuxカーネルに
伝えずに、リアルタイムカーネルが一度割り込みを受けてからLinuxカーネル本体に伝
えます。
Interface Corporation
-8-
Linuxカーネル本体ではスケジューリング間隔が10ms程度であるため、割り込みを受
けてからISR(Interrupt Service Routine)を実行するまでに600µs∼20ms程度かかり、ば
らつきがある上に応答性能もかなり低いといえます。
これに対して、RTLinux下で割り込み処理を実行すれば、15μs程度で応答することが
可能になります。
★スレッド
プログラム実行の、ある最小単位です。
文脈次第では、タスクと呼ばれることもあります。
Linux や Windows 等のマルチタスク OS では、これら複数のスレッドを時分割に実行させ、
並列して動作するように見せかけています。
(MS-DOS は、基本的に 1 つのタスクしか動作できないのでシングルタスク OS と呼ばれま
す)
本書では、RTLinux モジュール内で動作するスレッドのことを、特に RTLinux スレッドと
呼んでいます。
複数のスレッドを同時に動作させる状態を、マルチスレッドと呼びます。
極端な例えですが、C 言語の main 関数が、幾つも同時に動いているのだと思ってくださ
い。
1.2 LinuxとRTLinuxとの違い
先に示した説明を元に、Linuxの構造とRTLinuxの構造を比較し、違いを見ていきます。
まず、Linuxでのユーザアプリケーションとデバイスドライバとの関係を図1-2に示し
ます。
アプリケーション
ライブラリ
デバイスドライバ
ユーザ空間
カーネル空間
PCI/CompactPCI ボード
CardBus カード
図 1-2 Linuxでのアプリケーションとデバイスドライバとの関係
Interface Corporation
-9-
項目
アプリケーション
ライブラリ
デバイスドライバ
PCI/CompactPCIボード
CardBusカード
ユーザ空間と
カーネル空間
内容
お客様が作られるプログラムを示します。
インタフェースボードを簡単に制御できるよう、アプリ
ケーションに対して公開されているAPIを提供している
ソフトウェアです。
弊社製品GPG-2000を例にすると、共有ライブラリ
libgpg2000.soがこれにあたります。(Windowsに詳しい方
は、DLLファイルを想定してください)
実際にインタフェースボードにアクセスし、ボードの制
御を行うソフトウェアです。
弊社製品GPG-2000を例にすると、ドライバcp2000.oがこ
れにあたります。(Windowsに詳しい方は、VxDやSysファ
イルを想定してください)
インタフェースボードです。
お客様は、このインタフェースボードを使って、何らか
の制御を行うことを目的としています。
manやvi等、通常のアプリケーションは、ユーザ空間と呼
ばれるアドレス空間で実行されます。
ハードウェアに関わる処理、例えばカーネルやドライバ
等と呼ばれるものは、カーネル空間で実行されます。
両者の違いを、プログラムの制限事項から捉えると、
・ユーザ空間のプログラムは、できる内容に制限を加えた
上で、プログラムを安全に動かすことができます。
・カーネル空間のプログラムは、何でもできる代わりに、
一つ間違えると(例えばポインタを書き間違えるとか)ハ
ングアップしてしまいます。
と捉えることができます。
お客様の作られるソフトウェアは、常にユーザ空間にて実行されます。このため、プ
ログラムが暴走しても、別のコンソールから、そのプロセスをkillして復旧させること
が簡単にできます。
その代わり、お客様の作られるアプリケーションは、ボードを直接制御することがで
きない等の、幾つか制限を受けることになります。
このため、通常ライブラリを経由して、インタフェースボードを制御します。
Interface Corporation
- 10 -
次に、RTLinuxでのユーザアプリケーションとデバイスドライバとの関係を図1-3
に示します。(先の図 と比較してみてください)
アプリケーション
RTLinux モジュール
ユーザ空間
カーネル空間
デバイスドライバ
PCI/CompactPCI ボード
CardBus カード
図 1-3 RTLinuxでのアプリケーションとデバイスドライバとの関係
項目
アプリケーション
RTLinuxモジュール
デバイスドライバ
PCI/CompactPCIボード
CardBusカード
内容
お客様が作られるプログラムを示します。
お客様がカーネル空間で実行させるソフトウェアです。
この空間で実行されるソフトウェアは、リアルタイム性が
確保されています。
実際にインタフェースボードにアクセスし、ボードの制御
を行うソフトウェアです。Linux版のライブラリとデバイ
スドライバが合わさったものと考えてください。
弊社製品GPG-2000を例にすると、rcp2000.oがこれにあた
ります。
なお、デバイスドライバ、RTLinuxモジュール共、RTLinux
のリアルタイム管理下にて動作します。
インタフェースボードです。
お客様は、このインタフェースボードを使って、何らかの
制御を行うことを目的としています。
お客様の作られるソフトウェアは、ユーザ空間で動作するアプリケーションと、カー
ネル空間で動作するRTLinuxモジュールを、実行可能です。
プログラミングスタイルとしては、リアルタイム性を確保したいクリティカルな制御
場面ではRTLinuxモジュール内で処理を行い、回収したデータの画面表示等、リアル
タイム性を要求されない場面では、アプリケーションにて処理を行います。
Interface Corporation
- 11 -
データ表示など、リアルタイム性を要
求しない処理を行う
アプリケーション
タイムクリティカルな処理を行う
RTLinux モジュール
RTLinux環境下での、Linuxとの大きな違いを、以下に列挙します。
・ユーザのRTLinuxモジュールは、カーネル空間に配置されます。
このため、Linuxではカーネル空間からユーザ空間へのスイッチ時に発生して
いた時間的なロスがありません。
・ユーザのRTLinuxモジュールとアプリケーションとの間には、RT-FIFOと呼ばれ
る情報交換機能が提供されており、両者を並行して非同期に動作させることが
できます。
・RTLinuxのAPIは、ns(ナノ秒)単位で指定できます。
つまり、RTLinuxスレッドの周期実行時間や、ウェイトの呼び出しを、ns(ナノ
秒)単位で指定することが可能です。
・Linuxの割込みおよびカーネル処理は、RTLinuxの制御下に置かれています。
ハードウェア割込みは、即座に割込みハンドラに遷移することができます。
使用するCPUにも依りますが、数∼十数μsで割込みハンドラが起動します。
このように、RTLinuxは通常のLinuxに比べ、応答要求の厳しいプログラミング環境に
おいて、確実かつ応答性の高いシステムを構築することが可能です。
★Linux と RTLinux の内部の違い
Linux のカーネルは、ノンプリエンプティブです。(ユーザ空間の実行プロセスは、プリエ
ンプティブです)
また、割り込み処理について、元々リアルタイム処理を考慮した設計にはなっていません。
ノンプリエンプティブなため、カーネルコール中に、他のプロセスに実行権を奪われるこ
とはありません。割り込み処理も、リアルタイム OS ならば、割り込み処理中に、より優
先度の高い事象が発生した時、プリエンプトされますが、こういったことはありません。
結果として、プロセスの実行時に予測不可能な遅延が発生する可能性があります。
このことは、事象の変化に対して、要求された時間内で応答しなければならないリアルタ
イム処理を実現する上で、大きな妨げとなります。
対して、RTLinux は、割り込み処理はプリエンプトされます。
このため、RTLinux では安定した周期実行と、上に示した高速な割り込み応答を実現して
います。
Interface Corporation
- 12 -
1.3 パフォーマンス比較
ここでは、RTLinuxとLinuxで、応答性や周期性について、弊社で測定したパフォーマ
ンスデータについて、一部ご紹介します。
詳細なパフォーマンスデータについては、弊社お客様相談センタまで、お問い合わせ
ください。
1.3.1 DIOボードのパフォーマンス比較
まずは、DIOボードでの応答性と周期性のパフォーマンス比較データを紹介します。
測定環境は次の通りです。
表 1-1 パフォーマンス測定環境
項目
内容
GPG-2000
CTP-PE09
CTP-2703
2.4.4
RTLinux 3.1
デバイスドライバ
CPUボード
DIOボード
Linuxカーネルバージョン
RTLinux バージョン
応答性のパフォーマンス比較
汎用入力信号IN1の割り込みが発生してから、コールバック関数内ですぐにデジタル
出力関数を呼び出した場合の応答時間を測定しました。
RTLinux、Linuxともに、1000回応答時間を測定しています。
コールバック関数呼び出し
表 1-2 応答時間のトータル結果
測定環境
デジタル出力処理
RTLinux
Linux
9.6
18.8
9.4
0.48
17.3
36.3
16.7
0.92
トータル結果
汎用入力信号
IN1 割り込み
平均(μs)
最大(μs)
最小(μs)
標準偏差(σ)
コールバック関数
デジタル出力
時間
この時間を測定
図1-4 応答性の測定
RTLinuxは、Linuxに比べ平均,最大,最小時間共、優れた結果が出ています。
特に、最大応答時間では、Linuxで36.3μsにまで応答時間のぶれが発生しているのに
対し、RTLinuxでは、18.8μsまでしかぶれが発生していません。
Interface Corporation
- 13 -
周期性のパフォーマンス比較
指定した周期でデジタル信号出力を繰り返し行い、
その周期性のぶれを測定しました。
こちらも1000回ずつ測定を行っています。
Linuxでは1ms周期を実行しても20msより短い周期実行が行えなかったため、100ms周期に
出力を行う設定で測定しています。
RTLinuxは、1ms周期でも安定した動作が確認できたため、1ms周期の周期性を測定しま
した。
表 1-3 RTLinuxとLinuxの周期実行性測定結果
RTLinux
Linux
測定環境
指定
周期(μs)
平均
(μs)
最大
(μs)
最小
(μs)
100000 98434.42 98439.98 98431.76
10000 9844.188 9847.56 9839.34
1000 971.8
975.57
967.2
標準
偏差
(σ)
1.794
1.757
0.944
平均
(μs)
最大
(μs)
最小
(μs)
標準
偏差
(σ)
106808.75 106816.08 104424.12 75.56
19686.99 19729.37 19593.74 0.336
19686.93 19723.89 19599.22 10.708
Linuxでは、指定した周期が100msであるにもかかわらず、平均で7ms程度遅れが出て
います。また、最大値と最小値のぶれ幅も大きいです。
RTLinuxでは、ほぼ指定周期通り実行され、さらに最大値と最小値のぶれも小さくな
っています。
1.3.2 調歩同期シリアル通信ボードのパフォーマンス比較
次に、調歩同期シリアル通信ボードでの応答性と周期性のパフォーマンス比較データ
を紹介します。
測定環境は次の通りです。
表 1-4 パフォーマンス測定環境
項目
デバイスドライバ
CPUボード
調歩同期シリアル通信ボード
Linuxカーネルバージョン
RTLinux バージョン
Interface Corporation
内容
GPG-4141
CTP-PE09
CTP-4142
2.4.4
RTLinux 3.1
- 14 -
応答性のパフォーマンス比較
データを受信してから、コールバック関数内ですぐにデータ送信関数を呼び出した場
合、データ受信完了から、実際にデータが送信されるまでの時間を測定しました。
RTLinux、Linuxともに、1000回応答時間を測定しています。
表 1-5 応答時間のトータル結果
コールバック関数呼び出し
測定環境
データ送信開始
受信完了
RTLinux
Linux
46.957
50
45
0.760085
5089.048
10070
80
2883.494
トータル結果
平均(μs)
最大(μs)
最小(μs)
標準偏差(σ)
データ受信
コールバック関数
データ送信
この時間を測定
図 1-5 応答性を測定した時間
RTLinuxは、Linuxに比べ平均,最大,最小時間共、優れた結果が出ています。
特に最大応答時間では、負荷が入った場合、Linuxでは、10msにまで応答時間のぶれ
が発生しているのに対し、RTLinuxでは、50μsまでしかぶれが発生していません。
周期性のパフォーマンス比較
指定した周期でデータ送信を繰り返し行い、その周期性のぶれや限界値を測定しまし
た。
こちらも各周期で1000回ずつ測定を行っています。
表 1-6 RTLinuxとLinuxの周期実行性測定結果
ネットワーク負荷なし
測定環境
RTLinux
Linux
平均
最大
最小
標準偏差
平均
最大
最小
標準偏差
10001.09
1000.11
10005
1004
9997
996
1.15379
1.19387
10001.26
10001.26
10061
10071
9943
9935
5.241171
4.4672
指定周期
10000
1000
Interface Corporation
- 15 -
ネットワーク負荷あり
RTLinux
測定環境
Linux
平均
最大
最小
標準偏差
平均
最大
最小
標準偏差
10001.09
1000.108
10007
1005
9995
996
1.36563
1.183104
10001.22
10001.22
10939
11081
9051
8938
56.60038
50.56933
指定周期
10000
1000
Linuxでは1ms周期を実行しても10ms以下の周期実行は行えておらず、最大値と最小値のぶ
れも大きくなっていますが、RTLinuxでは、最大値と最小値のぶれも小さくなっています。
またネットワーク負荷をかけたとき、Linuxではデータばらつきが10倍に増えましたが、
RTLinuxではほとんど増えていません。
1.4 RTLinux導入のメリット
RTLinuxを導入するメリットとしては、以下のようなことが挙げられます。
★ Linuxの機能,アプリケーションをそのまま使用することが可能。
(RTLinuxモジュールは別途作成する必要があります)
★ ソースコードがオープンになっており、自由に参照(改造)することが可能。
★ 市販のリアルタイムOSに比べて安価(無償)に入手可能。
通常、市販のリアルタイムOSを使用する場合には、高いライセンス料を必要とする場
合がほとんどです。RTLinuxでは、Linuxカーネルはいうまでもなく、RTLinux自体も
無償で提供されていることが大きなメリットとなります。
また、Linux環境で使用可能なツールは、基本的に全てRTLinuxでも使用することが可
能なため、Linuxの資産をそのまま流用して開発を行うことが可能な点もメリットとし
て挙げられます。但し、Linux用のアプリケーション,ドライバは優先度の低いLinux
カーネル上で動作するため、リアルタイム処理は行われません。
また、組み込み環境で使用するOSに市販のリアルタイムOSを選択した場合には、開
発用のホスト環境にターゲットのOSと異なるOSを使用することとなります。
これらの開発環境を用意することが、さらにコストを押し上げる結果となります。
RTLinuxを組み込み用のOSとして選択した場合、開発用のホスト環境とターゲットに
同じRTLinuxを使用することができます。
※ 組み込み環境に関しては、『第7章 組み込みLinux』で解説します。
Interface Corporation
- 16 -
第2章 RTLinuxのインストール
『1.1 RTLinuxとは(概要)』でも紹介した様に、RTLinuxは通常のLinuxカーネルのさ
らに下層に構築されます。そのためRTLinuxを導入する際には、Linuxカーネルのソー
スにRTLinuxのパッチを適用してから、Linuxカーネルの再構築(コンパイル)を行う
必要があります。
「難しそう!」と思われるかも知れませんが、実際の作業は定型的なもので、それほ
ど難しくはありません。
ここでは、実際にRTLinuxのインストールを順に説明していきます。
手順に沿って進めていけば、RTLinuxのインストールが意外と簡単なことに気付くこ
とでしょう。
2.1 RTLinux,Linuxカーネルソースの入手(ダウンロード)
RTLinuxは下記のWeb siteから入手することができます。(2005年10月現在)
RTLinuxの公式Web site(FSMLabs社のWeb site)
米国Web site http://www.fsmlabs.com/
日本Web site http://www.fsmlabs.co.jp/
RTLinuxのダウンロード
http://www.rtlinuxfree.com
まずここで、パッチ用のファイルrtlinux-3.1.tar.gz(またはrtlinux-3.1.tar.bz2)と、ドキュ
メントrtldoc-3.1.tar.gz(またはrtldoc-3.1.tar.bz2)をダウンロードします。
(2004年1月現在、RTLinux 3.2 pre2がFSMLabsから公開されています。これらの情報に
ついては、『第8章 補足資料』をご覧ください。)
また、RTLinuxのパッチを適用するLinuxカーネルのソースを用意する必要があります。
下記のWeb siteからオリジナルのカーネルソースをダウンロードしてください。
Linuxカーネルのダウンロード
http://www.kernel.org/
Interface Corporation
- 17 -
本書ではRTLinux 3.1が対応しているカーネルバージョン2.4.4を使用して解説を行い
ます。
(2005年10月現在で、RTLinux 3.1が対応しているLinuxのカーネルバージョンは、2.2
系では2.2.19、2.4系では2.4.4となっています。)
以降の説明では、以下の2つのファイルを基に説明しております。
ファイル名
linux-2.4.4.tar.gz
rtlinux-3.1.tar.gz または
rtlinux-3.1.tar.bz2
項目
Linuxのカーネルソースのアーカイブファイル
RTLinuxのパッチソースのアーカイブファイル
★参考情報
本章の説明時に用いたコンピュータならびにディストリビューションのスペックを紹介
します。
コンピュータ:エプソンダイレクト MT-3500
ディストリビューション:VineLinux 2.1.5
2.2 作業の前に
ここからの作業は、OS本体であるカーネル部分に対する修正が入ります。
万が一のために、必ず起動ディスクを作成してから作業を進めてください。
起動ディスクは、mkbootdiskコマンドを使って作成します。
以下に例を示します。
(カーネルのバージョンはunameコマンドで簡単に調べることができます)
# uname –r
← カーネルのバージョンをチェックしています
2.4.7-10
# mkbootdisk 2.4.7-10
← カーネルのバージョンを指定します
Insert a disk in /dev/fd0. Any Information on the disk …
また、ここからの作業は、コンパイラやリンカ等の開発ソフトウェアが必須となりま
す。
例えば、コンソール画面で、「gcc」と入力した時、「command not found」とプログラ
ムが見つからない旨のメッセージが表示されたら、お手持ちのLinuxに対して、開発環
境をインストールしてから作業を進めてください。
(Red Hat等のディストリビューションが用意しているCD-ROMならば、開発環境をイ
ンストールするオプション設定が用意されています)
もう一つ。以降の作業を進めるには、スーパーユーザである必要があります。
suコマンド等でスーパーユーザになって作業を進めてください。
% su
Password: ----- ← root のパスワードを入力します。
Interface Corporation
- 18 -
2.3 カーネルへのパッチあて作業
ここからの作業は、元のカーネルソースに影響を及ぼさないよう、既存のカーネルソース
のディレクトリとは別のディレクトリを作成し、そこで作業を進めるようにします。
最近のディストリビューションでは、カーネルのソースは、/usr/srcディレクトリ下に配置
されるので、その下にサブディレクトリ(ここではrtlinux)を作成して、進めます。
まず、/usr/srcディレクトリの下に、rtlinuxディレクトリを作成し、そこに前もってダウン
ロードしておいた2つのファイルをコピーします。
# cd /usr/src
# mkdir rtlinux
# cd rtlinux
# cp /mnt/cdrom/linux-2.4.4.tar.gz . ← CD-ROM から持って来た例です。
# cp /mnt/cdrom/rtlinux-3.1.tar.gz .
次に、コピーした2つのファイルを展開します。
# tar xzf linux-2.4.4.tar.gz
# tar xzf rtlinux-3.1.tar.gz
# ls /usr/src/rtlinux
linux linux-2.4.4.tar.gz rtlinux-3.1 rtlinux-3.1.tar.gz
★tar.bz2 ファイルの展開方法
ファイルの拡張子が tar.bz2 の場合、以下のコマンドオプションでファイルを展開できま
す。
# tar --bzip2 -xvf rtlinux-3.1.tar.bz2
次に、展開したLinuxのソースディレクトリへのシンボリックリンクを張ります。
# cd /usr/src
ln –sf /usr/src/rtlinux/linux /usr/src/linux
※カーネルバージョンによっては、ディレクトリ名が「linux-カーネルバージョン」に
なっている場合があります。
展開後のディレクトリ構成を示します。
圧縮ファイルを展開した後のディレクトリ
/usr
/src
/rtlinux
/linux
← ①linux-2.4.4.tar.gz ファイルの展開後のディレクトリ
linux-2.4.4.tar.gz
/rtlinux-3.1 ← rtlinux-3.1.tar.gz ファイルの展開後のディレクトリ
kernel_patch-2.2.19 ← カーネル 2.2.19 に対応したパッチファイル
kernel_patch-2.4.4 ← カーネル 2.4.4 に対応したパッチファイル
rtlinux-3.1.tar.gz
/linux
← ①に対するシンボリックリンクを張っています。
rtlinux-3.1ディレクトリ直下に、Linuxのカーネルソースに対して、パッチをあてるための
パッチファイルがあります。
Interface Corporation
- 19 -
/usr/src/rtlinuxディレクトリ下に展開したカーネルソース(linux)に対して、RTLinuxのパッチ
をあてます。ソースファイルを展開したディレクトリに移動し、patchコマンドを使ってパ
ッチを適用します。
(下では、カーネル2.4.4に対してパッチをあてています)
# cd /usr/src/rtlinux/linux
# patch –p1 < ../rtlinux-3.1/kernel_patch-2.4.4
…
patching file scripts/mkdep.c
#
これで、Linuxカーネルソースに対するRTLinuxのソースパッチは完了しました。
2.4 Linuxカーネルイメージの構築
Linuxカーネルの構築を行うために、コンフィギュレーションを行います。
カーネルソースのディレクトリに移動して、makeコマンドを実行します。
# cd /usr/src/rtlinux/linux
# make xconfig
X Window用の「Linux Kernel Configration」が起動します。
使用するハードウェア構成に応じた設定を行ってからSave and Exitをクリックすると
「.config」ファイルが生成されます。
(X Window環境がない場合には、「make menuconfig」もしくは「make config」を実行
してください)
★カーネルコンフィギュレーションの注意事項
「make xconfig」の実行時に、サポートするファイルシステムで vfat を選択していなかっ
たために、Windows でフォーマットしたフロッピーディスクが使用できなかったり、ネッ
トワークカードのドライバを正しく設定していないために、ネットワークが使用できない
等のトラブルが発生することがあります。
必要な設定項目をよく吟味してオプション設定を行ってください。
次に、Linuxカーネルを構築します。
カーネルソースのディレクトリに移動して、依存関係のチェックを行います。
# cd /usr/src/rtlinux/linux
# make dep
← 依存性関係のチェック
# make clean
← ソースツリーの準備
Interface Corporation
- 20 -
カーネルイメージを作成します。
# make bzImage
← カーネルの構築
…
Root device is (3, 1)
Boot sector 512 bytes.
Setup is 4528 bytes.
System is 1103 kB
warning: kernel is too big for standalone boot from floppy
#
モジュールの作成、インストールを行います。
# make modules
← モジュールの構築
# make modules_install
← カーネルモジュールのインストール
モジュールの依存関係ファイルを作成します。
# depmod –a
ここまでで、カーネルイメージが以下の生成例に示す、各ディレクトリに生成されま
す。
PC/AT互換機および、CPUボード(PentiumⅢ、Geode)での生成例
/usr
/src
/rtlinux
/linux
/arch
/i386
/boot
bzImage ← カーネルイメージファイル
/lib
/modules
/2.4.4-rtl
← ここに、モジュール群が生成されます
該当ディレクトリに、カーネルイメージ(bzImageファイル)が作成されていることを確認
します。(下は参考です。ファイルサイズは、コンフィギュレーション設定によって異
なります)
# cd /usr/src/rtlinux/linux/arch/i386/boot
# ls –l
・
・
・
-rw-r—r-1 root root 464842 Feb 4 9:49 bzImage
Interface Corporation
- 21 -
2.5 カーネルイメージを起動するローダの設定
OSローダに対し、先ほど作成したカーネルイメージを登録して、起動できるように設
定します。
<grubを使用する場合の設定>
カーネルイメージが配置されている「/boot」に移動し、先ほど作成したカーネルイメ
ージをコピーします。
# cd /boot
# cp /usr/src/rtlinux/linux/arch/i386/boot/bzImage /boot/rtlinuz
「grub.conf」ファイルを以下のように編集します。
# cd /boot/grub
# vi grub.conf
List 2-1 「grub.conf」の修正
1
2
3
4
5
6
7
8
9
10
default=1
timeout=25
splashimage=(hd0,0)/boot/grub/splash.xpm.gz
title linux
root (hd0,0)
kernel /boot/vmlinuz ro root=/dev/hda1
title rtlinux
root (hd0,0)
kernel /boot/rtlinuz ro root=/dev/hda1
↑
↑ルート位置を指定します。6行目を参考に
してください。
カーネルイメージのファイル名を指定します。
<liloを使用する場合の設定>
カーネルイメージが配置されている「/boot」に移動し、先ほど作成したカーネルイメージ
をコピーします。
# cd /boot
# cp /usr/src/rtlinux/linux/arch/i386/boot/bzImage /boot/rtlinuz
「lilo.conf」ファイルを以下のように編集します。
# cd /etc
# vi lilo.conf
Interface Corporation
- 22 -
List 2-2 「lilo.conf」の修正
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
boot=/dev/hda
map=/boot/map
install=/boot/boot.b
prompt
timeout=25
default=rtlinux
image=/boot/vmlinuz
label=linux
root=/dev/hda1
read-only
image=/boot/rtlinuz
label=rtlinux
root=/dev/hda1
い。
read-only
←カーネルイメージファイル名を指定します。
← ルート位置を指定します。10行目を参考にしてくださ
liloコマンドを実行して、設定を更新します。
# /sbin/lilo
2.6 RTLinuxのパッチをあてたLinuxの起動
OSローダの設定が完了したら、再起動します。
# shutdown –r now
ローダが起動したら、先ほど追加した「rtlinux」を選択して起動し、rootでログインします。
login: root
Password: ******(パスワードを入力)
unameコマンドでカーネルバージョンの確認を行ってください。
# uname –r
2.4.4-rtl ← カーネル 2.4.4 + RTLinux 3.1 の場合です
カーネル 2.2.19 の場合は、表示が異なります
Interface Corporation
- 23 -
★カーネルバージョン
uname コマンドで表示されるカーネルバージョンは、どうやって生成されたのでしょう
か?
答えは、Linux カーネルを構築する際に使用される Makefile にあります。
/usr/src/rtlinux/linux ディレクトリに、Makefile があるので、これをエディタで開いてみて
ください。
そこに、以下の表記があります。
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 4
EXTRAVERSION = -rtl
カーネルバージョンは、この定義の組み合わせなのです。
Interface Corporation
- 24 -
2.7 RTLinuxのコンパイル
次に、RTLinuxのコンパイルを行います。
RTLinuxをインストールしたディレクトリに移動して、RTLinuxの設定を行います。
# cd /usr/src/rtlinux/rtlinux-3.1
コンパイルの前に、RTLinux-3.1ディレクトリに対して、Linuxディレクトリへのシン
ボリックリンクを張ります。
# ln –s /usr/src/rtlinux/linux linux
このシンボリックリンクを正確に張らないと、次のmake xconfigが失敗しますので、注
意してください。シンボリックリンクの関係を以下に示します。
シンボリックリンクの設定関係
/usr
/src
/rtlinux
/linux
← ①Linux 2.4.4 のディレクトリ
(前項でコンパイルしたソース類一式がある)
/rtlinux-3.1 ← RTLinux 3.1 のディレクトリ
/linux
← ①に対するシンボリックリンクを張っています
RTLinux用のコンフィギュレーション設定を行います。
# make xconfig
THE OPEN RTLINUX PATENT LICENSE
…
Do you agree to the terms of this license [y/n]?
(make xconfigが使用できない環境では、make config、もしくは make menuconfigを実行
してください)
make xconfigを実行すると、ライセンス説明と同意を求められます。よく読んで、yキ
ーを入力してください。すると、X Window上にRTLinuxのコンパイル時の設定を行う
メニューが表示されます。ここで、必要な項目を設定してから、Save and Exitをクリ
ックして設定を終了します。
参考に、RTLinux 3.1のコンフィギュレーション設定を一覧として示します。
メニューの右側にヘルプボタンがありますので、これらを参考にしながら、設定を行
ってください。
図2-1 設定画面
Interface Corporation
- 25 -
xconfigを実行したディレクトリで続けて、RTLinuxのコンパイルを実行します。
# make
# make devices
# make install
以上でRTLinuxのインストールは完了です。
作成したRTLinuxモジュールを確認することができます。
# cd /usr/src/rtlinux/rtlinux-3.1/modules
# ls
mbuff.o rtl.o rtl_fifo.o rtl_posixio.o rtl_sched.o rtl_time.o
次に、RTLinuxのモジュールをシステムに組み込みます。
以下のようにして、ロード用のスクリプトを実行します。
# cd /usr/src/rtlinux/rtlinux-3.1
# sh scripts/insrtl ← RTLinuxのトップディレクトリで実行してください
下記の方法で、システムに組み込まれたモジュールを確認できます。
<方法1:ログ出力を確認する>
# cat /var/log/messages
…
RTLinux Extensions Loaded (http://www.fsmlabs.com/)
↑RTLinuxのモジュールがロードされている旨のメッセージが表示されています。
rtl 27184 0 [rtl_sched rtl_fifo rtl_posixio rtl_time]
↑RTLinuxのモジュール名が列挙されています。
ログ出力の中に「RTLinux Extensions Loaded…」を確認します。
<方法2:ロードされているモジュールを一覧表示>
# lsmod
Module Size
Used by
rtl_sched 43104 0 (unused)
rtl_fifo 9968 0 (unused)
rtl_posixio
7184
0 [rtl_fifo]
rtl_time 10000 0 [rtl_sched rtl_posixio]
rtl 27184 0 [rtl_sched rtl_fifo rtl_posixio rtl_time]
↑RTLinuxのモジュール名が列挙されています。
一覧表示の中に、「rtl_sched」「rtl_fifo」「rtl_posixio」「rtl_time」「rtl」の5つのモジ
ュール名があることを確認します。
Interface Corporation
- 26 -
モジュールの組み込みのために、何度もコマンドラインから打ち込むのは、結構手間
な作業です。
シェルスクリプトを作って、作業を効率化できます。
vi等のエディタを使い、以下のファイルを作成し、保存します。
#!/bin/sh
# example: RTLinux install module script
cd /usr/src/rtlinux/rtlinux-3.1
sh scripts/insrtl
これをシェルスクリプトとして実行すれば、より簡単にモジュールを組み込むことが
できます。
# sh runrtl.sh ← シェルスクリプト名
あるいは、OSが起動する際に、自動的に組み込むよう設定するのも良いでしょう。
# cd /etc/rc.d/rc3.d
# ln -s ../init.d/rtlinux ./S99rtlinux
上の例は、ランレベル3で起動する時、rtlinuxスクリプトを優先順位99で起動するよう
に、指定しています。
こうすることで、Linuxにてログインする際に、既にRTLinuxカーネルが組み込まれた
状態にすることができます。
Interface Corporation
- 27 -
2.8 RTLinuxのディレクトリ構成
RTLinux 3.1のインストール後のディレクトリ構成は、以下のようになっています。
/rtlinux-3.1
-/debugger/
-/doc/
-/drivers/
-/examples/
-/fifos/
-/include/
-/main/
-/measurement/
-/modules/
-/psc/
-/regression/
-/schedulers/
-/scripts/
-/semaphores/
-/system/
-/tracer/
- kernel_patch-2.4.0-test1
- kernel_patch-2.4.4
- kernel_patch-2.2.19
- FAQ.pdf
- Rules.make
- Installation.txt
- CREDITS
- Makefile
- PATENT
- README
- RELEASENOTE
- UPGRADING
- rtl.config
- rtl.mk
RTLinux用のデバッガのディレクトリ
RTLinuxのドキュメントディレクトリ
ドライバのディレクトリ
サンプルプログラムのディレクトリ
RT-FIFOのディレクトリ
インクルードファイルのディレクトリ
RTLinuxリアルタイムカーネルが生成されるディレクトリ
リアルタイムスケジューラのディレクトリ
スクリプトのディレクトリ
セマフォモジュールのディレクトリ
トレーサのディレクトリ
カーネル2.4.0用の(テスト)パッチファイル
カーネル2.4.4用のパッチファイル
カーネル2.2.19用のパッチファイル
FAQのドキュメント(PDF形式)
インストール方法のドキュメント
インストール用のメイクファイル
readmeファイル
改訂履歴
リアルタイムカーネルの設定ファイル
RTLinuxの環境変数の設定ファイル
◆ 「debugger」ディレクトリ
「debugger」ディレクトリにはRTLinux用のデバッガが用意されています。RTLinux
モジュールのデバッグを行うことが可能になります。
デバッガの使用方法については『6.1 RTLinuxプログラムノデバック』を参照して
ください。
◆ 「examples」ディレクトリ
「examples」ディレクトリにはRTLinuxの各サンプルプログラムが用意されていま
す。RTLinuxスレッドやRT-FIFO等の基本的な使用方法が例題として用意されてい
ますので、インストール後に是非一度動かしてみてください。
Interface Corporation
- 28 -
◆ RTLinuxインストール後に追加されるファイル(ディレクトリ)
で網掛けされたファイルは、『2.7 RTLinuxのコンパイル』のRTLinux
のコンパイル後に追加されるファイルです。
RTLinuxのルートディレクトリでは、コンパイルの実行後にmodulesディレクトリ
と、rtl.config, rtl.mkが作成されています。
modulesディレクトリには、make実行時に作成されたRTLinuxのリアルタイムカー
ネルが格納されています。RTLinuxでリアルタイム処理を行う場合には、このリア
ルタイムカーネルをあらかじめ組み込んでおく必要があります。
rtl.configファイルは、make xconfigを実行後に作成されるファイルで、RTLinuxの
コンパイル時のオプション情報や設定が記録されています。
rtl.mkファイルは、RTLinuxモジュールを自作した際に使用する、コンパイルオプ
ション等が指定されています。Makefileにインクルードして使用します。
rtl.mkはincludeディレクトリの中にもコピーされています。
make installを実行した際に、/usr/include/rtlinuxにrtlinux-3.1/includeへのシンボリッ
クリンクが張られますので、Makefileには、
include /usr/include/rtlinux/rtl.mk
を記述することでRTLinuxモジュールのコンパイルが可能になります。
その他のディレクトリの詳細については、各ディレクトリの中にドキュメント
(README等)が用意されていますので、そちらをご参照ください。
Interface Corporation
- 29 -
2.9 RTLinuxサンプルプログラムの紹介
それでは、RTLinuxに付属されているサンプルプログラムを実際に動かします。
まず、『第2章 RTLinuxのインストール』でRTLinuxのインストールを行ったディレク
トリに移動します。
ここで、下記のRTLinuxの各リアルタイムカーネルが組み込まれていることを確認し
ます。
# cd /usr/src/rtlinux/rtlinux-3.1
# lsmod
Module
Size
Used
by
psc
18656 0
(unused)
rtl_sched 42496 0
[PSC]
rtl_fifo
9792 0
[PSC]
rtl_posixio
7120 0
[rtl_fifo]
rtl_time
9872 0
[psc rtl_sched rtl_posixio]
rtl
26368 0
[psc rtl_sched rtl_fifo rtl_posixio
rtl_time]
もし、必要なモジュールが組み込まれていなかった場合は、インストール用のシェル
スクリプトを実行して、モジュールの組み込みを行ってください。
# sh scripts/insrtl
RTLinux Extensions Loaded (http://www.fsmlabs.com/)
★RTLinux モジュールの自動組み込み
上記の方法でモジュールの組み込みを行った場合、OS の再起動を行うと再びモジュール
の組み込み作業を行う必要があります。
RTLinux 用のソフトウェアの開発作業中には、再起動が必要になることも多くありますが、
非常に面倒な作業となってしまいます。
RTLinux に必要なモジュールを、起動時に自動的に組み込みたい場合は、
# cd /etc/rc.d/rc3.d
# ln -s ../init.d/rtlinux ./S99rtlinux
この様に設定しておけば、次回 RTLinux 起動時から自動的にモジュールが組み込まれ、
RTLinux 起動時に毎回、手動でシェルスクリプトを実行する必要がなくなります。
(rc3.d にリンクを用意すると、ランレベル 3 で起動した場合にのみ組み込まれます)
次に、サンプルプログラムがインストールされたディレクトリに移動します。
# cd examples
# ls
README
cpp
fp
frank
hello
measurements
misc
mutex
old
sound
v1api
Interface Corporation
- 30 -
この中で、frankと言うサンプルプログラムを動かします。
『第2章 RTLinuxのインストール』の手順が完了していれば、サンプルプログラムの
コンパイルも同時に行われ、実行に必要なRTLinuxモジュール(frank_module.o)とLinux
プログラム(frank_app)が作成されています。
RTLinuxのリアルタイムカーネルを組み込んで、frank_appを実行してください。
# cd frank
# insmod frank_module.o
# ./frank_app
もし、RTLinuxモジュールとLinuxプログラムが作成されていなければ、makeを実行し
てサンプルプログラムをコンパイルしてください。
実行に成功した場合は、下記のように表示されます。
FIFO handler: sending the “1” command to task0; period 500000
task0: executing the “1” command to task0; period 500000
FIFO handler: sending the “1” command to task1; period 200000
task1: executing the “1” command to task1; period 200000
・
・
FIFO 1: Frank
FIFO 2: Zappa
FIFO 2: Zappa
FIFO 1: Frank
FIFO 2: Zappa
FIFO 2: Zappa
FIFO 2: Zappa
FIFO 1: Frank
FIFO 2: Zappa
FIFO 2: Zappa
FIFO 1: Frank
FIFO 2: Zappa
FIFO 2: Zappa
FIFO 2: Zappa
・
・
・
X Windowシステム上の端末で実行している場合には、2つのRTLinuxスレッドと
my_handlerからの出力(rtl_printf関数を使用した出力)は表示されません。
しばらくすると、表示が止まってプログラムが完了します。
frank_app: now sending commands to stop RT-tasks
FIFO handler: sending the “2” command to task0; period 200000
task0: executing the “2” command to task0; period 200000
FIFO handler: sending the “2” command to task1; period 200000
task1: executing the “2” command to task1; period 200000
#
次章では簡単なRTLinuxのプログラミングについて説明します。
Interface Corporation
- 31 -
第3章 初歩のRTLinuxプログラミング
ここでは、簡単ながらRTLinux上で動くRTLinuxモジュールを作り、実際に動かします。
これにより、LinuxプログラムとRTLinuxプログラムの違いについて、理解が深まると
思います。
3.1 プログラミングの前に(RTLinuxリアルタイムカーネルの組
み込み)
これ以降の、実際のプログラミング作業では、suコマンドを使う等して、スーパーユ
ーザにて作業を行ってください。(例えば、ドライバの組み込みは、スーパーユーザで
ないと実行できません)
suコマンドでスーパーユーザになるには、コンソールで、以下のように入力します。
% su
Password: ----- root のパスワードを入力してください。
次に、RTLinuxのリアルタイムカーネルを組み込み、これから作成するRTLinuxモジュール
が動かせるようにします。
RTLinuxがインストールされたディレクトリに移り、RTLinuxリアルタイムカーネル組み込
み用のシェルスクリプトを実行します。
# cd /usr/src/rtlinux/rtlinux-3.1
# sh scripts/insrtl
★RTLinuxリアルタイムカーネルが組み込みできない!?
シェルスクリプトで RTLinux リアルタイムカーネルを組み込む時、スーパーユーザでない
と、組み込みエラーが発生します。
間違いやすいので、組み込み時エラーが発生したら、慌てずスーパーユーザかどうか確認
してください。
これでRTLinuxリアルタイムカーネルが組み込まれます。
ちゃんと組み込まれたかどうか、ロードされているモジュールを一覧表示するlsmodコマ
ンドを使って確認します。
Interface Corporation
- 32 -
# lsmod
Module
rtl_sched
rtl_fifo
rtl_posixio
rtl_time
rtl
Size
43104
9968
7184
10000
27184
Used
0
0
0
0
0
by
(unused)
(unused)
[rtl_fifo]
[rtl_sched rtl_posixio]
[rtl_sched rtl_fifo rtl_posixio
rtl_time]
5つのモジュールが組み込まれていることが分かります。
RTLinuxでは、これら5つのリアルタイムカーネルが組み込まれることで、ユーザの作
成するRTLinuxモジュールを実際に動かすことができるようになります。
lsmod コマンド実行時の表示内容
rtl
rtl_fifo
rtl_posixio
rtl_sched
rtl_time
モジュール名
rtl.o
rtl_fifo.o
rtl_posixio.o
rtl_sched.o
rtl_time.o
これで、RTLinuxプログラミングの準備が整いました。
Interface Corporation
- 33 -
用語解説
先ほど出た用語について、幾つか簡単に解説します。
★シェルスクリプトについて
シェルスクリプトとは、コンソールから打ち込むコマンドを、まとめて実行させるように
記述したファイルです。高機能なバッチ処理を行うことができます。
(Windows では、bat ファイルや wsh ファイル等が、それにあたります)
ここで、insrtl が scripts ディレクトリにあるのならば、なぜ
#cd /usr/src/rtlinux/rtlinux-3.1/scripts
#sh insrtl
としないのでしょうか?
実は、/usr/src/rtlinux/rtlinux-3.1/scripts からスクリプトを実行すると、RTLinux のリアルタ
イムカーネルを格納しているディレクトリへのパスが、insrtl スクリプト内で設定している
パスと一致せず、エラーとなってしまうからなのです。
また、RTLinux リアルタイムカーネルは insmod で組み込むことができますが、それぞれの
モジュールは、順番が決まっているため、間違った順番でモジュールを組み込めません。
用意されている insrtl シェルスクリプトを使用することで簡単にモジュールを組み込むこ
とができます。
実際に組み込みシステムを運用する場合は、いちいちコマンドを打ち込むことはできない
ので、RTLinux 起動時、自動的にシェルスクリプトを実行するよう設定するのが良いでし
ょう。
★RTLinux リアルタイムカーネルが公開している関数を確認するには?
5 つのリアルタイムカーネルを組み込んだ後、
#less /proc/ksyms
を実行すると、これらのモジュールが公開している関数等を確認することができます。
これにより、どのモジュールがどのような役割を持っているかが分かります。
Interface Corporation
- 34 -
★rtlinux スクリプトを使って組み込む
先の説明では、insrtl スクリプトを使って、リアルタイムカーネルを組み込んでいますが、
rtlinux スクリプトを使ってリアルタイムカーネルを組み込むこともできます。
# rtlinux start
rtlinux スクリプトを使うと、簡単にリアルタイムカーネルを組み込むことができます。
単に rtlinux と入力すると、詳しい説明が表示されます。
# rtlinux
USAGE:
rtlinux {start│stop│status} [module(s)]
EXAMPLES:
To insert RTLinux only --> ./rtlinux start
To remove RTLinux modules only --> ./rtlinux stop
To check status of RTLinux only --> ./rtlinux status
To insert RTLinux and foo{1,2}.o modules --> ./rtlinux start foo1 foo2
To remove foo{1,2}.o and RTLinux modules --> ./rtlinux stop foo1 foo2
To check status of RTLinux and foo{1,2}.o modules --> ./rtlinux status foo1 foo2
Copyright 2000, Finite State Machine Labs, Inc.
Questions? Contact Edgar F. Hilton <[email protected]>
3.2 Hello Worldプログラム
まずは古くからの慣例に従い、「Hello World」をコンソールに表示させてみます。
エディタを立ち上げ、List3-1に示すプログラムを入力し、ファイル名を「sample1.c」
として保存してください。これは、一番単純なRTLinuxプログラムです。
★プログラム中のコメントについて
サンプルプログラムには、理解し易いよう、日本語コメントを用いています。
しかし、プログラム中に日本語を用いてコンパイルすると、正常にコンパイルできないこ
とがあります。その時は、日本語コメントを削除してコンパイルしてください。
List3-1 sample1.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include
<rtl.h>
/* 初期化関数(insmodコマンドでモジュールを読み込む時、呼ばれる関数) */
int init_module(void)
{
rtl_printf("Hello World!!¥n");
return 0;
}
/* 終了関数(rmmodコマンドでモジュールを排除する時、呼ばれる関数) */
void cleanup_module(void)
{
rtl_printf("bye bye¥n");
}
Interface Corporation
- 35 -
次に、
またエディタを立ち上げ、
List3-2に示すプログラムを入力し、
ファイル名を
「makefile」
として保存してください。
これは、上記プログラムをコンパイルするメイクファイルです。
List3-2 makefile
1
2
3
4
5
include /usr/include/rtlinux/rtl.mk
all: sample1.o
sample1.o:sample1.c
$(CC) $(INCLUDE) $(CFLAGS) -o sample1.o -c sample1.c
★include /usr/include/rtlinux/rtl.mk は何のためにある?
このメイクファイルでインクルードしている/usr/include/rtlinux/rtl.mk というファイルは、
私たちの RTLinux モジュールをコンパイルするために必要な定義を、全て行ってくれてい
ます(ヘッダファイルのインクルード等)。
この方法でコンパイルを行うのもよいですが、作成する RTLinux モジュール名とソースフ
ァイル名とが同じ場合(拡張子は除く。例えば test.c と test.o のような場合)、暗黙的ルー
ルを使用することで、メイクファイルは、
include /usr/include/rtlinux/rtl.mk
all: test.o
test.o: test.c
のみでもコンパイル可能となります。
それでは、コンパイルして動かします。
コンソールに以下を入力し、Enterキーを押します。
# make
すると、次のファイルができ上がります。
# ls
makefile
sample1.c
sample1.o
この「sample1.o」ファイルが、RTLinuxモジュールです。
それでは、早速RTLinuxモジュールを、組み込んでみます。
X Windowで使用されている方は、rtl_printf関数の出力内容が画面で確認できるよう、コン
ソールをもう一つ立ち上げ、次のコマンドを入力してください。
# tail –f /var/log/messages
コンソール画面で作業されている方は、次のように打ち込んでください。
# tail –f /var/log/messages &
これにより、rtl_printf関数が出力する内容が画面で確認できます。
Interface Corporation
- 36 -
★/var/log/messages
syslogやcron等で実行されたサービスのログ等の情報は、「/var/log/」に保存されます。通常、
ログは「/var/log/messages」に保存されます。
RTLinuxでは、rtl_printf関数を使って、ここに出力し、デバッグプリントができるようになっ
ています。
(そのままコンソール画面に出力されるようには、なっていません)
上の用例では、tailコマンドを使って、このログ出力を常に表示状態にしています。
コンソール画面で用いた&(アンパサンド)コマンドはジョブコマンドの一種で、tailコマンドを
バックグランドで実行させています。
コンソール画面では、X Windowのように幾つもコンソールを起動することができないので、
こうやって対処しています。
準備ができたら、RTLinuxモジュールを組み込みます。
コンソールに以下を入力し、Enterキーを押します。
# insmod sample1.o
すると、コンソール画面に、以下のメッセージが表示されます。
(X Windowでは、メッセージは、tailコマンドを実行中の画面に表示されます)
# insmod sample1.o
Hello World!!
このメッセージが表示された時、作ったRTLinuxモジュールが動いています。
次に、組み込んだRTLinuxモジュールを一覧で確認します。
確認は、lsmodコマンドで行います。
# lsmod
Module
sample1
rtl_sched
rtl_fifo
rtl_posixio
rtl_time
rtl
rtl_posixio
Size
320
43104
9968
7184
10000
27184
Used
0
0
0
0
0
0
by
(unused) ← 組み込んだモジュール名
(unused)
(unused)
[rtl_fifo]
[rtl_sched rtl_posixio]
[sample1
rtl_sched
rtl_fifo
rtl_time]
リストの中に「sample1」の名前が見て取れます。組み込まれていることが確認できました。
次に、組み込んだRTLinuxモジュールを削除します。
コンソールに以下を入力し、Enterキーを押します。
# rmmod sample1
Interface Corporation
- 37 -
すると、コンソール画面は、以下のメッセージが表示されます。
# rmmod sample1
bye bye
RTLinuxモジュールが削除されたことが判ります。
何度か、insmodコマンドによるモジュール組み込みとrmmodコマンドによるモジュール削
除を繰り返してみてください。
その都度、メッセージが表示されることがわかります。
3.3 Hello Worldプログラムの解説
それでは、先ほどのプログラムの動きを解説します。
先ほど、コンパイルしたプログラムを組み込むと称して、「insmod sample1.o」をコン
ソールで入力しました。
insmodコマンドは、作ったRTLinuxモジュール(sample1.o)を、RTLinuxに組み込む専用
のコマンドです。
このコマンドを入力した時、コンソールに「Hello World」と表示されました。
sample1.cリストを読み直してください。同じ内容が、init_module関数の6行目に有りま
す。
つまり、insmodコマンドを使ってRTLinuxモジュールを組み込むと、init_module関数が
呼び出されます。ここで、コードの中のrtl_printf関数が呼び出され、コンソールにメ
ッセージを表示させることができるのです。
(実際には、/var/log/messagesにログ出力しています)
init_module関数は、RTLinuxモジュールをシステムに登録する際、1回だけ呼ばれる専
用の関数です。通常、ここはRTLinuxモジュールの初期化を行うコードを記述します。
(C++のクラスで言うコンストラクタのようなものです)
RTLinux モジュール
sample1.o
組み込み(insmod)
init_module 関数
解除(rmmod)
cleanup_module 関数
リアルタイムカーネル
図 3-1 RTLinuxモジュールの呼び出し関係
Interface Corporation
- 38 -
次に、「rmmod sample1」をコンソールに入力しました。
このrmmodコマンドは、組み込んだRTLinuxモジュール(sample1.o)を、RTLinuxカーネル空
間から削除するためのコマンドです。
このコマンドを入力した時、コンソールに「bye bye」と表示されました。
これと同じ内容が、cleanup_module関数の13行目に有ります。
cleanup_module関数は、RTLinuxモジュールをシステムから解除する時、1回だけ呼ばれる
専用の関数です。
通常、ここはRTLinuxモジュールの終了処理を行うコードを記述します。
(C++のクラスで言うデストラクタのようなものです)
どうですか?RTLinuxプログラミングって、意外と簡単ですね。
3.4 組み込み中にも実行されるプログラムを作る
先ほどのプログラムは、RTLinuxモジュールをシステムに組み込んでいる間、何も
コンソールに表示しませんでした。
それは、組み込んでいる間、動作するコードを何も書いてなかったからです。
では、組み込んでいる間、周期的にメッセージを出力するプログラムを作ります。
エディタを立ち上げ、List3-3に示すプログラムを入力し、ファイル名を「sample2.c」
として保存してください。
List3-3 sample2.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include
#include
#include
<rtl.h>
<rtl_sched.h>
<rtl_time.h>
pthread_t
argo_task_info;
/* 周期実行を行うRTLinuxスレッド */
void* argo_task(void* arg)
{
struct sched_param p;
rtl_printf("argo_task called arg=%d¥n", arg);
/* 自スレッドに対する優先順位や周期の設定 */
p.sched_priority = 5;
pthread_setschedparam(pthread_self(), SCHED_FIFO, &p);
pthread_make_periodic_np(pthread_self(), gethrtime(), 1 * 1000 * 1000 * 1000);
Interface Corporation
- 39 -
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
47
48
49
50
51
52
53
/* RTLinuxスレッドが登録中、動作する永久ループ */
while(1){
/* 周期的なメッセージ表示 */
struct timespec t;
t = timespec_from_ns(clock_gethrtime(CLOCK_REALTIME));
rtl_printf("now clock=%d:¥n", t.tv_sec);
/* 自スレッドをスリープさせる */
pthread_wait_np();
}
return 0;
}
/* 初期化モジュール(insmodコマンドでモジュールを組み込む時、呼ばれる関数) */
int init_module(void)
{
int
ret;
rtl_printf("init_module called¥n");
EXPORT_NO_SYMBOLS;
/* スレッドを作成、起動する */
ret = pthread_create(&argo_task_info, NULL, (void*)argo_task, 0);
return ret;
}
/* 終了モジュール(rmmodコマンドでモジュールを削除する時、呼ばれる関数) */
void cleanup_module(void)
{
rtl_printf("cleanup_module called¥n");
/* スレッドを終了させる */
pthread_cancel(argo_task_info);
pthread_join(argo_task_info, NULL);
}
同じように、「sample2.c」をコンパイルするメイクファイル(makefile)を示します。
List3-4 makefile
1
2
3
4
5
include /usr/include/rtlinux/rtl.mk
all: sample2.o
sample2.o: sample2.c
$(CC) $(INCLUDE) $(CFLAGS) -o sample2.o -c sample2.c
コンパイルし、insmodコマンドでRTLinuxモジュールを組み込みます。
# make
# ls
makefile sample2.c
# insmod sample2.o
Interface Corporation
sample2.o
- 40 -
登録した瞬間から、メッセージが表示されだしました。
# insmod sample1.o
init_module called
argo_task called arg=0
now clock=7905
now clock=7906
now clock=7907
now clock=7908
<以下略>
lsmodコマンドで、RTLinuxモジュールをリスト表示させてみます。
# lsmod
Module
sample2
rtl_sched
rtl_fifo
rtl_posixio
rtl_time
rtl
rtl_posixio
Size
976
43104
9968
7184
10000
27184
Used
0
0
0
0
0
0
by
(unused) ← 組み込んだモジュール名
[sample2]
(unused)
[rtl_fifo]
[sample2 rtl_sched rtl_posixio]
[sample2
rtl_sched
rtl_fifo
rtl_time]
rmmodコマンドで、RTLinuxモジュールを削除します。
# rmmod sample2
cleanup_module called
メッセージの表示がストップしました。
3.5 組み込み中にも実行されるプログラムの解説
それでは、先ほどのプログラムの動きを解説します。
まず、このサンプルの大まかな動きを以下の図に示します。
argo_task
pthread_create
pthread_cancel
init_module
cleanup_module
insmod コマンド
rmmod コマンド
図 3-2 sample2.oの動き
Interface Corporation
- 41 -
1. insmodコマンドでsample2モジュールを組み込む時、init_module関数が呼ばれま
す。その中で、pthread_create関数により、argo_task関数がRTLinuxスレッドとし
て生成、起動されます。
2. argo_taskスレッドは、pthread_make_periodic_np関数により、自身の実行周期を、
1秒に設定します。
3. argo_taskスレッドの、whileループ内では、rtl_printf関数により、システム起動時
からの時間を秒単位で表示します。その後、pthread_wait_np関数により、自身の
RTLinuxスレッドをスリープさせ、システムから次の周期呼び出しまで待機しま
す。
(周期呼び出しは、先に設定したように、1秒間隔です)
4. whileループ自体は永久ループなので、特に指示ない限り、回り続けます。
5. rmmodコマンドでsample2モジュールをRTLinuxから削除する時、cleanup_module
関数が呼ばれます。
その中で、pthread_cancel関数により、argo_taskスレッドに対してスレッド終了
の通知が発せられ、argo_taskスレッドは終了します。
6. 全ての終了処理を終え、sample2モジュールの解除は完了します。
では、上の図に沿って、もう少し詳しくプログラムを読み解きます。
まず、init_module関数から行きます。
(38行目:EXPORT_NO_SYMBOLSマクロ)
EXPORT_NO_SYMBOLSマクロは、このRTLinuxモジュールのグローバルシンボ
ルを非公開にするためのマクロです。
Interface Corporation
- 42 -
★グローバルシンボル
モジュールがカーネル内に組み込まれると、公開されたシンボル(グローバル変数や、グロ
ーバル関数等)は、他のモジュールから参照できるようになっています。それを防ぐために
EXPORT_NO_SYMBOLS マクロを定義します。
もし、これを行わないと、どうなるのでしょうか?
例えば、A のモジュールで count 変数を定義し、B のモジュールで何の気なしに参照する
と、B のモジュールは A のモジュールの count 変数と共有してしまうことになります。
この共有をプログラマが意図してなかった場合どうなるでしょうか?
恐らく、原因不明のバグとして、悩みつづけることになるでしょう。
EXPORT_NO_SYMBOLS マクロは、これら意図しないシンボルの共有を防ぐためのもので
す。
なお、グローバルシンボルは、/proc/ksyms で確認することができます。
以下に、EXPORT_NO_SYMBOLS を付けた場合と、付けない場合のシンボルを比較します。
<EXPORT_NO_SYMBOLS なし>
<EXPORT_NO_SYMBOLS あり>
c88e8000
c88e8000
__insmod_sample2_O/root/test/sample2. __insmod_sample2_O/root/test/sample2.o_M
3CBF8491_V132100 [sample2]
o_M3CBF7E4C_V132100 [sample2]
c88e8060
__insmod_sample2_S.text_L384
c88e83a8 argo_task_info [sample2]
c88e83a8
__insmod_sample2_S.bss_L4 [sample2]
c88e838c
__insmod_sample2_S.bss_L4
[sample2]
[sample2]
c88e8060 argo_task
[sample2]
c88e8060 __insmod_sample2_S.text_L384
[sample2]
(41行目:pthread_create関数)
pthread_create関数では、RTLinuxモジュールを組み込んでいる間、動作し続ける
RTLinuxスレッドを生成しています。
ここでは、argo_task関数をスレッドの実行単位として指定しています。
★RTLinux スレッドを作らずに動かすことはできるか?
RTLinux スレッドを作るのが面倒だからと言って、pthread_create 関数を省き、argo_task 関
数の処理内容を、init_module 関数内に持って来てはいけません。
これを行うと、プログラムが完全に停止状態に陥ります。
これは、init_module の処理が、RTLinux のカーネルスケジューラに戻らないためです。
(注意!:真似をしないでください。本当に何のキーも受け付けなくなります)
次は、argo_task関数本体に移ります。
Interface Corporation
- 43 -
(15,16行目:pthread_setschedparam、pthread_make_periodic_np関数)
ここでは、自身のRTLinuxスレッドに対する、スケジューリング、優先度の設定およ
び、実行周期を設定しています。
実行周期は、pthread_make_periodic_np関数で設定します。
周期は第3引数で、ns(ナノ秒)単位で設定します。サンプルプログラムでは、”1 * 1000 *
1000 * 1000 = 1s”とし、1秒の周期を設定しています。
(19~27行目:whileループ)
while文により、永久ループしているのが目に付きます。
これは特に指示されない限り、RTLinuxスレッドを実行し続けるための工夫です。
もし、このwhileループを外してしまうと、すぐに終了してしまいます。
(RTLinuxスレッドと言っても、中身はただの関数です)
(21~23行目:clock_gettime関数等)
21~23行は、現在のタイマー値を読み取り、rtl_printf関数でデバッグプリントを行って
います。
(26行目:pthread_wait_np関数)
whileループ中のpthread_wait_np関数は、実行中のRTLinuxスレッドをスリープさせ、
他のRTLinuxスレッドに対する実行権を明示的に渡す関数です。
システムは、他のRTLinuxスレッドへ実行権を渡し処理を続けます。
他のRTLinuxスレッドの処理が終わると、システムは優先度の兼ね合いを判定し、こ
のRTLinuxスレッドに再び実行権を渡します。
★pthread_wait_np を外すと、どうなるか?
ところで、このサンプルから、pthread_wait_np 関数を排除するとどうなるでしょう?
結果は、他のどの RTLinux スレッドにも実行権が移らなくなり、いわゆる固まった状態に
陥ります。
(注意!:真似をしないでください。本当に何のキーも受け付けなくなります)
通常の Linux プログラムならば、別途シェルを起動して、永久ループに陥ったプロセスを
kill して復帰することも可能ですが、RTLinux プログラムでは、そんなに甘くありません。
文字通り固まります。
これは、見方を変えると、RTLinux では、他の何者に対しても優先的に処理することが可
能だと言う証拠でもあります。
(他のプロセスを立ち上げkillできるということは、実行しているプロセスより優先的
に動くプロセスが存在するということです)
最後に、cleanup_module関数に目を向けます。
Interface Corporation
- 44 -
(51,52行目:pthread_cancel関数、pthread_join関数)
これは、このRTLinuxモジュールをシステムから削除するので、実行中のRTLinuxスレ
ッドを終了させるための指令です。
この関数により、argo_taskスレッドに対して終了通知が発せられ、argo_taskスレッド
は、終了通知を検知した時、自身のスレッドを終了します。
どうでしたか?一見複雑そうに見えるサンプルプログラムも、
順に追いかけていくと、
簡単に読み取ることができます。
関数&用語解説
先ほど出た用語について、幾つか簡単に解説します。
★init_module での禁止事項
RTLinux モジュールは、カーネル空間に存在するため、ユーザ空間でできないことができ
る反面、一歩間違えると、カーネルやファイルシステムを破壊してしまう恐れがあります。
代表的な禁止事項として、init_module や割り込みハンドラ内で usleep 関数を呼び出しては
いけません。Linux が起動しなくなってしまう場合があります。
他にも、禁止事項が幾つかあります。RTLinux 関連のドキュメントをよく読んでください。
★pthread_create
RTLinux スレッドを作成する関数です。
第 1 引数には RTLinux スレッドの ID を格納する pthread_t 変数へのポインタを指定します。
第 2 引数には RTLinux スレッドの属性を指定する pthread_attr_t 変数へのポインタを指定し
ます。
第 3 引数には作られた RTLinux スレッドで処理する関数を指定します。
第 4 引数にはその関数に渡す引数を指定します。
プログラム例では、RTLinux スレッドの属性は指定しないため、NULL を指定しています。
★pthread_self
呼び出した自身の、RTLinux スレッドの ID を取得することができます。スレッド ID を引
数パラメータに指定する関数に対して自身のスレッド ID を指定する場合等に使用します。
★pthread_setschedparam
RTLinux スレッドのスケジューリング方法、優先度の設定を行う関数です。
第 1 引数では、RTLinux スレッドの ID を指定します。(ここでは、自身のスレッド ID を返
す pthread_self 関数により、自身の ID を取得しています)
第 2 引数では、スケジューリング方法を指定します。ここでは SCHED_FIFO をパラメー
タ値に指定しています。
第 3 引数では、プライオリティ等の設定を行う sched_param 構造体のポインタを渡してい
ます。ここではプライオリティ値を 5 に設定しています。
なお、プライオリティとは日本語で「優先度」を意味し、複数のスレッドを動かした際、
どのスレッドから実行を行うか、指定を行うことができます。
Interface Corporation
- 45 -
★pthread_make_periodic_np
ある RTLinux スレッドに対し、実行周期の間隔を指定する関数です。
第 1 引数にはスレッドの ID を指定します(ここでは、自身のスレッドの ID を返す
pthread_self 関数により、自身の ID を取得しています)。
第 2 引数には、リアルタイム処理の実行を開始する時間を hrtime_t 型で指定します(ここで
はシステム起動からの絶対時間を取得する gethrtime 関数を用いて、開始時間を関数呼び出
しと同時にしています)。
第 3 引数には、リアルタイム処理を実行する周期を ns(ナノ秒)単位で設定します。おなじ
く hrtime_t 型で指定します。
リストでは、pthread_wait_np によるスレッドの待機箇所を起点として、指定された周期で
while ループ中の処理が実行されます。
★pthread_wait_np
pthread_wait_np 関数は、pthread_make_periodic_np 関数により、指定された周期まで待つ関数
です。
例えば、pthread_make_periodic_np 関数により 10ms の周期を指定された場合、10ms が経過
するまで、この pthread_wait_np 関数で待つことになります。
また、pthread_wakeup_np 関数を呼ぶことにより、実行を再開することもできます。
(但し、別の RTLinux スレッドからスリープ状態の RTLinux スレッドに対して、
pthread_wakeup_np 関数で呼び起こす必要があります)
★終了時の関数
pthread_cancel 関数は、引数に終了要求を出すスレッド ID を指定します。pthread_join 関数
も第 1 引数に同じくスレッド ID を指定します。第 2 引数は、ここでは NULL にしていま
す。
なお、pthread_exit 関数で RTLinux スレッドの処理を終わらせた場合、pthread_exit 関数の
引数が、pthread_join 関数の第 2 引数に格納されます。
以下に例を示します。
void* input_task(void *arg)
{
int status = 10;
・・・
pthread_exit(status);
・・・
}
void cleanup_module(void)
{
int value;
pthread_join(send_thread, &value); // value には 10 が格納されます
・・・
}
Interface Corporation
- 46 -
3.6 LinuxプロセスからRTLinuxモジュールを制御する
今までのプログラムは、登録したら最後、誰からの命令を受けることも無く、永
遠に同じことを繰り返すだけのプログラムでした。
実際の組み込みプログラミングでは、こんなことはありません。
誰かから(大抵は上位アプリケーション)指令を受け、その指令に従って何らかのア
クションを起こすのが普通です。
ここでは、Linuxプロセスから、RTLinuxモジュールを制御します。
まずは、4つのファイルを作成します。
ファイル名
備考
sample3.h
LinuxプロセスとRTLinuxモジュールの双方で共有する定義ファイル
sample3.c
Linuxプロセスのソースコード
module3.c
RTLinuxモジュールのソースコード
makefile
上記ソースコードをコンパイルするためのmakefile
List3-5は、LinuxプロセスとRTLinuxモジュール間で、共通で使う定義ファイルで
す。ファイル名を「sample3.h」として入力、保存してください。
List3-5 sample3.h
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
/*
sample3.h 共通定義ヘッダファイル
Copyright 2002 Interface Corporation. All rights reserved.
*/
#if
!defined(___SAMPLE3_H)
#define
___SAMPLE3_H
/* const defines -------------------------------------------------------------- */
#define
GET_HANDLER_FIFO
1
/* Linuxプロセスから指令を受
け取るFIFOチャネル */
#define
GET_TASK_FIFO 2 /* ハンドラから指令を受け渡しするFIFOチャ
ネル */
#define
SET_TASK_FIFO 3 /* Linuxプロセスへ結果を送るFIFOチャネル
*/
#define
BUFF_SIZE
ネルのサイズ */
100 /* Linuxプロセスへ結果を送るFIFOチャ
/* type defines --------------------------------------------------------------- */
/* コマンドID群(RTLinuxスレッドへの指示用) */
enum CMD_IDS {
ID_START,
/* スタート指示 */
ID_STOP
/* ストップ指示 */
};
Interface Corporation
- 47 -
27
28
29
/* コマンド指示用の構造体 */
struct CMD_STRUCT {
enum CMD_IDS
id;
/* コマンドID */
long
value; /* 設定用パラメータ*/
};
#endif
List3-6は、Linuxプロセスのソースファイルです。ファイル名を「sample3.c」とし
て入力、保存してください。
List3-6 sample3.c
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
/*
sample3.c Linuxプロセスのソースコード
Copyright 2002 Interface Corporation. All rights reserved.
*/
#include
#include
#include
#include
#include
#include
#include
<stdio.h>
<fcntl.h>
<unistd.h>
<sys/time.h>
<sys/ioctl.h>
<rtl_fifo.h>
"sample3.h"
/* Linuxプロセスのメインルーチン */
int main(void)
{
int
fd_ret, fd_ctrl;
fd_set
rfds;
struct timeval tv;
struct CMD_STRUCT cmd;
long
counter = 0;
*/
/* 周期スレッドのチェック用カウンタ
/* RTLinuxスレッドに指令を送るFIFOチャネルのオープン */
if((fd_ctrl = open("/dev/rtf1", O_WRONLY)) < 0){
fprintf(stderr, "failed to open /dev/rtf1¥n");
return -1;
}
/* RTLinuxスレッドからの結果を受け取るFIFOチャネルのオープン */
if((fd_ret = open("/dev/rtf3", O_RDONLY)) < 0){
fprintf(stderr, "failed to open /dev/rtf3¥n");
return -1;
}
/* RTLinuxスレッドへの実行開始の指示 */
cmd.id
= ID_START;
cmd.value = 500;
/* 500ms周期実行に設定 */
if(write(fd_ctrl, &cmd, sizeof(cmd)) < 0){
fprintf(stderr, "failed to send the start command¥n");
Interface Corporation
- 48 -
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
return -1;
}
/* RTLinuxスレッドのカウンタが10になるまで取得のループ */
do {
FD_ZERO(&rfds);
FD_SET(fd_ret, &rfds);
tv.tv_sec = 30; /* select関数のタイムアウト値の設定:30秒 */
tv.tv_usec = 0;
/* RTLinuxスレッドからのデータ受け取り */
if(select(FD_SETSIZE, &rfds, NULL, NULL, &tv) > 0){
if(FD_ISSET(fd_ret, &rfds)){ /* fd_retに対してFIFOの書き込みがあ
った */
read(fd_ret, &counter, sizeof(counter));
printf("counter:%ld¥n", counter);
}
}
}while(counter < 10);
/* RTLinuxスレッドへの停止指示 */
cmd.id
= ID_STOP;
cmd.value = 0;
if(write(fd_ctrl, &cmd, sizeof(cmd)) < 0){
fprintf(stderr, "failed to send the stop command¥n");
return -1;
}
printf("The Linux process is successfully completed.¥n");
return 0;
}
List3-7は、RTLinuxで動作するRTLinuxモジュールのソースファイルです。ファイル名
を「module3.c」として入力、保存してください。
List3-7 module3.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/*
module3.c RTLinuxモジュール
Copyright 2002 Interface Corporation. All rights reserved.
*/
#include
#include
#include
#include
<rtl.h>
<rtl_sched.h>
<rtl_fifo.h>
"sample3.h"
pthread_t
my_task_info;
/* 周期実行を行うRTLinuxスレッド */
void* my_task(void* arg)
{
int
err;
Interface Corporation
- 49 -
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
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
struct CMD_STRUCT cmd;
long
counter = 0, temp_counter;
rtl_printf("call my_task arg=%d¥n", arg);
/* RTLinuxスレッドが組み込み中、動作する永久ループ */
while(1){
/* 自スレッドをスリープさせる */
pthread_wait_np();
/* FIFOチャネルからの取り込み */
if((err = rtf_get(GET_TASK_FIFO, &cmd, sizeof(cmd))) == sizeof(cmd)){
rtl_printf("my_task: get command id=%d value=%d¥n", cmd.id,
cmd.value);
switch(cmd.id){
case ID_START:
/* 周期実行の設定と開始 */
rtl_printf("my_task: start!!¥n");
pthread_make_periodic_np(pthread_self(), gethrtime(),
cmd.value * 1000 * 1000);
counter = 0;
/* 周 期 カ ウ ン タ の リ セ ッ ト
(ms) */
break;
case ID_STOP:
/* 周期実行の停止 */
rtl_printf("my_task: stop!!¥n");
pthread_suspend_np(pthread_self());
break;
default:
rtl_printf("my_task: unknown command!!¥n");
break;
}
}
/* 周期カウンタのカウントアップ */
counter++;
rtl_printf("my_task: counter=%d¥n", counter);
/* カウンタ値を、LinuxプロセスへのFIFOチャネルに書き込み */
temp_counter = counter;
rtf_put(SET_TASK_FIFO, &temp_counter, sizeof(temp_counter));
}
return 0;
}
/* Linuxプロセスからの指令を受け取るハンドラ */
int my_handler(unsigned int fifo)
{
int
ret;
struct CMD_STRUCT cmd;
rtl_printf("call my_handler fifo:%d¥n", fifo);
/* Linuxプロセスからの指示を、RTLinuxスレッドのFIFOチャネルに横流しす
る */
Interface Corporation
- 50 -
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
while((ret = rtf_get(GET_HANDLER_FIFO, &cmd, sizeof(cmd))) == sizeof(cmd)){
rtf_put(GET_TASK_FIFO, &cmd, sizeof(cmd));
rtl_printf("my_handler: get command id=%d value=%d¥n", cmd.id, cmd.value);
pthread_wakeup_np(my_task_info);
}
if(ret != 0){
rtl_printf("my_handler: error!!(%d)¥n", ret);
return -EINVAL;
}
return 0;
}
/* 初期化モジュール(RTLinuxモジュールが起動する時、呼ばれる関数) */
int init_module(void)
{
rtl_printf("call init_module¥n");
EXPORT_NO_SYMBOLS;
/* Linuxプロセスからの指示を受け取るハンドラとFIFOチャネルを生成する
*/
rtf_destroy(GET_HANDLER_FIFO);
rtf_create(GET_HANDLER_FIFO, sizeof(struct CMD_STRUCT));
rtf_create_handler(GET_HANDLER_FIFO, my_handler);
/* ハンドラとLinuxプロセスの間のFIFOチャネルを生成する */
rtf_destroy(GET_TASK_FIFO);
rtf_create(GET_TASK_FIFO, sizeof(struct CMD_STRUCT));
/* Linuxプロセスへ結果を送るFIFOチャネルを生成する */
rtf_destroy(SET_TASK_FIFO);
rtf_create(SET_TASK_FIFO, sizeof(long) * BUFF_SIZE);
/* スレッドを作成、起動する */
return pthread_create(&my_task_info, NULL, (void*)my_task, 0);
}
/* 終了モジュール(RTLinuxモジュールが終了する時、呼ばれる関数) */
void cleanup_module(void)
{
rtl_printf("call cleanup_module¥n");
/* FIFOチャネルを閉じる */
rtf_destroy(GET_HANDLER_FIFO);
rtf_destroy(SET_TASK_FIFO);
rtf_destroy(GET_TASK_FIFO);
/* スレッドを終了させる */
pthread_cancel(my_task_info);
pthread_join(my_task_info, NULL);
}
Interface Corporation
- 51 -
List3-8は、上記ファイルをコンパイルするメイクファイルです。ファイル名を
「makefile」として入力、保存してください。
List3-8 makefile
1
2
3
4
5
6
7
8
include /usr/include/rtlinux/rtl.mk
all: module3.o sample3
sample3: sample3.c
$(CC) $(INCLUDE) $(USER_CFLAGS) -O2 -Wall -o sample3 sample3.c
module3.o: module3.c
$(CC) $(INCLUDE) $(CFLAGS) -o module3.o -c module3.c
コンパイルし、insmodコマンドでRTLinuxモジュールを登録します。
# make
# ls
makefile sample3 module3.c module3.o sample3.c sample3.h
# insmod module3.o ← RTLinux モジュールを組み込んでいます
次に、Linuxプロセスを実行します。
# ./sample3
← Linux プロセスを実行しています
★./を何故付けるか?
上の例で、Linux プロセスを実行させるのに、「./」を付けて、実行ファイルがカレントディレクト
リ上にあることを明示しています。
もし、これを付けないと、「command not found」となってしまいます。
Windows や MS-DOS では、相対/絶対パスを付けずに、実行ファイルを呼び出すと、カレントディ
レクトリから実行ファイルを検索しますが、Linux(Unix)では、そうはならず、設定されたパス通り
に検索が行われます。
カレントディレクトリ上にあるファイルを実行させるには、必ず「./」を付加してください。
Interface Corporation
- 52 -
実行画面を以下に示します。
(画面左上のウィンドウがLinuxプロセスを実行しているコンソール。画面右下のウィンド
ウはRTLinuxモジュールのログメッセージを表示させているコンソールです)
図 3-3 sample3実行時の画面
sample3を実行させると、「get counter」の値がカウントアップしていき、10を表示し
た後、プログラムが終了します。
Interface Corporation
- 53 -
3.7 LinuxプロセスからRTLinuxモジュールを制御するプログ
ラムの解説
それでは、先ほどのプログラムの動きを解説します。
まず、LinuxプロセスとRTLinuxモジュールの関係を、下図に示します。
main
rtf1
ユーザ空間
sample3
カーネル空間
module3.o
指令
結果の通知
my_handler
rtf3
生成
破棄
rtf2
init_module
cleanup_module
指令の転送
生成
my_task
破棄
図 3-4 LinuxプロセスとRTLinuxモジュールの相関関係
・RTLinuxモジュール(module3.o)では、init_module関数呼び出し時に、my_handler
とmy_taskを生成します。cleanup_module関数は、逆に2つを破棄します。
・my_handlerは、Linuxプロセスからの指令を受け取る専用のハンドラです。
・my_taskは、周期的な処理を行う専用のRTLinuxスレッドです。プログラムでは、
スレッドのスタートとストップをサポートし、指定間隔の周期スレッドがスタ
ートされると、ストップ指令を受けるまで、内部のカウンタをアップカウント
し、結果を書き込むという単純なものです。
・Linuxプロセス(sample3)のmain関数内では、RTLinuxモジュール(module3.o)に対
して、my_taskへのスタートおよびストップを指令します。
Linuxプロセスのmain、RTLinuxモジュールのmy_handler、my_taskの各ブロック間
の、情報のやり取りは、RT-FIFOと呼ばれる専用の通信路を使って、やり取りさ
れます。
RT-FIFOは、mainとmy_handler間にrtf1、my_handlerとmy_taskの間にrtf2、my_task
とmainの間にrtf3の、合計3つのRT-FIFOが設定されます。
各スレッドおよびプロセスは、このRT-FIFOを情報の通信路として利用します。
詳細は後述しますが、このRT-FIFOを用いることで、RTLinuxスレッドはLinuxプ
ロセスの動きに引っ張られることなく、確実な周期実行を可能にしています。
Interface Corporation
- 54 -
3.7.1 RT-FIFOの役割
RT-FIFOとは、双方のスレッドがメッセージをやり取りする際の、一種の緩衝領
域です。
この機構を用いることで、双方のスレッドが非同期的に処理することが可能です。
例を示します。下図は、指令を出すスレッドAと、指令を受け取るスレッドBを仮
定しています。
<スレッドAの動き>
<スレッドBの動き>
処理 1
処理 2
処理 1
データ有る?
書き込み
RT-FIFO
RT-FIFO
取り込み
処理 3
無い
データ
有る
処理 2
スレッドAは、一連の処理の中で、RT-FIFOに対して逐次指令を書き込んでいきます。
スレッドBは、一連の処理の中で、スレッドAからの指令を検出すると、RT-FIFOから
指令を取り出して処理し、無ければスキップするという処理を行います。
もし、RT-FIFOを使わずに、2つのスレッド間でやり取りする場合、幾つか方法があり
ます。例えば、あるデータ領域に対して、スレッドAが指令を書き込み、スレッドB
は、それを読み取る処理を仮定したとします。
多くの場合、2つのスレッドが同一のデータ領域にアクセスするため、データの完全
性を保証するために、セマフォ等の同期オブジェクトを併用してデータを同期します。
ここで問題となるのが、同期オブジェクトによって、ロックしている時間です。
片方のスレッドがロックしている時間が長いと、もう片方は、その間ロック待ちの状
態となります。これは、自身の処理間隔が他方に影響を受ける点で、望ましいとは言
えません。
RT-FIFOは、この手の問題に対する、簡易かつ確実な解決方法を提供します。
Interface Corporation
- 55 -
3.7.2 共通定義ファイルの役割
ここでは、共通定義ファイル(sample3.h)の役割について見ます。
共通定義ファイルは、RTLinuxモジュール(module3.c)とLinuxプロセス(sample3.c)
の内、共通で使用する定義内容を抜き出したものです。各ファイルの関係を下図
に示します。
sample3.h
共通定義
参照
参照
sample3.c
Linux
module3.c
RTLinux
プロセス
モジュール
図 3-5 ファイルの参照関係
共通定義ファイルでは、以下のように設定しています。
・10∼14行目:#define宣言
RT-FIFO番号の定義と、バッファサイズの指定。
・18~21行目:enum宣言
LinuxプロセスからRTLinuxモジュールに対して指令を出す際のコマンドのID
値を指定。
・24∼27行目:struct宣言
LinuxプロセスからRTLinuxモジュールに対して指令を出す際のコマンドの構造
を指定。
ここで重要なのが、LinuxプロセスからRTLinuxモジュールに対して指令を出すために
使用される、コマンドの構造体(CMD_STRUCT)です。
Linuxプロセスでは、この構造体に値をセットしてRTLinuxモジュールに渡します。
RTLinuxモジュールでは、この構造体ごと 受け取って、指示された内容に従って処理
を行います。(実際には、RTLinuxモジュール内のハンドラが受け取っています)
Interface Corporation
- 56 -
Linux プロセス
struct CMD_STRUCT {
enum CMD_IDS id;
long
value;
};
RTLinux モジュール
図 3-6 LinuxプロセスからRTLinuxモジュールへのコマンドの流れ
コマンドの構造体は、簡単な2つのメンバ変数で構成されています。RTLinuxモジュー
ルに、どんな作業をして欲しいか指示を出すID値(idメンバ変数)と、ID値に補足する
情報(valueメンバ変数)です。
作業を指示するID値は、18∼21行の列挙体定数、ID_STARTとID_STOPで定義されて
います。以下に、LinuxプロセスからRTLinuxモジュールに指示する際の取り決めを、
簡単にまとめます。
id 変数
value 変数
内容
ID_START 周 期 時 間 (ms 単 value で指定し た時 間間 隔で、周 期 スレッ ド
位)
(RTLinux スレッド)をスタートする。
ID_STOP
特になし
周期実行スレッドをストップさせる。
この構造体は、後の説明にも出てきますので注意して読み進めてください。
Interface Corporation
- 57 -
3.7.3 RTLinuxモジュールの動き
ここでは、RTLinuxモジュール(module3.o)の動きに注目して見てみます。
まず、RTLinuxモジュール内の各リソースとRTLinuxスレッド、ハンドラの生成関
係を下図に示します。
RT-FIFO
FIFO1(GET_HANDLER_FIFO)
FIFO2(GET_TASK_FIFO)
生成
破棄
FIFO3(SET_TASK_FIFO)
init_module
cleanup_module
スレッド&ハンドラのコード
ハンドラ(my_handler)
RTLinux スレッド(my_task)
図 3-7 RTLinuxモジュール内の生成関係
Linuxプロセスからの指令を受け取るハンドラ(my_handler)と、RTLinuxスレッド
(my_task)が生成/破棄されています。
次に、RTLinuxモジュール内での相互関係を示します。
Linux プロセス
FIFO1(GET_HANDLER_FIFO)
FIFO3(SET_TASK_FIFO)
ハンドラ(my_handler)
FIFO2(GET_TASK_FIFO)
RTLinux スレッド(my_task)
ID_START
ID_STOP
開始
停止
周期実行
counter 変数
←インクリメント
図 3-8 RTLinuxモジュール内の処理の流れ
Interface Corporation
- 58 -
RTLinuxモジュール内で中心となるのは、周期実行を行うRTLinuxスレッド
(my_task)です。このRTLinuxスレッドは、Linuxプロセスからの指令により、周期
実行のスタート(ID_START)、ストップ(ID_STOP)を行います。スタート後の周期
実行中、RTLinuxスレッドは内部のcounter変数を周期ごとにインクリメントします。
(将来、カスタマイズするならば、例えば、ここにDIOやAD/DA等の周期的な制
御を入れると良いでしょう)
LinuxプロセスからRTLinuxスレッドへの指示は、ハンドラ(my_handler)を経由して
行われます。このハンドラは、Linuxプロセスからの指示を、RTLinuxスレッドに、
そのまま送っています。(将来、RTLinuxスレッドを2つ以上に増やした時、このハ
ンドラで、操作するスレッドを集中的に管理すると良いでしょう)
ハンドラとRTLinuxスレッドは、RT-FIFOによって、情報の交換を行います。
RT-FIFOの生成と削除は、お馴染みのinit_module関数とcleanup_module関数で行っ
ています。
以降では、処理順に、これらの処理を解説します。
(89∼99行目:rtf_destroy、rtf_create関数)
RT-FIFOを生成するのは、rtf_create関数です。破棄はrtf_destroy関数です。
コードでは、rtf_destroy関数を呼び出した後、rtf_create関数を呼び出しています。
通常であれば、init_module関数を実行する時、RT-FIFOは生成済みということは考
えにくいのですが、ここでは保険として、rtf_destroy関数で明示的に削除を行って
います。
RT-FIFOのサイズは、各RT-FIFOごとに変えています。
特にRTLinuxスレッドからLinuxプロセスへ結果を返却するRT-FIFO(99行目の、
SET_TASK_FIFO)では、”sizeof(long:4バイト) * BUFF_SIZE(100個) = 400バイト”の
バッファサイズを確保しています。
これは、RTLinuxスレッドに格納した情報を、即座にLinuxプロセス側で取り出せ
ることは考えにくいため、ある程度RT-FIFOに情報が溜まっても、処理が続けら
れるよう(バッファをオーバーフローしないよう)に、大きめのバッファを確保して
います。
Interface Corporation
- 59 -
実際のリアルタイムプログラミングでも、2つのプロセス間が非同期に動作する場
合、バッファサイズに、余裕を持たせることは重要です。
(91行目:rtf_create_handler関数)
rtf_create_handler関数は、ハンドラ(my_handler)を生成する関数です。
このハンドラでは、指定されたRT-FIFOにメッセージが溜まると呼び出される、
明示的なイベントハンドラと思えば良いでしょう。
(但し、受け取ったメッセージを取り出すコードは必要です)
(102行目:pthread_create関数)
pthread_create関数は、周期実行を行うRTLinuxスレッドを生成しています。
(69∼73行目:my_handler関数のwhileループ)
ハンドラ(my_handler)関数では、このwhileループがメインとなります。
ここでは、Linuxプロセスと繋がるRT-FIFOから送られるデータを受け取るために、
rtf_get関数で待機します。
受け取ったデータは、ここでは、rtf_put関数にて、そのままRTLinuxスレッド
(my_task)と繋がるRT-FIFOに送っています。
簡単なイメージを、下図に示します。
rtf_put
rtf_get
Linux プロセス側
RTLinux スレッド側
my_handler
RT-FIFO
RT-FIFO
ハンドラ
図 3-9 LinuxプロセスからRTLinuxスレッドへのデータのな流れ
将来、RTLinuxスレッドを2つ3つと増やした場合、ここをLinuxプロセスから各
RTLinuxスレッドへメッセージを分配するための、集配所として追加すれば良いで
しょう。
Linux プロセス側
RT-FIFO
rtf_put
rtf_get
my_handler
RTLinux スレッド側
RT-FIFO
ハンドラ
RT-FIFO
RT-FIFO
図 3-10 将来、RTLinuxスレッドを複数に増やした場合の想定例
Interface Corporation
- 60 -
(24∼56行目:my_task関数のwhileループ)
RTLinuxスレッド(my_task)では、このwhileループがメインとなります。
ここでは、ハンドラと繋がるRT-FIFOから送られるデータをrtf_get関数で受け取り、
その指示に従い、周期実行のスタートおよびストップを行います。
周期実行を動作させている時、内部のcounter変数がインクリメントされていきま
す。
このインクリメントされた値は、rtf_put関数を用いて、Linuxプロセスに繋がる
RT-FIFOに送られます。
29行目のrtf_get関数は、周期実行が行われている/行われていないに係わらず、こ
こでRT-FIFOからのデータ待ちになってしまうと思われるかも知れません。
しかし、実際には、rtf_get関数の呼び出しは、RT-FIFOからのデータがあれば、29
∼47行の処理を行い、無ければ50行以降の処理を続けます。
33∼46行のswitch文では、Linuxプロセスから送られてきた指示に対する処理が記
述されています。動きを以下に示します。
ID_START value変数の値をms単位の実行周期として、pthread_make_periodic_np
関数を呼び出し、自身の実行周期の間隔を指定する。
ID_STOP
pthread_suspend_np関数を呼び出し、自スレッドをスリープ状態にす
る。
50∼55行の処理は、周期実行している時の、処理コードです。
内容は、内部counter変数をインクリメントし、counter変数の値を、rtf_put関数を使
って、RT-FIFOに書き込み続けています。
ここでやっているのは、非常に単純な処理ですが、この処理をDIOやAD/DA等に
置き換えて見ると、様々なやり方が想定できることでしょう。
例えば、周期実行の部分に、1件のAD入力関数を配置するだけで、サンプリング
間隔を簡単に可変することが実現できます。
Interface Corporation
- 61 -
関数解説
★rtf_create
RT-FIFO を生成します。
第 1 引数で、RT-FIFO の ID 値を。第 2 引数でサイズを指定します。
生成した RT-FIFO を破棄するには、rtf_destroy 関数を用います。
★rtf_create_handler
この関数は、ユーザ空間から RT-FIFO にデータが書き込まれた際に、呼び出される関数を
登録します。
第 1 引数には、RT-FIFO 作成時に指定した ID 値を指定します。
第 2 引数には、RT-FIFO にデータが書き込まれた際に、呼び出される関数を指定します。
この関数は、ユーザ空間から RT-FIFO にデータが書き込まれた際に呼ばれる関数を登録し
ますが、カーネル空間からアクセスされた(rtf_put、rtf_get 関数を使用した)場合に呼ばれる
関数を登録するには、rtf_create_rt_handler 関数を使用します。
★pthread_wakeup_np
この関数を呼ぶことで、指定した RTLinux スレッドの実行を再開することができます。
★pthread_suspend_np
引数により指定した RTLinux スレッドを pthread_wakeup_np が呼び出されるまで中断しま
す。
3.7.4 Linuxプロセスの動き
ここでは、Linuxプロセスの動きに注目して見てみます。
まず、LinuxプロセスとRTLinuxモジュールとの関係を、下図に示します。
カウンタ値取得
RT-FIFO(rtf3)
RTLinux
モジュール
main
コマンド指令
RT-FIFO(rtf1)
図 3-11 LinuxプロセスとRTLinuxモジュールとのRT-FIFOの関係
Linuxプロセスは、2つのRT-FIFOをオープンし、それぞれコマンド指令と、RTLinux
モジュールからのカウンタ値の取得に使用しています。
以降では、処理順に、これらの処理を説明します。
Interface Corporation
- 62 -
(25∼33行目:RT-FIFOのオープン)
25∼33行のopen関数は、RTLinuxモジュールのinit_module関数内のrtf_create関数で
作成したRT-FIFOをオープンします。
Linuxプロセスでは、RT-FIFOは、open、read、write、closeの低レベル入出力関数
にてアクセス可能です。
rtf_create関数の第1引数で指定するID値と、open関数で用いるデバイス名は、相対
的な関係があります。
両者の関係を、以下に示します。
Linuxプロセス側
RTLinuxモジュール側
“/dev/rtf1”
GET_HANDLER_FIFO = 1
“/dev/rtf2”
GET_TASK_FIFO
=2
“/dev/rtf3”
SET_TASK_FIFO
=3
RTLinuxプログラミングでのRT-FIFOは、”/dev/rtfXX”というデバイス名にてアク
セス可能です。そして、デバイス名の数値の部分は、rtf_create関数のID値が、そ
のまま割り当てられます。
(36∼41行目:RTLinuxモジュールの周期実行開始)
38行目のwrite関数は、RTLinuxモジュールに対してRtlinuxスレッドの周期実行ス
タートを指示しています。
CMD_STRUCT構造体のidメンバ変数にID_START、valueメンバ変数に500(実行周
期を500msに指定している)を指定しています。
ここで与えられたパラメータは、RTLinuxモジュールのハンドラ(my_handler)を経
由し、RTLinuxスレッド(my_task)に、コマンドとして伝達されます。
(44∼57行目:RTLinuxモジュールからのカウンタ値取得)
44∼57行の処理は、RTLinuxモジュール内のRTLinuxスレッドからカウンタ値を順
次読み取っていき、読み取った値が10を超えた時点で、whileループを抜けていま
す。
もう一度、『3.7.3 RTLinuxモジュールの動き』のRTLinuxスレッドの処理を見返し
てみてください。51∼56行で、内部counter変数をインクリメントして、RT-FIFO
に値を書き込んでいると思います。ここで書き込んだ値が、この処理の中で読み
取られているのです。
Interface Corporation
- 63 -
次に、select関数と一連のマクロの動きを説明します。
この処理は、まずselect関数で、RT-FIFOにデータが入ってくるのを待機し、デー
タを受け取ると、FD_ISSETマクロで、確かに自分のRT-FIFOにデータが入ってい
ることを確認した上で、データを読み取っています。
select 関数
RT-FIFO のハンドル(fd_ret)に対
し、データ待ちを行う。
有る
読み取り
fd_ret データ有り?
RT-FIFO(fd_ret)からデータを取
FD_ISSET で検出
り込む
無い
図 3-12 select関数の処理の流れ
リストでは、1つのRT-FIFOからしか値を読み取って無いので、わざわざselect関数
を用いる必要はありませんが、複数のRT-FIFOを同時に読み取ろうとした時、こ
のselect関数を使用することで、データのあるRT-FIFOからのみデータを読み取る
ことが可能となります。
select 関数
複数の RT-FIFO のハンドルに対
し、データ待ちを行う。
有る
読み取り 1
データ有り?
RT-FIFO からデータを取り込む
FD_ISSET で検出
無い
有る
データ有り?
読み取り 2
RT-FIFO からデータを取り込む
FD_ISSET で検出
無い
図 3-13 複数のRT-FIFOのselect処理想定例
Interface Corporation
- 64 -
(60∼65行目:RTLinuxモジュールの周期実行停止)
62行のwrite関数は、RTLinuxモジュールに対してRTLinuxスレッドの周期実行スト
ップを指示しています。
先の実行開始の時は、idメンバ変数にID_STARTをセットしていましたが、ここで
はID_STOPをセットしています。ここで与えられたパラメータは、RTLinuxモジュ
ールのハンドラを経由してRTLinuxスレッドに対して、ストップ命令として伝えら
れます。
以上で、基本的なRTLinuxプログラミングは終わりです。
どうでしたか?リアルタイムプログラミングといえど、思ったより難しくなかっ
たのでは無いでしょうか?
以降のプログラムは、
本書の最後に挙げた
「参考文献」
や、
インターネット、
RTLinux
インストール時のサンプルプログラム、弊社ドライバ付属のサンプルプログラム
を参考に進めて行ってください。
関数&用語解説
★Linux プロセスが終了しても、RTLinux モジュールは自動で取り外されません。
Linux プロセスの実行が終了しても、RTLinux モジュールは自動で取り外されることはあ
りません。
Linux プロセスの処理を終了させた後、lsmod コマンドを打ち込んでみてください。RTLinux
モジュールが常駐していることに気付くことでしょう。
# lsmod
Module
module3
rtl_sched
rtl_fifo
rtl_posixio
rtl_time
rtl
Size
1472
43104
9968
7184
10000
27184
Used
0
0
0
0
0
0
Interface Corporation
by
(unused) ← RTLinux モジュールが常駐している
[module3]
[module3]
[rtl_fifo]
[module3 rtl_sched rtl_posixio]
[module3 rtl_sched rtl_fifo rtl_posixio rtl_time]
- 65 -
★Linux プロセスは、複数起動が可能か?
先ほどのプログラムを実行していて、疑問に思いませんでしたか。
「sample3 を複数同時に動かすことは、できるのだろうか?」
実際に何度かテストした結果を示します。
ケース1:「fail open /dev/rtf1」と表示されて終了。
ケース2:「get counter:11」と表示されて終了
ケース1は、ある Linux プロセスが RT-FIFO をオープン中かつ使用中なので、オープンで
きなかったことを意味します。
これは、このサンプルでは、RT-FIFO がオープンできるプロセスは、たかだか 1 つだけで
あり、共有オープンはできないことを意味します。
ケース2は、ちょっと複雑です。これは、以前のプロセスが、RT-FIFO に格納されたバッ
ファデータがクリアされない内にオープンし、意図しないデータを読んで終了してしまっ
たことを意味します。
このことから、Linux プロセスと RTLinux モジュールを繋ぐ RT-FIFO を複数に増やせば、
複数の Linux プロセスから制御できそうだ、と予想できます。
★open
第 1 引数には、オープンするデバイスのパスを指定し、第 2 引数には、読み取り用のフラ
グ O_RDONLY もしくは、書き込み用のフラグ O_WRONLY を指定しています。
★ディスクリプタ
open 関数の実行が成功すると、戻り値としてファイルディスクリプタが返されますが、こ
の値は、現在使用されていないファイルディスクリプタのうち、負でない最小の値が返さ
れます。
★FD_ZERO、FD_SET マクロ
ここで使用している FD_ZERO マクロと FD_SET マクロは、select 関数に関係のあるもの
です。後方に記述している select 関数は、複数のディスクリプタに変化があるまで待つ関
数です。ここでは、RT-FIFO しか監視する必要はないため、複数のファイルディスクリプ
タを監視する必要はありません。そのため、最初に FD_ZERO マクロにより指定したファ
イルディスクリプタの集合(ここでは rfds)をクリア(消去)し、次に、先ほどクリアしたファ
イルディスクリプタの集合(rfds)に RT-FIFO のディスクリプタ(fd_ret)を設定することによ
り、select 関数は、RT-FIFO の変化のみを監視するようになります。
★タイムアウト
select 関数では、指定したファイルディスクリプタの変化を監視する時間を設定すること
ができます。
select 関数の第 5 引数として、タイムアウト時間に 0 を指定するとすぐに処理が抜け、NULL
を指定すると、指定したファイルディスクリプタに変化があるまでずっと待ちます。
Interface Corporation
- 66 -
★select
select 関数の第 1 引数には、監視するファイルディスクリプタの個数を指定します。例え
ば 5 を指定すると、0∼4 の 5 つのファイルディスクリプタを監視します。ここでは、使用
できるファイルディスクリプタの最大値である FD_SETSIZE を指定しています。
第 2 引数には、読み込み可能かどうかを監視するファイルディスクリプタの集合、第 3 引
数には書き込み可能かどうかを監視するファイルディスクリプタの集合、第 4 引数には例
外の監視を行うファイルディスクリプタの集合を指定します。ここでは、RT-FIFO からデ
ータを読み出すので、先ほど FD_ZERO マクロ、FD_SET マクロで設定したファイルディ
スクリプタの集合を第 2 引数に設定します。
第 5 引数には、select 関数のタイムアウト時間を設定する timeval 構造体を指定します。こ
こを NULL に指定すると、タイムアウトが発生しなくなりますので、ご注意ください。
★FD_ISSET
FD_ISSET マクロは、第 2 引数で指定されるファイルディスクリプタの集合に、第 1 引数
で指定されるファイルディスクリプタが存在するかをチェックします。FD_ISSET が真を
返せば、集合の中に指定したファイルディスクリプタが存在することになります。
★read
read 関数の第 1 引数には読み込みを行うファイルディスクリプタ、第 2 引数には読み込み
データを格納するバッファ、第 3 引数には読み込みを行うサイズを指定します。戻り値に
は、実際に読み込み取得できたバイト数が返されます。
★コンパイル時の注意事項
RTLinux のプログラムを作成する際には、Makefile 内で「rtl.mk」を include することで、
コンパイルに必要なフラグや識別子が全てセットされます。
ここで注意が必要なのは、このフラグにコードの最適化を行う-02 や、デバッグ情報を添
付する-g 等がデフォルトで指定されていることです。
rtl.mk をそのまま使用する場合には、使用されているフラグを確認してください。そうし
ないと、バグを埋め込む原因になるかもしれません。
(1) 修正前
while(*memadr & CMPL);
(2) 修正後
while(1){
BYTE Status;
memcopy(&Status, memadr, 1);
if(Status & CMPL) break;
}
上記(1)のコードでは、アドレス memadr の値を参照して、データが書き込まれた場合にル
ープを抜ける処理となっています。
このコードを最適化フラグを有効にしてコンパイルすると、環境によってはメモリの参照
を一度しか行わない場合があります。そうなってしまうと、最初に参照した時点でメモリ
の値が 0 であった場合に、無限ループに入ってしまいます。
最適化によるコンパイラの動作は環境にも依存します。一概には言えませんが、デフォル
トで設定されているコンパイラのフラグを念頭に置いておくと、デバッグ時に無用な苦労
を減らせるかもしれません。
Interface Corporation
- 67 -
第4章 弊社RTLinux用ソフトウェアの導入
4.1 RTLinux対応ソフトウェアの特長
弊社では、Linux/RTLinux対応ドライバソフトウェアとして、下記の製品を用意し
ています。
型式
GPG-1604
GPG-1609
GPG-1900
GPG-2000
GPG-2746C
GPG-2910C
GPG-2x72C
GPG-3100
GPG-3300
GPG-3500
GPG-4101
GPG-4115
GPG-4116
GPG-4141
GPG-4301
GPG-4304
GPG-4851
GPG-4910
GPG-5520
GPG-6105
GPG-6106
GPG-6201
GPG-6202
GPG-6204
GPG-7204
GPG-7302
GPG-7400
GPG-8208
GPG-8210
名称
Linux/RTLinux用フラッシュメモリIDEモジュール
Linux/RTLinux用PCカードATAドライバセット
RASボード Linux/RT対応ドライバソフトウェア
デジタル入出力ボード Linux/RT対応ドライバソフトウェア
パラレル入出力ボードLinux/RT対応ドライバソフトウェア
ロジックアナライザボード Linux/RT対応ドライバソフトウェア
バスマスタ方式デジタル入出力ボードLinux/RT対応ドライバソフト
ウェア
アナログ入力ボード Linux/RT対応ドライバソフトウェア
アナログ出力ボード Linux/RT対応ドライバソフトウェア
アナログ入出力ボード Linux/RT対応ドライバソフトウェア
無手順通信ボード Linux/RT対応ドライバソフトウェア
LAP-B通信ボード Linux/RT対応ドライバソフトウェア
HDLC通信ボード Linux/RT対応ドライバソフトウェア
調歩同期シリアル通信ボード Linux/RT対応ドライバソフトウェア
GP-IBインタフェースボード Linux/RT対応ドライバソフトウェア
GP-IBインタフェースボード Linux/RT対応ドライバソフトウェア
CANインタフェース Linux/RT対応ドライバソフトウェア
メモリンクボード Linux/RT対応ドライバソフトウェア
カラー画像入力ボード Linux/RT対応ドライバソフトウェア
パルスジェネレータボード Linux/RT対応ドライバソフトウェア
パルスカウンタボード Linux/RT対応ドライバソフトウェア
エンコーダカウンタボード Linux/RT対応ドライバソフトウェア
ユニバーサルカウンタボード Linux/RT対応ドライバソフトウェア
エンコーダカウンタボード Linux/RT対応ドライバソフトウェア
モーションコントローラボード Linux/RT対応ドライバソフトウェア
DCモータドライバボード Linux/RT対応ドライバソフトウェア
モーションコントローラボードLinux/RT対応ドライバソフトウェア
プリンタボード Linux/RTLinux対応ドライバソフトウェア
プリンタボード Linux/RTLinux対応ドライバソフトウェア
Interface Corporation
- 68 -
弊社のLinux/RTLinux対応ソフトウェアは、以下の特長があります。
・RTLinux 3.1に対応したドライバモジュールを提供
・弊社PCI/CompactPCIボードに対応
・付属のテストドライバを使用すれば、ボードをコンピュータに実装せずにソフ
トウェアの動作を確認することが可能
・サンプルプログラムにより、具体的なリアルタイム処理の構築例を用意
・再コンパイルによって様々なカーネルバージョンのLinuxに対応可能
(ディストリビューションに依存しないモジュールを作成可能)
・弊社独自のインストーラを使用して、容易にインストール/アンインストール
が可能。ソフトウェアのバージョンチェック等も独自に行います
・PDFとテキストの2種類のヘルプファイルを用意して、コンソール,X Window
両方の開発環境に対応
・付属のシェルスクリプトをカスタマイズすることで、ターゲット環境用のイン
ストーラを作成可能
・各カテゴリごとにチュートリアルを用意して、具体的なシステムの構築例を
解説
ソフトウェアのインストール方法等は、従来のLinux対応ソフトウェアから変更さ
れていますので、『4.2 RTLinux対応ソフトウェアのインストール』をご参照くだ
さい。
4.2 RTLinux対応ソフトウェアのインストール
それでは、GPG-2000(デジタル入出力ボード Linux/RTLinux対応ドライバソフト
ウェア)を例に、インストールの手順を説明します。
(1) ソフトウェアの入手
Linux/RTLinux対応ドライバソフトウェアの入手方法については、弊社技術支援セ
ンタまでお問い合わせください。
(2) インストールFD(フロッピーディスク)の確認
インストールFDの準備ができたら、ドライブに挿入してマウントを行い、インス
トールFDの内容を確認してください。
# mount –t vfat /dev0/fd0H1440 /mnt/floppy
# ls /mnt/floppy
pg2000i.tgz gpg2000.ver readme.txt install
Interface Corporation
- 69 -
展開後のファイル構成が以下のようになっているか確認してください。
rgpg2000.(アーキテクチャ名).tgz RTLinux用アーカイブ
common.tgz
共通モジュール用アーカイブ
readme.txt
最新情報記載ファイル
instal
※1
インストール用シェルスクリプト
install_ja.txt
インストール補助ファイル
product.txt
インストール補助ファイル
sh4.txt
インストール補助ファイル ※2
※1
Web版には含まれていません。
※2
IBM PC/AT互換機用には含まれていません。
(3) インストーラの起動
インストールFDからinstallを実行すると、インストール画面が表示されます。
画面の指示に従って、インストールを実行してください。
# sh install
**************************************************************
GPG-2000 DIO(PCI/C-PCI)Linux/RT
File Name
Version
: INSTALL
: 1.0
Copyright 2003 Interface Corporation. All right reserved.
**************************************************************
インストールするドライバを選択してください。
Linux ドライバ(l)
RTLinux ドライバ(r)
中止(q)
選択:t
Linux用のドライバのみをインストールする場合は「l」、RTLinux用のドライバの
みは「r」を入力してEnterキーを押します。
Interface Corporation
- 70 -
----------------------------------------GPG-2000 DIO(PCI/C-PCI)Linux/RT
アプリケーションのインストール先の選択
----------------------------------------このディレクトリにインストールするには[OK(y)]を選択
してください
別のディレクトリにインストールする場合は[変更(C)]を
選択してください
インストールディレクトリ=/usr/src/interface
[OK(y)] [変更(c)] [戻る(b)] [中止(q)]
選択:y
次にインストールを行うディレクトリを決定します。
デフォルトでは「/usr/src/interface」となっていますが、インストール場所を変更した
い場合は「c」、そのままデフォルトにインストールする場合は「y」を入力してから、
Enterキーを入力します。
----------------------------------------GPG-2000 DIO(PCI/C-PCI)Linux/RT
セットアップタイプ
----------------------------------------標準(t)
カスタム(u)
[戻る(b)] [中止(q)]
選択:t
セットアップタイプの選択を行います。
「標準(t)」でインストールを行うと、全てのファイルをインストールします。
必要なファイルのみを選択してインストールする場合は、カスタムの「u」を入力して
Enterキーを押します。
----------------------------------------GPG-2000 DIO(PCI/C-PCI)Linux/RT
コンポーネントの選択
----------------------------------------Linux
+ ■ 開発環境(d)
+ ■ セットアップ(s)
■:設定
□:解除
[戻る(b)] [中止(q)]
選択:
Interface Corporation
- 71 -
カスタムを選択すると、インストールするコンポーネントを選択する画面が表示され
ます。ここで、コンポーネントを選択して、さらに詳細なインストールファイルの選
択へ進みます。
各コンポーネントはそれぞれ以下の様な特長を持ちます。
開発環境
開発用のファイルをまとめたコンポーネントです。ドライバのオブジェクト、ソースフ
ァイル、サンプルプログラムのソースファイル、API関数のライブラリ、ドキュメント
等が含まれます。
セットアップ
開発用のファイルをまとめたコンポーネントです。ドライバのオブジェクト、API関
数のライブラリ、デバイス設定ユーティリティ等が含まれます。
----------------------------------------GPG-2000 DIO(PCI/C-PCI)Linux/RT
開発環境コンポーネントの選択
----------------------------------------Linux
+ 開発環境(d)
+ □ 1: ドキュメント
+ □ 2: インクルードヘッダ
+ ■ 3: ドライバソースオブジェクト
+ □ 4: ライブラリ
+ ■ 5: サンプルプログラム
+ ■ 6: 共通モジュール
+ ■ 7: 共通ユーティリティ
■:設定
□:解除
[OK(y) ] [戻る(b)] [中止(q)]
選択:
インストールを行うコンポーネントに対応する番号を入力すると、コンポーネン
ト名の左にあるチェックボックスの設定/解除が切り替わります。
全ての設定が完了したら、「b」を入力してコンポーネントの選択から戻ります。
----------------------------------------GPG-2000 DIO(PCI/C-PCI)Linux/RT
----------------------------------------ファイルをインストールしてよろしければ
[OK]を選択してください。
[OK(y) ] [戻る(b)] [中止(q)]
選択:
Interface Corporation
- 72 -
ここで、ファイルをインストールして良いかを確認してきますので、問題なければ「y」
を入力してインストールを開始してください。
----------------------------------------GPG-2000 DIO(PCI/ C-PCI)Linux/RT
ファイルのコピー
----------------------------------------gpg2000/i386/rtl/drivers/ver2404/rcp2000.o
書庫内のファイル = 2002-2-14 16:25:14
/lib/modules/2.4.4-rtl/misc/rcp2000.o
インストール先 = 2002-2-14 16:26:42
タイムスタンプが異なりますが上書きしますか?
[はい(y) ] [いいえ(n)] [全て上書き(a)]
選択:
もし、すでにインストールされているファイルが存在する場合には、タイムスタンプ
を表示してファイルの上書きを確認しますので、書庫内のファイルのタイムスタンプ
が新しければ上書きするようにしてください。
(後述するデバイス番号の設定ユーティリティは、全カテゴリで共通のプログラムを
使用します。他のGPGシリーズのソフトウェアがインストールされた状態でインスト
ールを行うと、上記の様な上書き確認を行いますのでタイムスタンプを確認して新し
いバージョンのファイルを残すようにしてください。)
ドライバ等のファイルのコピーが完了後、コンポーネントの選択で標準もしくはセッ
トアップを選択していた場合は、デバイス番号の設定ユーティリティが起動します。
デバイス番号設定プログラムが起動すると、現在コンピュータもしくはユニットに設
置されている弊社PCIデバイスが表示されますので、各デバイスに対してユニークな
デバイス番号を割り振ります。デフォルトで割り振られる番号を使用する場合には、
そのまま終了してください。
デバイス番号の設定が終了すると、GP-IBボード等の一部の型式では、ボードの初期
値を設定する初期設定プログラムが起動します。(GPG-2000をご使用の場合は所期
設定プログラムは起動しません。)
Interface Corporation
- 73 -
全ての設定が完了後、下記のような画面が表示されます。
----------------------------------------GPG-2000 DIO(PCI/ C-PCI)Linux/RT
インストールファイルの完了
----------------------------------------readme.txtを表示しますか?[y/n]y
最後にreadme.txtの表示を確認しますので、readme.txtを読む場合は「y」、読まない場
合は「n」を入力してください。
=======================================================
GPG-2000 DIO(PCI/ C-PCI)Linux/RT 最新情報ドキュメント
株式会社インタフェース
=======================================================
● お問い合わせ
● 改訂履歴
+---------+----------------------------------+
| 1.00-01 | 新規作成
|
+---------+----------------------------------+
[製品概要]
[対象ボード]
[ファイル一覧]
--続ける--
「y」を選択すると、readme.txtの内容が表示されますので、Enterキーで画面をスクロ
ールさせて読み進んでください。(「q」を入力するとで終了します。)
以上でドライバソフトウェアのインストールは完了です。
(4) ドライバモジュールの組み込みに失敗した場合
インストールの途中でドライバモジュールの組み込みに失敗した場合には、
「gpg-2000.oの組み込みに失敗しました」というようなメッセージが表示されます。
ドライバのコンパイルを行った環境と組み込みを行う環境でカーネルのバージョ
ンが異なる場合には、ドライバのモジュール組み込み時にエラーが発生する場合
があります。
弊社が標準で用意しているドライバモジュールの対応カーネルバージョンを表
に示します。
Interface Corporation
- 74 -
表 4-1 弊社ソフトウェアの標準対応カーネル
カーネルバージョン
RTLinux対応ドライバ
Linux対応ドライバ
2.2.18
―
○
2.2.19
○
―
2.4.4
○
○
○:対応ドライバを標準で用意
※RTLinux 3.1はカーネル2.2.19および2.4.4に対応しています。
※各ドライバソフトウェア製品と対応カーネルは、各製品のReadmeにてご確認
ください。
これら以外のカーネルバージョンのLinux,RTLinuxにドライバをインストールする場
合には、一度全てのファイルをインストール後に、ドライバモジュールの再コンパイ
ルを行うことで、ご使用の環境で使用可能なドライバモジュールを作成できます。
installスクリプトを実行時に、標準もしくは開発環境のコンポーネントを選択してインス
トールを行います。
インストールが完了したら、インストールを行ったディレクトリに移動して、ドライバモ
ジュールのmakeを実行してください。
# cd /usr/src/interface/gpg2000/i386/rtl/drivers/src
# make
makeが完了後、/lib/modules/2.4.4-rtl/miscディレクトリに移動して、insmodコマンドを実行
してモジュールの組み込みを行います。
# cd /lib/modules/2.4.4-rtl/misc
# insmod rcp2000.o
インストール時、当該ディレクトリにパスが追加されているので、次のようにモジュール
を組み込むことも出来ます。
# insmod rcp2000
← .oを付けずに、組み込む
モジュールの組み込みに成功したら、GPG-2000の場合、新たにデバイスノードを作成する
必要がありますので、デバイス番号設定ユーティリティ(dpg0101)を実行してデバイス
ノードの作成を行ってください。
# dpg0101
**************************************************
Setup Utility
-------------------------------------------------Version: 1.03-04
-------------------------------------------------Copyright 2003 Interface Corporation.
All rights reserved.
**************************************************
Enter the model number of the product: GPG/GPH-2000
Interface Corporation
- 75 -
デバイス番号設定ユーティリティ(dpg0101)を起動すると上記の様な画面が表示されま
す。ここで、設定を行いたいドライバソフトウェアの型式を入力して、デバイス番号の設
定を行ってください。(デバイス番号設定ユーティリティの詳細については、各ソフトウ
ェアのHelpをご参照ください。)
以上で、手動によるデバイスドライバの組み込みは完了です。
※GPG-2000では、デバイスドライバ組み込み用スクリプトinsdio.sh, setup_shを用意してい
ます。GPG-2000ではこちらをご利用ください。
4.3 テストドライバを使用した動作確認
弊社Linux/RTLinux対応ソフトウェアには「テストドライバ」が付属しています。
これは、実際にインタフェースボードを実装していない状態でも、サンプルプログラ
ムや、ユーティリティを動作させることができます。
(一部ユーティリティやサンプルプログラムでは動作しない場合もあります。)
RTLinux用のテストドライバはモジュール形式で提供していますので、insmodコマン
ドで組み込みを行います。
# cd /usr/src/interface/gpg2000/i386/rtl/drivers/exp/ver2404
# insmod rcp2000t.o
※正規版のドライバを組み込んでいる場合は、
テストドライバを使用できませんので、
一度rmmodコマンドでモジュールを外してから、テストドライバを組み込んでくだ
さい。
テストドライバの組み込みが完了したら、DIOのサンプルプログラムのディレクトリ
に移動してコンパイルを行い、サンプルプログラムを起動して動作することを確認し
てください。
(テストドライバ機能は、ハードウェアのエミュレートを行うものではありません。各
ドライバソフトウェアのテストドライバ機能については、付属のHelpファイルをご参
照ください。)
Interface Corporation
- 76 -
4.4 RTLinux対応ソフトウェアのアンインストール
ソフトウェアのアンインストール手順は、以下の通りです。
「RTLinux対応ソフトウェアのインストール」でソフトウェアをインストールした
ディレクトリに移動します。
# cd /usr/src/interface/gpg2000/i386
インストールを行ったディレクトリの中に、アンインストール用のシェルスクリ
プトを用意していますので、実行してください。
# sh UNINSTALL
************************************************************
**
GPG-2000 DIO(PCI/C-PCI)Linux/RT
File Name
:
UNINSTALL
Version
: 1.0
Copyright 2003 Interface Corporation. All right reserved.
************************************************************
**
GPG-2000 をアンインストールしますか?[y/n]y
アンインストールを行うディレクトリを指定してください。
アンインストールするディレクトリ:/usr/src/interface/gpg2000
アンインストールが完了しました。
#
以上で、ソフトのアンインストールは完了です。
指定したディレクトリ内のファイルは全て削除します、開発用のファイル等を保
存されている場合は、アンインストール実行前にバックアップを取るようにして
ください。
Interface Corporation
- 77 -
第5章 ドライバモジュールの優先度設定
5.1 割り込みハンドラの優先度設定(DPG-0102)
通常、RTLinuxのリアルタイムカーネルで割り込みを使用する場合には、rtl_request_irq
関数を使用して、割り込みハンドラを登録します。
List5-1「rtl_request_irq」による割り込み登録
1
2
3
4
5
6
7
8
1
2
3
4
5
6
#include <rtl_core.h>
unsigned int nIRQ = 9; //使用するIRQを9に設定
int rtl_request_irq(nIRG, my_handler );
・
・
・
int rtl_free_irq(nTRQ);
//割り込みハンドラの登録
//割り込みハンドラの解除
unsigned int my_handler(unsigned int irq, struct pt_regs *regs)
{
・
・
・
}
List5-1のように、割り込み(IRQ)番号と割り込み発生時に実行したい関数(my_handler)
を、rtl_request_irqの引数に指定することでハンドラとして登録します。
割り込みハンドラを解放したい場合には、rtl_free_irq関数にIRQ番号を指定します。
ただし、現時点のRTLinuxの仕様では、IRQ番号に対してハンドラの割り当てを行うと、
別のハンドラを登録できません。(登録しようとしてもエラーを返します。)
一般的なPCを使用している場合、PCI/CompactPCIのバススロットは、複数のスロット
でIRQを共有する仕様になっている場合がほとんどですが、RTLinuxでは通常のままだ
と割り込みを共有できません。
そこで、弊社のRTLinux対応ドライバソフトウェアでは、独自に割り込みの共有,優
先度切り替えを行うモジュール(dpg0102.o)を用意しており、弊社PCI/CompactPCI
ボード間の割り込みの共有をサポートしています。
Interface Corporation
- 78 -
GPG-2000の割り込みの設定は、下図の様な流れで行います。
割り込み優先度設定
dpg0102
RT-FIFO
ユーザモジュール
dpg0102p.o
API 関数の Call
ハンドラの Call
dpg0102.o
ドライバモジュール
rcp2000.o
ハンドラの登録
ハードウェア割り込み
図 5-1 割込み設定の流れ
RTLinuxに対応したドライバモジュール本体は「rcp2000.o」と言う名称のモジュールにな
ります。API関数をRTLinuxモジュールからコールした場合は、このドライバモジュールを
通してデバイスの制御が行われます。
「dpg0102.o」は弊社RTLinux用デバイスドライバで共通の割り込みモジュールとして使用
します。
各ボードごとの割り込みの優先順位を確認、もしくは変更したい場合には、「dpg0102p.o」
が必要となります。このモジュールを組み込んでから、「dpg0102」を実行することで、
割り込みの優先順位を設定することが可能です。
# insmod dpg0102p.o
# /usr/bin/dpg0102
IRQ
07
07
10
10
11
DEV
4115
2760
4115
2727
4115
No.
2
2
3
1
1
Pri
1
2
0
1
1
Do you want to change the priority ?[y/n]
Interface Corporation
- 79 -
「dpg0102」を実行すると上記のような画面になり、現在使用中の弊社PCI/CompactPCIボ
ードの一覧が表示されます。表示されるデータの意味は、次のようになります。
項目
IRQ
DEV
No.
Pri.
内容
ボードが使用する割り込みの番号を示します。
上記の例では、IRQ7とIRQ10がそれぞれ2枚のボードから共有されていること
がわかります。
ボードのDeviceIDを示します。
弊社PCI/CompactPCIボードでは、型式からアルファベットをのぞいた数字4桁
が、DeviceIDとなります。
例)CTP-4115 →
DEV = 4115
PCI-2726C →
DEV = 2726
ボードのデバイス番号を示します。
『RTLinux 対応ソフトウェアのインストール』で設定した、各ボードのデバ
イス番号が表示されています。上記の例では、4115が3枚使用されていますが、
それぞれ異なるデバイス番号が割り振られていることがわかります。
割り込みのPriority(優先番号)が0∼15の数値で設定されています。
0が最も優先度が高く、15が最も低い値となります。(ここで設定した優先番
号はRTLinuxスレッドの優先度とは関係ありません。IRQが競合している各ボ
ードの割り込み処理間での相対的な優先度を示しています。)
以上が、割り込み優先番号情報の見方になります。
優先度の設定を変更したい場合には、上記の表が表示されたあと「y」を入力します。
Do you want to change the priority ?[y/n]y
次に、設定を変更するボードのDeviceID(DEV)を入力します。
Enter the device id : 4115
続けて、デバイス番号(No.)を入力します。
Enter the device number : 2
最後に優先番号(Pri)を0∼15の数値から入力します。
Enter the priority : 3
設定が完了すると、また最初の画面が表示されます。
IRQ
DEV
No.
Pri
07
2760
2
2
07
4115
2
3
10
4115
3
0
10
2727
1
1
11
4115
1
1
Do you want to change the priority ?[y/n]
Interface Corporation
- 80 -
4115(No.2)の優先番号を、1から3に変更したため、表の順番が2760(No.2)と入れ
変わっているのが分かります。
ここで、設定を終了する場合には、「n」を入力してください。再び設定を変更する場
合には「y」を入力して、先ほどの手順で設定を繰り返します。
この優先番号は「dpg0102.o」を取り外すとクリアされます。再起動時には再び優先番
号の設定を行うようにしてください。
(デバイスドライバの自動組み込みを設定している場合でも、優先番号の設定値は初
期化されます。)
また、「dpg0102」を使用しなかった場合には、デフォルト値としてドライバモジュー
ルの組み込まれた順番に0から優先番号が割り振られます。
/etc/rc.d/rc.localにドライバの自動組み込みを記述している場合には、各ボード用モジュ
ールのinsmodを記述する順番を変更することで、優先番号の設定を行うことも可能で
す。
Interface Corporation
- 81 -
第6章 RTLinuxでのソフトウェア開発
6.1 RTLinuxプログラムのデバッグ
6.1.1 rtl_printf( ) + 弊社デバイスドライバのデバッグ機能を使用した方法
従来、Linux用のドライバモジュールのデバッグでは、モジュール内でprintk関数を使
用して行っていましたが、RTLinuxプログラムのデバッグではprintk関数の替わりに
rtl_printf関数を使用して行います。
rtl_printf関数の使用方法は、ほぼprintf関数と同様です。
注意点としては、カーネル空間では基本的に浮動小数点演算を行うことができないた
め、RTLinuxモジュール内で浮動小数点を扱う場合には下記の関数を使用して、明示
的にする必要があります。
int pthread_setfp_np( pthread_t thread, int flag );
また、弊社が提供するLinux/RTLinux用のデバイスドライバにはデバッグを支援する機
能が用意されています。(テストドライバにはこの機能はありません。)
insmodでモジュールの組み込みを行う際に、デバッグオプションを指定することで、
API関数実行時のデバッグ情報をmessagesログに出力します。(コンソール上で実行し
た場合には、画面上にも表示されます。)
【書式】
# insmod rcp4116 rcp4116_debuglevel = <デバッグレベル>
表 6-1 デバッグ機能の例
デバッグレベル
0
1
2
4
16
32
機能
分類
デバッグ情報を出力しません
関数呼び出しトレース
詳細エラー情報
ボードリソース情報
送信フレーム情報
受信フレーム情報
(デフォルトレベル)
共通デバッグ情報
カテゴリ固有デバッグ情報
※ オプションを指定しなかった場合には、デフォルトのデバッグレベル0が適用され、デ
バッグ情報は出力されません。
※ 複数のデバッグ情報を表示したい場合には、デバッグレベル値をORした値で指定
してください。
Interface Corporation
- 82 -
例)関数呼び出しトレース、ボードリソース情報を出力したい場合は、
# insmod rcp4116 rcp4116_debuglevel = 5
の様にモジュールの組み込みを行います。
デバッグレベル1,2,4,8は、全てのカテゴリで共通のオプションとなります。
具体的に表示する内容は、以下のようになります。
項目
内容
関数呼び出しトレース
(デバッグレベル1)
API関数の呼び出しを行うと、使用した関数の関数名,入
力パラメータ情報を出力します。
パラメータは、16進数の場合には数値の前に0xが付加さ
れ、ポインタ型の場合には[ ]で表示されます。
<例>
HdlcOpen( 1, [0xce803b4a])
関数の戻り値のエラーコードよりも詳細なエラー情報を
出力します。例えば、パラメータエラーの場合には、どの
パラメータがエラーになったのかまで出力を行います。
(使用する関数によって、詳細は変更になります。)
<例>
HdlcOpen : ulLineMode parameter eror
以下のPCIリソース情報を出力します。
デバイスID、サブシステムID、リビジョンID、I/Oアドレ
ス、メモリアドレス、IRQ番号などが出力されます。
<例>
DeviceID : 4116 , SubSystemID : 0x0101 , RevisionID :
0x0001
I/O Address : 0xd000 , Memory Address : 0x0000 , IRQ : 9
詳細エラー情報
(デバッグレベル2)
ボードリソース情報
(デバッグレベル4)
デバッグレベル8,16,32,64は、各カテゴリで固有のオプションとなります。
カテゴリごとに異なるデバッグ情報を出力しますので、デバッグ情報の詳細について
は、各ソフトウェアに付属するオンラインヘルプをご参照ください。
ここでは、GPG-4116(HDLC)を例に、デバッグ情報の内容を紹介します。
項目
送信フレーム情報
(デバッグレベル16)
受信フレーム情報
(デバッグレベル32)
Interface Corporation
内容
送信フレームのフレームサイズ、フレームデータ(先頭4バ
イト、16進表示)を出力します。
<例>
SendFrame : length=164 data=31 32 33 34
受信フレームのフレームサイズ、フレームデータ(先頭4バ
イト、16進表示)を出力します。
<例>
ReceiveFrame : length=45 data=54 3A 2D 10
- 83 -
★確認方法
ドライバから出力されたデバッグ情報は/var/log/messages に追加されていきます。
このファイルを参照することで、ドライバのデバッグ情報を取得することができます。
★注意事項
デバッグ情報の出力を有効にすると、システムの負荷が非常に高くなってしまいます。こ
れは、デバッグ情報の出力時にディスクアクセスが発生するために起こる現象です。パフ
ォーマンスの低下も起こりますので、デバッグ情報の出力はアプリケーションのバッグの
時のみ有効にし、リリース時では必ず無効にするようにしてください。
6.1.2 デバッガ(gdb + RTDebugger)を使用する方法
次に、デバッガを使用する方法について説明します。
RTLinuxにはRTLinuxモジュールの部分のデバッガが付属しています。
このデバッガは、
gdb
やDDDなどのLinux用のデバッガにRTLinuxモジュール部分のトレースを行う機能を拡張
するものです。
これにより、通常のgdbやDDDなどではトレースすることのできない、RTLinuxモジュール
の内部のコードについてトレースすることが可能になります。(Linuxカーネル内のトレ
ースを行うことはできません。)
RTLinux用のデバッガを使用する場合には、RTLinuxのコンパイル(『第2章 RTLinuxのイ
ンストール』のRTLinuxのコンパイル)で、「make xconfig」を実行して表示されるRTLinux
のオプション設定で、CONFIG_RTL_DEBUGを有効にする必要があります。
「Support option」をクリックして、オプションメニューを開きます
図 6-1 RTLinux Configration メインメニュー画面
make xconfigのメニューダイアログが表示されたら、Support optionsをクリックして、オプ
ションメニューを開きます。
Interface Corporation
- 84 -
「RTLinux Debugger」をyにします
図 6-2 Support options メニュー画面
オプションメニューのRTLinux Debuggerの項目がyになっていることを確認してくだ
さい。デフォルトではyになっています。
図 6-3 RTLinux Debugger のHelp表示
その後は、『RTLinuxのインストール』の手順に従って、RTLinuxのコンパイル/インスト
ールを実行すれば、RTLinux用のデバッガが使用可能になります。
Interface Corporation
- 85 -
(以降の手順は、『RTLinuxのインストール』まで完了しているものとして進めます。)
それでは、RTLinuxに付属のサンプルプログラム「hello.c」を使用して、デバッガを動かし
ます。
デバッグを開始する前に必要な作業としては、breakpointの設定とコンパイルオプション
「-g」を指定して再コンパイルを行う必要があります。
通常、gdbを使用してデバッグを行う場合には、デバッガ起動中に「run」コマンド等でプ
ログラムを開始できるため、元のソースコードには手を加えなくてもデバッグを行えます。
(breakpointはgdb実行中に設定可能です。)
ところが、gdb実行中には「.o」モジュールの組み込み(insmod)は、行うことができま
せん。
RTLinuxのデバッガは基本的にgdb(DDD)のインタフェースを使用して行うため、モジュ
ールを組み込みはデバッガを起動する前に行わなければいけません。
「hello.o」モジュールは、insmodコマンドで組み込みを行うと動作が開始しますので、デ
バッグを実行する前に動作を停止させたい部分には、あらかじめbreakpoint( )を挿入してお
く必要があります。
それではまず、エディタでhello.cを開き、デバッグに必要なbreakpoint( )とrtl_debug.hを追
加します。
# cd /usr/src/rtlinux/rtlinux-3.1/examples/hello
# emacs hello.c
List 6-1 「hello.c」のstart_routineの修正箇所
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <rtl.h>
#include <time.h>
#include <pthread.h>
#include <rtl_debug.h>
pthread_t thread;
void * start_routine(void *arg)
{
struct sched_param p;
p . sched_priority = 1;
pthread_setschedparam (pthread_self(), SCHED_FIFO, &p);
pthread_make_periodic_np (pthread_self(), gethrtime(), 500000000);
breakpoint();
while (1) {
pthread_wait_np ();
rtl_printf("I'm here; my arg is %x¥n", (unsigned) arg);
}
return 0;
}
Interface Corporation
- 86 -
この、breakpoint( )はi386では単にint3を実行して、例外を発生しているだけですので、0除
算などで例外が発生した場合にも、デバッガにbreakpointとしてアタッチされます。
(「rtlinux-3.1/include/rtl_debug.h」の30行目を参照)
次に、モジュールにデバッグ情報を付加するために、コンパイルオプションに「-g」が必
要になります。
RTLinux用のモジュールをコンパイルする際には、rtl.mkをインクルードしてmakeの設定を
行います。rtl.mkのデフォルト設定にはCFRAGSに「-g」はあらかじめ設定されていますの
で、とくに修正の必要はありません。
また、「-fomit-frame-pointer」がフラグに設定されている場合には、それを削除する必要が
あります。
# emacs ../../rtl.mk
List 6-2 「rtl.mk」
1
2
3
4
5
6
7
8
#Automatically generated by RTLinux Makefile
RTL_DIR = /usr/src/rtlinux/rtlinux-3.1
RTLINUX_DIR = /usr/src/linux
INCLUDE=
-I/usr/src/linux/include
-I/usr/src/rtlinux/rtlinux3.1/include
-I/usr/src/rtlinux/rtlinux-3.1/include/compat
CFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -fno-strict-aliasing pipe
-march=i686 -DMODULE -DMODVERSIONS
-include
/usr/src/rtlinux/linux2.4.4/include/linux/modversions.h
-g -D__RTL__ -D_LOOSE_KERNEL_NAMES -O2 -I/usr/src/linux/include
-I/usr/src/rtlinux/rtlinux-3.1/include
-I/usr/src/rtlinux/rtlinux-3.1/include/compat
-I/usr/src/rtlinux/rtlinux-3.1/include/posix
ARCH = i386
CC = gcc
CXXFLAGS = -D__KERNEL__ -Wall -Wstrict-prototypes -fno-strict-aliasing
-pipe
-march=i686 -DMODULE -DMODVERSIONS
-include
/usr/src/rtlinux/linux2.4.4/include/linux/modversions.h
-g -D__RTL__ -D_LOOSE_KERNEL_NAMES -I/usr/src/linux/include
-I/usr/src/rtlinux/rtlinux-3.1/include
-I/usr/src/rtlinux/rtlinux-3.1/include/compat
-I/usr/src/rtlinux/rtlinux-3.1/include/posix -fno-exceptions
-fno-rtti
準備が完了しましたら、helloの再コンパイルを行い、「rtl_debug.o」と「hello.o」を順番に
組み込みます。組み込みの順番を間違えると正常に組み込みが行えません。
# make
# insmod ../../debugger/rtl_debug.o
# insmod hello.o
rtl.debug: exception 0x3 in hello (EIP=0xc88de0d0), thread id
0xc44b8000: (re)start GDB to debug
Interface Corporation
- 87 -
ここで、デバッガモジュールのメッセージが表示されて、hello.oの実行が中断されている
のがわかります。
次に、gdbを起動して、モジュールのデバッグを開始します。
# gdb hello.o
GNU gdb 19990928
Copyright 1998 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License,
and you are
welcome to change it and/or distribute copies of it under certain
conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for
details.
This GDB was configured as "i686-pc-linux-gnu"...
(gdb)
gdbのプロンプトが表示されますので、ここでgdbのコマンドを実行します。
(gdb)list
1
#include <rtl.h>
2
#include <time.h>
3
#include <pthread.h>
4
#include <rtl_debug.h>
5
pthread_t thread;
6
7
void * start_routine(void *arg)
8
{
9
struct sched_param p;
10
p . sched_priority = 1;
まず、「list」を実行して、モジュールのソースコードを表示します。
hello.cのソースコードが表示されます。
モジュールの実行は、RT-FIFOを介して行います。デフォルトではrtf10をデバッグ用の端
末として使用する設定になっていますので、targetコマンドを実行します。
(gdb)target remote /dev/rtf10
start_rutine (arg=0x0) at hello.c:17
17
pthread_wait_np ();
(gdb)
「hello.o」のモジュール実行を再開すると、breakpoint( )を設定した次の命令に移ったとこ
ろで、実行待ちの状態になります。
ステップ実行でトレースしたい場合には、「step」もしくは「s」コマンドを入力するとス
テップ実行を行います。
(gdb)target remote /dev/rtf10
start_rutine (arg=0x0) at hello.c:17
17
pthread_wait_np ();
(gdb)
Interface Corporation
- 88 -
さらに、ブレークポイントを追加したい場合には、行数や関数名(スレッド名)を指定し
て「breakpoint」(又は「b」)コマンドを実行します。
(gdb)breakpoint 18
Breakpoint 1 at 0xc88de0d5: file hello.c, line 18
(gdb)
モジュールをブレークポイントまで実行する場合には、「continue」(又は「c」)コ
マンドを実行します。
以下に、gdbの基本的なコマンドについて紹介します。
また、gdbで使用可能なコマンドについては、(gdb)プロンプト上で「help」を実行
することで表示されます。詳細な使用方法についてはそちらをご参照ください。
コマンド
breakpoint
[line]
step [num]
continue
list [line]
run [arg...]
backtrace
print
[symbol]
clear [line]
内容
ブレークポイントを[line]行目に設定します。
[line]の代わりに関数名(スレッド名)も使用できます。
break ,
b
[num]行分ステップ実行を行います。
[num]は省略可能です。(省略した場合は1行分)
モジュール(プロセス)の実行を再開します
ソースコードのリストを表示します。
行数,関数名等を引数にとります。
引数を省略した場合には、前回表示したlistの続きが表示されます。
gdb起動時の引数で指定したプログラムもしくは、
「file」,
「exec-file」
コマンドで設定したプログラムを実行します。※1
引数には実行ファイルに渡す引数を指定できます。
コードのバックトレースを行います。
[symbol]の内容を表示します。
s
指定した行のブレークポイントを解除します。
引数には、関数名等を指定することも可能です。
引数を省略した場合、全てのブレークポイントを解除します。※2
target
ターゲットプロセスやマシンを設定します。
[protcol]
RTLinuxのモジュールをデバッグする場合は、remoteマシンと
/dev/rtf10を介して通信を行う設定でデバッグ実行を行います。
kill
gdbの下で動作しているプログラムのプロセスを終了させます。※3
pwd
現在のWorking directoryを表示します。
cd [directory] Working directoryを変更します。
quit
gdbを終了します。
※1
短縮形
c
l
r
bac
p
cl
ta
pw
q
RTLinuxモジュールの実行をrunコマンドで行った場合、モジュールの実行がgdbの制御
下からはずれてしまい、breakpoint等が使用できなくなります。
※2
RTLinux用にソース中に埋め込んだbreakpoint( )は解除されません。
※3
RTLinuxのデバッグ中にこのコマンドを実行すると、モジュールがgdbの制御下からは
ずれてしまいます。
Interface Corporation
- 89 -
★デバッグ使用時の機能
(gdb)の端末下でコマンド入力を行う際に、以下のような機能を使用できます。
・ コマンドを省略して実行可能。
コマンドが特定可能な字数に達していれば、2,3 文字だけ入力して残りの文字を省略し
て実行できます。また、使用頻度の高いコマンド(step,breakpoint 等)に関しては、
「s」や「b」のように一文字で使用することも可能です。
・ TAB キーの使用
通常のコンソール端末と同じ感覚で、TAB キーを使用したコマンドの補完が可能です。
・ Enter キーの使用
Enterーキーのみを入力すると、前回実行したコマンドを続けて実行します。たとえば
STEP 実行を行う場合に、最初の1回のみ「step」(「s」)コマンドを実行すれば、後
は Enter キーを入力するだけでステップ実行を繰り返し行います。
6.2 リアルタイム性の評価
通常のLinux用ドライバとRTLinux用ドライバを使用した場合の性能の違いについては、各
カテゴリのチュートリアルで詳しく解説を行っています。
性能評価の方法もカテゴリに応じた方法が必要となりますので、そちらをご参照下さい。
(各カテゴリのチュートリアルも、弊社Web siteからダウンロード可能となっておりま
す。)
ここでは単純に、RTLinuxスレッドを周期実行した場合に、どの程度の精度でRTLinuxスレ
ッドが呼ばれているのかを測定します。
Interface Corporation
- 90 -
RTLinuxスレッドの周期実行は、『6.1.2 デバッガ(gdb + RTDebugger)を使用する方法』
で解説したサンプルプログラムのhelloを使用して確認します。
List 6-3 「hello.c」のソースコード修正
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
#include <rtl.h>
#include <time.h>
#include <pthread.h>
#include <rtl_time.h>
pthread_t thread;
hrtime_t tasktime[201];
void * start_routine(void *arg)
{
int I;
struct sched_param p;
p . sched_priority = 1;
pthread_setschedparam (pthread_self(), SCHED_FIFO, &p);
pthread_make_periodic_np (pthread_self(), gethrtime(), 100000);
for(I = 0; I < 201; i++) {
pthread_wait_np ();
tasktime = gethrtime(void);
}
for(I = 1; I < 201; i++) {
rtl_printf(“cycle time is : %ld¥n”, tasktime[i] – tasktime[i-1]);
}
return 0;
}
int init_module(void) {
return pthread_create (&thread, NULL, start_routine, 0);
}
void cleanup_module(void) {
pthread_delete_np (thread);
}
List 6-3のソースコードの網掛けがしてある部分が、元のサンプルプログラム「hello.c」か
ら修正を行った部分です。
周期実行の間隔を100(μs)で実行するように、変更を行います。
元々、周期実行を行うRTLinuxスレッドの中で「I'm here; my arg is %x」と表示を行って
いた部分では、替わりにgethrtime( )関数を使用してCPUタイマのカウント値を取得します。
この関数では、起動時からの経過時間を(ns)単位で取得します。
201回ほど取得したあと、カウント値の差分を取り、rtl_printf( )で出力しています。
gethrtime関数を使用するためには、<rtl_time.h>をインクルードする必要があります。(4
行目)
Interface Corporation
- 91 -
修正が完了したら、makeを行ってRTLinuxモジュールを組み込みます。
# cd /usr/src/rtlinux/rtlinux-3.1/examples/hello
# make
・
・
・
# insmod hello.o
モジュールを組み込んで、しばらくしてからモジュールを取り外します。
(コンソール上で組み込みを行った場合には、画面上にrtl_printf( )の実行結果が表示され
ます。)
# rmmod hello
システムのログに実行結果が残っていますので、表示します。
# tail –20 /var/log/messages
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
Feb 22 20:34:15 linux kernel: cycle time is :
99840(ns)
99296(ns)
99552(ns)
100864(ns)
103616(ns)
94752(ns)
101184(ns)
100512(ns)
100896(ns)
98464(ns)
100576(ns)
100256(ns)
99520(ns)
101248(ns)
99776(ns)
98176(ns)
102496(ns)
98272(ns)
101152(ns)
98336(ns)
上記の様な結果が表示されるはずです。
今回試した環境では、200回の平均値で99964 (ns)、標準偏差値は719.5940577(ns)と言う
結果となりました。
この数値は、周期スレッド内での処理をほとんど行っていませんので、純粋にリアルタイ
ムカーネルの処理精度が現れているといえます。
Interface Corporation
- 92 -
6.3 I/O公開資料(PDF)の利用
弊社では、ボード制御用のI/Oポート資料を公開しています。
PCI製品のI/O公開資料は、弊社Web siteのダウンロードページから無償でダウンロード可
能となっています。
下記のURLを開き、I/O公開資料の欄にチェックを入れて製品型式を入力してSerchを行っ
てください。
ダウンロードページ
http://www.interface.co.jp/download/search.asp
また、CompactPCIボードについては、製品マニュアルにI/Oポート一覧を記載しています。
詳細な制御方法を記載したI/O公開資料については、別途資料請求を行っていただく必要が
ございます。
I/O公開資料はPDF形式で提供致しております。
ご使用になるOS用の「Adobe Reader」を、下記のURLからダウンロードしてご利用くださ
い。
Adobe Reader ダウンロードページ
http://www.adobe.co.jp/support/downloads/main.html
Interface Corporation
- 93 -
第7章 組み込みLinux概要
7.1 組込みLinux概要
現在、組み込み環境にLinux系のOSを使用する動きが盛んになっています。
それでは、組み込み環境とは、一体どういった物でしょうか?
一般に、WindowsやLinux等のOSを使用する環境としては、パソコンと呼ばれるPC(主に
PC/AT互換機)が有名ですが、それ以外にも、専用のシステムを動かすための組み込み機
器にもOSが使用されている場合があります。
具体的には、産業用のロボットを制御するコントローラや、ルータを制御する為に組み込
まれたOS等もこれに当たります。
組み込み機器の特長としては、使用する目的がはっきり決まっている場合が多いため、そ
のシステムの概要にあわせて、ハードウェアの構成が大きく変わってきます。
前述した汎用機のPCを小型化した物を使用する場合もあれば、標準の入出力を持たない装
置に、OSを書き込んだROMが搭載されているような物もあります。
このような組み込み用のOSとしては、VxWorks,ITRON,Windows Embedded等の商用の
リアルタイムOSや、自作の専用OS等が使用されてきました。
近年、Linuxがこの様な組み込み分野で使用される機会が増えている理由としては、様々
なアーキテクチャ(x86,Alpha,PowerPC,SPARC等)に対応していることや、強力なネ
ットワーク機能を搭載していること等が考えられます。
組み込み用のOSとして必要な機能(要件)としては、次のような事柄があります。
・ OSを使用するのに必要とするリソース(容量)が少ないこと
・ 必要な機能を選択して、カスタマイズが可能であること。
・ リアルタイム性を持っていること。
従来の組み込み分野ではハードウェアの機能が非常に制限されており、少ないリソースで
動作する小型の専用OSが使用されることがほとんどでした。
Interface Corporation
- 94 -
しかし、ハードウェアの機能が強化されるに従って使用可能なリソースが増大し、組み込
み用のOSでも多くの機能が必要とされるようになってきました。
特にネットワーク機能については、家電製品にまで搭載されるようになっており、Linux
を組み込みで使用するメリットが増大していると言えます。
また、ソースコードが公開されているため、使用するハードウェア環境にあわせてカスタ
マイズが可能な点もメリットとなります。
反面、商用のリアルタイムOSではサポート体制が確立しており、強力な開発環境もセット
で用意されていることが多いのですが、フリーのLinux(RTLinux)を使用する場合には環
境に合わせたツールを自分で用意する必要があり、Linuxに関するスキルもある程度必要
になることが問題点といえます。
Interface Corporation
- 95 -
第8章 補足資料
8.1 インストールに関する参考情報
ここでは、インストールに関連する参考情報を示します。
RTLinux 3.2 pre1の導入について
2003年1月時点で、RTLinux 3.2 pre1がFSMLabsから公開されています。
(2003年12月現在は、RTLinux 3.2 pre2が公開されています)
プレリリース版ですが、先行して導入を試されたいお客様のため、現在 弊社で確認して
いる内容について説明します。
導入に必要なファイルは、次の通りです。
ファイル名
rtlinux-3.2-pre1.tar.bz2
Linuxカーネルへのパッチを行うファイルは、patchesディレクトリにあります。
ファイル名
kernel_patch-2.2.19
kernel_patch-2.4.4
kernel_patch-2.4.17-rtl3.2-pre1.bz2
kernel_patch-2.4.18-rtl3.2-pre1.bz2
kernel_patch-2.4.19-rtl3.2-pre1.bz2
項目
カーネル2.2.19に対応したパッチファイル
カーネル2.4.4に対応したパッチファイル
カーネル2.4.17に対応したパッチファイル
(bzip2圧縮されています)
カーネル2.4.18に対応したパッチファイル
(bzip2圧縮されています)
カーネル2.4.19に対応したパッチファイル
(bzip2圧縮されています)
カーネル2.4.17∼2.4.19用のパッチファイルはbzip2圧縮されており、bunzip2コマンド等を
使用して ファイルを展開する必要があります。
kernel_patch-2.4.19-rtl3.2-pre1.bz2ファイルを展開する例>
# bunzip2 kernel_patch-2.4.19-rtl3.2-pre1.bz2
カーネル2.2.19とカーネル2.4.4用のパッチファイルは展開済みであり、そのまま使用でき
ます。
インストール作業自体は第2章のRTLinux 3.1のインストール方法と変わりません。
Interface Corporation
- 96 -
★カーネル 2.4.17 のパッチについて
弊社では、カーネル 2.4.17 のパッチを導入する際、カーネルの Makefile を以下のように修
正して確認しました。
VERSION = 2
PATCHLEVEL = 4
SUBLEVEL = 17
EXTRAVERSION =
↓
VERSION = 2
EXTRAVERSION を指定する
PATCHLEVEL = 4
SUBLEVEL = 17
EXTRAVERSION = -rtl3.2-pre1
確認した組み合わせ:
コンピュータ:エプソンダイレクト MT-3500
ディストリビューション:VineLinux 2.5
確認したボードとドライバ:PCI-3521、GPG-3100
なお、他にも、カーネル 2.4.17 のみパッチ当て時にエラーが発生するのを確認しています。
RTLinux 3.2 pre2の導入について
2003年12月現在、RTLinux 3.2 pre2がFSMLabsから公開されています。
ここでは、上記RTLinux 3.2 pre1との違いを中心に、現在 弊社で確認している内容につい
て説明します。
導入に必要なファイルは、次の通りです。
ファイル名
rtlinux-3.2-pre2.tar.bz2
Linuxカーネルへのパッチを行うファイルは、patchesディレクトリにあります。
ファイル名
kernel_patch-2.4.19-rtl3.2-pre2
kernel_patch-2.4.20-rtl3.2-pre2
kernel_patch-2.4.21-pre5-rtl3.2-pre2
項目
カーネル2.4.19に対応したパッチファイル
(bzip2圧縮されています)
カーネル2.4.20に対応したパッチファイル
(bzip2圧縮されています)
カーネル2.4.21-pre5に対応したパッチファ
イル
(bzip2圧縮されています)
pre2では、カーネル2.4.4および2.2.19のパッチは同梱されていません。
インストール作業自体は、第2章のRTLinux 3.1のインストール方法と変わりません。
Interface Corporation
- 97 -
Red Hat Linux 7.3/8.0にRTLinuxを導入する際の注意点
Red Hat Linux 7.3/8.0にRTLinuxをインストールする際の注意点を説明します。
FSMLabsで公開されている文書には、Red Hat Linux7.x環境下にRTLinux 3.1を導入する際の
How-toが掲載されています。
それには、カーネルをコンパイルする際、使用するコンパイラをgccからkgccに変更するよ
う促しています。
弊社では、以下のRPMファイルにてkgccをインストールし、RTLinux 3.1の起動を確認しま
した。
ファイル名
kgcc-1.1.2-40.i386.rpm
本ファイルは、Red Hat 7.0のCDかインターネット上から入手できます。
★Red Hat Linux と RTLinux 3.2 pre1 組み合わせについて
Red Hat Linux と RTLinux 3.2 pre1 の組み合わせでは、特定のカーネルバージョン(2.4.17 以
降)の組み合わせにおいて、RTLinux リアルタイムカーネルの導入時にハングアップ、また
はパッチ当て時にエラー等の現象が出る場合があることを確認しています。
Interface Corporation
- 98 -
8.2 その他のTips
ここでは、幾つかTipsを紹介します。
insmod等のコマンドが呼び出せない
特定のディストリビューションによっては、insmod等のコマンドを呼び出そうとする
と、「command not found」が返ってくる場合があります。
これは、コマンドが格納されているディレクトリに対して検索パスが設定されていな
いため、起こることが多いです。
こういった時は、exportコマンド等で検索パスを追加するか、シェルの設定ファイル
に検索パスを追加します。
現在の検索パスに、/sbinを追加する例>
# export PATH=$PATH:/sbin
RTLinuxリアルタイムカーネルを組み込もうとするとエラー
RTLinuxリアルタイムカーネルを組み込もうとすると、以下のメッセージに出会うことが
あります。
例>
# sh scripts/insrtl
modules/rtl.o: create_module: Operation not permitted
modules/rtl_time.o: unresolved symbol rtl_printf
modules/rtl_time.o: unresolved symbol rtl_request_local_irq
…
これは、このコマンドを実行する権限を持っていないために、起こる場合が多いです。
こういった時は、suコマンドでrootにログインするか、最初からrootでログインします。
Interface Corporation
- 99 -
ドライバをinsmodしようとするとunresolved symbol
ドライバをinsmodしようとすると、次のエラーが発生する場合があります。
ドライバをinsmodする例>
# insmod dpg0100.o
dpg0100.o: unresolved symbol vsprintf_Rsmp_13d9cea7
dpg0100.o:
Hint: You are trying to load a module without a GPL compatible license
and it has unresolved symbols. Contact the module supplier for
assistance, only they can help you.
これは、モジュールをinsmodする際に解決しなければならない関数が見つからなかったこ
とを示します。
この場合は、ドライバを再コンパイルし、ファイルをinsmodで組み込みます。
あるいは、Linuxカーネルを構築する際、
「Loadable module support」→「Set version information
on all module symbols」を「n」に設定することで、回避できる場合もあります。
Interface Corporation
- 100 -
技術資料紹介
弊社では下記の技術資料を提供しております。
詳しくは、弊社Web site(www.interface.co.jp)、または弊社窓口までお問い合わせ下さい。
カタログ
PRM-0061
PRM-0062
PRM-0063
CPZカタログ(日本語版)
PCIカタログ(日本語版)
CSIカタログ(日本語版)
チュートリアル
TUT-0056
TUT-0055
TUT-0054
TUT-0053
TUT-0050
TUT-0048
TUT-0044
TUT-0043
TUT-0041
TUT-0040
TUT-0039
TUT-0038
TUT-0037
TUT-0036
TUT-0034
TUT-0033
TUT-0032
TUT-0031
TUT-0030
TUT-0029
TUT-0028
TUT-0027
TUT-0026
TUT-0025
TUT-0024
TUT-0023
TUT-0022
TUT-0021
TUT-0020
TUT-0019
TUT-0018
TUT-0017
TUT-0016
TUT-0015
TUT-0014
TUT-0008
TUT-0007
TUT-0006
TUT-0005
TUT-0004
TUT-0003
TUT-0002
TUT-0001
チュートリアル XP Embedded OS構築編
チュートリアル 画像入力ボード
CANチュートリアル
モーションコントロールチュートリアル
RTLinuxによるモーションコントローラボード制御プログラミング チュートリアル(GPG-7400用)
RTLinuxによるカウンタボード制御プログラミング チュートリアル
RTLinuxによるメモリ共有インタフェースボード制御プログラミング チュートリアル
RTLinuxによる調歩同期シリアル通信ボード制御プログラミング チュートリアル
RTLinuxによるGP-IBボード制御プログラミング チュートリアル
RTLinuxによるDAボード制御プログラミング チュートリアル
RTLinuxによるADボード制御プログラミング チュートリアル
RTLinuxによるDIOボード制御プログラミング チュ-トリアル
RTLinuxによるHDLCボード制御プログラミング チュートリアル
RTLinuxによるPCI/CompactPCI/CardBus制御入門書(導入編)
Visual C++によるPPI入門書
Visual Basicによるメモリ共有インタフェース入門書
Visual C++によるメモリ共有インタフェース入門書
Visual Basicによるカウンタ入門書
Visual C++によるカウンタ入門書
Visual BasicによるHDLC入門書
Visual C++によるHDLC入門書
Visual BasicによるGP-IB入門書
Visual C++によるGP-IB入門書
Visual BasicによるDIO入門書
Visual C++によるDIO入門書
Visual BasicによるDA入門書
Visual C++によるDA入門書
Visual BasicによるAD入門書
Visual C++によるAD入門書
Visual Basicによるモーションコントローラ入門書
Visual C++によるモーションコントローラ入門書
メモリンクを使用した負荷分散システム事例チュートリアル
Visual BasicによるPPI入門書
モーションコントロールチュートリアル
Microsoft Visual Studio .NET移行ガイド
拡張ユニット チュートリアル(問題解決編)
拡張ユニットチュートリアル(入門編)
C(98)/ISA製品からPCI/CompactPCI製品への移行チュートリアル(DOS編)
DOSによるLAP-B入門書
DOSによるAD入門書
LinuxによるPCI/CompactPCI/CardBus制御 入門書
PCI-ISAバスブリッジチュートリアル
PCI-Cバスブリッジチュートリアル
技術情報資料
初めてのCANインタフェース
Linux, リアルタイムLinux移植(SH-4)経験談及び当社の今後の取り組みについて
LinuxからPCI/CompactPCIボードを制御する方法
ActiveXコントロールによるシステム組み込み技術
CompactPCIへの置き換え+システム構築/移行ガイド
MS-DOSからPCI/CompactPCIボードを制御する方法
Interface Corporation
- 101 -
参考文献
・ALESSANDRO RUBINI 著、山崎 康宏、山崎 邦子 訳、「LINUXデバイスドラ
イバ」オライリー・ジャパン、1998年、ISBN4-900900-73-7
・舟木 陸議、羅 正華 著、「Linuxリアルタイム計測/制御 開発ガイドブック」株
式会社秀和システム、1999年、ISBN4-87966-849-4
・森 友一朗、薬師 輝久、馬場 秀忠 著、「RTLinuxリアルタイム処理プログラミ
ングハンドブック」株式会社秀和システム、2000年、ISBN4-7980-0056-6
・藤広 哲也 著、「組み込み型Linux導入・開発ガイド」株式会社すばる舎、2002
年、ISBN4-88399-181-4
・「Interface 1999年11月号」CQ出版株式会社、1999年、ISSN0387-9569
・「Interface 2001年6月号」CQ出版株式会社、2001年、ISSN0387-9569
・「Interface 2002年3月号」CQ出版株式会社、2002年、ISSN0387-9569
Interface Corporation
- 102 -
RTLinuxによるPCI/CompactPCI/CardBus制御入門書(導入編)
2005年 10月 Ver. 1.6 発行
発行所
〒732-0828
広島県広島市南区京橋町10-21
TEL 082-262-7777
FAX 082-262-5066
ISD-7059-16
価格 ¥2,100 (定価 ¥2,000 + 消費税 ¥100)
本書の内容の一部または全部を、無断で転載することを禁止します。
本書の内容は、将来予告なく変更することがありますので、あらかじめご了承くださ
い。© 2002, 2005 Interface Corporation. All rights reserved.
チュートリアル
チュートリアル
RTLinuxによるPCIボード・CompactPCIボード制御(導入編)
RTLinuxによるPCI/CompactPCI/CardBus制御入門書(導入編)
TUT-0036 Ver. 1.3
TUT-0036 Ver. 1.6
www.interface.co.jp
Fly UP