RTAI入門(9)[最終回]どう書くか?その3

この記事からの続きです。

とにかくテンプレートのように、コピペしてすぐ使える!という形式を目指しています。新たにRTAIアプリを組む時は、今回からの記事から必要な部分だけコピペして下さい。

なお、ここで使用するサンプルコードはすべてこちらの記事で構築した環境にて確かめています。

今回の記事で出来るようになる事は、次の通りです。

  • 割り込み処理

割り込み処理

そもそも割り込みって何?という方は、IRQ 割り込み といったキーワードで検索してみてください。

以前の記事ではかなり省略して書きましたので、ここで割り込み処理について詳しくご説明します。

さて、割り込み処理は、カーネルモード、ユーザーモードそれぞれの場合で処理方法が異なります。まずは、それぞれの特徴についてご説明します。

カーネルモードにおける割り込み

カーネルモードでは、割り込み発生時に、割り込み関数が直接呼び出されます。

howto_rtai_09_00図1 割り込み発生時に、関数が呼び出される

これはマイコンプログラミングではおなじみの方法ですね。

手順1: どのIRQの割り込みが発生した時に、どの関数を呼び出したいか登録する

手順2: 割り込みが発生したら、その関数が呼び出される

こんな感じで、割り込みが発生したときに処理したいコードを、割り込み関数に用意しておきます。

ユーザーモードにおける割り込み

これはRTAIのとてもユニークな点なのですが、ユーザーモードの中でも割り込みを扱う事が出来ます。

howto_rtai_09_01図2 割り込み発生時に、ブロック解除される

これは、1ms毎に処理をする、といった場合のプログラミング方法に似ています。

手順1: どのIRQの割り込みが発生した時に、どのタスクのブロックを解除したいか登録する

手順2: タスクを実行する

手順3: タスクの中で、 rt_irq_wait( ); を呼び出す。すると、割り込みが来るまでブロックする。

手順4: 割り込みが発生したら、rt_irq_wait( ) でブロックしているタスクが、ブロック解除される

このような感じで、rt_irq_wait( ) 関数の下に、割り込み発生時に処理したいコードを書いておきます。すると、割り込みが発生したときにブロック解除が行われ、用意しておいたコードが実行されます。

ちなみに、この方式はユーザーモードだけでなく、カーネルモードでも有効です。ですから、こっちの方法で記述しておけば、ユーザーモード、カーネルモード、どちらでも実行可能です。

ユーザーモードで割り込みを使うために

ユーザーモードで割り込みを使用するには、RTAIインストール時に、RTAIのコンパイルオプションを変えないといけません

こちらの記事では、make menuconfig したときにオプションを変えていません。しかし、このままではユーザーモードでの割り込みは使えません。

そこで、次のような設定に変更します。

howto_rtai_09_02図3 User-space interrupts を有効にする

make menuconfig時に、Base System => Other Features => User-space interrupts にチェックを入れます。

そしてSaveしてコンパイルすると、ユーザーモードでの割り込みが使えるようになります。

ユーザーモードの割り込みコード

rt_task_init_schmod でリアルタイムタスクを作ってから、rt_task_delete でそれを削除するまでの間に、次のようなコードを書きます。

	/* Make this task realtime */
	mlockall( MCL_CURRENT | MCL_FUTURE );
	rt_make_hard_real_time();

	rt_request_irq_task( 7 /* IRQ */, task1, RT_IRQ_TASK, 1 );
	rt_startup_irq( 7 /* IRQ */ );
	rt_enable_irq( 7 /* IRQ */ );

	/* do realtime job */
	while( 1 )
	{
		rt_irq_wait( 7 /* IRQ */ );
		/* do interrupt job here */
		;
		/* enable interrupt */
		rt_ack_irq( 7 /* IRQ */ );
	}

	rt_pend_linux_irq( 7 /* IRQ */ );
	rt_release_irq_task( 7 /* IRQ */ );

ここで、次の点に注意して下さい。

  • IRQは7としていますが、これは適宜書き変えて下さい。/* IRQ */ と書いてある所がそうです。
  • rt_request_irq_taskの第二引数は、RT_TASK* の変数です。自分自身のタスクのRT_TASK*を渡して下さい。
  • 割り込み発生時の処理は、rt_irq_wait と、 rt_ack_irq の間で行います。
  • 上記の例ではwhile(1)で無限ループしていますが、適当な条件でループを抜けるようにしてください

サンプルプログラム

サンプルとして、パラレルポートを使用します。PCに付属のパラレルポートには、データの入出力をしたり、入力から割り込みを発生させたりする機能があります。

そこで、パラレルポートからの出力を、パラレルポートの割り込み入力に入れる事によって、割り込みを発生させるようにしました。

なお、本サンプルの作成にあたっては、Rio’s Home Page様の、こちらのページを参考にさせていただきました。貴重な情報がふんだんにある、とても素晴らしいサイトです。

パラレルポートの設定

実は、パラレルポートの制御がサッパリうまくいきませんでした。パラレルポートからの出力をオシロで見ていたのですが、Lowに張り付いたまま、うんともスンともいいません。

なんとか動かしてやろうと四苦八苦していたのですが、どうにもなりませんでした。

そんな時、ふと「パレるポートのI/Oアドレスを変えたら動いた」というような記述を見ましたので、それをマネてみました。

パラレルポートのアドレスというと、0x378 が有名です。しかし、これではなぜか動かないということで、0x3BC に変更しました。すると・・・なんと動くではありませんか!

原因は良く分かりませんが、とにかく動いたのでヨシとします。

そんなわけで、パラレルポートの設定は以下のような感じです。

howto_rtai_09_03

図4 /proc/ioports の内容

howto_rtai_09_04図5 /proc/interrupts の内容

I/Oアドレスは 0x3BC, IRQは 7 です。

パラレルポート結線

パラレルポートの、

4番ピン: データ出力ビット2

10番ピン: 割り込み入力

を結線しました。

howto_rtai_09_05図6 4番ピンと10番ピンを結線

なぜこのピンをチョイスしたかというと、

4番ピン:右から4番目のピン

10番ピン:左から4番目のピン

ということで左右対称です。これで万が一、ピン番号を左右勘違いしていても大丈夫!

プログラムコード

ソースコードはこちらです。

ここには、2つのタスクがあります。

メインタスク: 割り込みカウンタの値を表示しつつ、パラレルポート出力をON/OFFします

割り込み用タスク: 割り込みがあるたびに、割り込みカウンタをインクリメントします。そして、パラレルポート出力をOFFします。

すると、次のような事が置きます。

メインタスクが、パラレルポート出力をONする → 割り込みがかかる → 割り込みタスクが起動する → パラレルポート出力をOFFする

こうして、パラレルポートはほんの一瞬だけONされる事になります。

これを実行すると、パラレルポートは次のような波形になります。

howto_rtai_09_06図7 パラレルポート出力波形

1ディビジョン 5マイクロ秒ですから、上記の例ではONしてからOFFするまで12マイクロ秒かかっています。

I/Oポートの制御にはおよそ1マイクロ秒かかります。それを差し引くと、割り込みが来てから割り込みハンドラが動き出すまでに11マイクロ秒かかっている、と言えます。

かなり遅いですが、所詮は汎用PC。まぁ、こんなものでしょう。

もっとタイムクリティカルな事をしたければ、マイコンをつかうか、いっそFPGAでも使った方が良いような気がします。

更なる情報源

今回のシリーズを書くにあたり、次の情報を参考にしました。

おわりに

9回にわたった記事のテーマは、「RTAIを使ってリアルタイムシステムを作る際に、ほんのちょっとでも工期を短縮出来るように」というものです。

しかし実は、これには裏のテーマがありました。それは、FreeHILSを作る際、RTAIの挙動をしっかり把握しておきたい。そうじゃないと、なんだか気持ち悪い!というものです。

実際、こうして記事にまとめていくうちに、私自身はとても勉強になりました。そして、RTAI周りの仕様がスッキリと理解できた気持ちがします。

ただし、FreeHILSへの適用を念頭においているため、APIのごくごく1部しかご紹介できませんでした。しかし、RTAIにはもっと沢山の機能があります。もしも、「こんな機能ないかなぁ?」と感じられたら、ぜひRTAIの各種ドキュメントをあたってみてください。