RTAI入門(8)どう書くか?その2

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

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

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

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

  • メールボックス
  • FIFO
  • セマフォ
  • Net_RPC

メールボックス

メールボックスを作成するには、

  1. メールボックスを作成する
  2. メールボックスにデータを送信する
  3. メールボックスからデータを取り出す

という手順が必要です。

よりくわしい情報は、<RTAIのソース>\doc\generated\html\api\group__msg.html を参照して下さい。

メールボックスについてざっくりお知りになりたい方は、こちらの記事を参照してください。

メールボックスを作成する

	mbx = rt_typed_named_mbx_init("MYMBX1", 32, FIFO_Q );
	if( NULL == mbx )
	{
		printf("Failed to initialize mbx\n");
		return( 0 );
	}

メールボックスを作成するには、rt_typed_named_mbx_init 関数を使用します。

第一引数: メールボックス名 6文字以下の文字列で指定します

第二引数: メールボックスのデータサイズ

第三引数: メールボックスにアクセスするタスクの順番。 FIFO_Qなら早い者勝ち。PRIO_Qなら優先順位の高いもの勝ち。RES_Qというのもありますが、これは良く分かりません・・・

メールボックスにデータを送信する

	char buf[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
	MBX* mbx = (MBX*)rt_get_adr( nam2num("MYMBX1") );
	rt_mbx_send( mbx, buf, sizeof(buf) );

ここで、rt_get_adr に渡している MYBMX1 は、メールボックスの名前を指定します。この名前は、rt_typed_named_mbx_init に渡したものと同じです。

rt_mbx_send関数には、次の引数を与えます。

第二引数:データを格納してあるバッファ

第三引数:データサイズ

メールボックスからデータを受信する

	char buf2[64];
	MBX* mbx = (MBX*)rt_get_adr( nam2num("MYMBX1") );
	rt_mbx_receive( mbx, buf2, 16 );

ここで、rt_mbx_receive関数には、次の引数を与えます。

第二引数: データを格納したいバッファ

第三引数: 受信したいデータサイズ

メールボックスを削除する

	rt_mbx_delete( mbx );

メールボックスを使い終わったら、かならず削除して下さい

メールボックスを削除しないままアプリを終了したとしても、メールボックスはまだ生き残っています。そのため、必ず明示的にメールボックスを削除してやる必要があります。

FIFO

メールボックスと同様に、FIFOを使ったデータのやり取りも可能です。

howto_rtai_08_00より詳しい情報は、<RTAIのソース>\doc\generated\html\api\group__fifos__ipc.html を参照してください。

FIFOに関する概要は、こちらの記事を参照してください。

FIFOを作成する

FIFOを作成するには、あらかじめ

mknod /dev/rtf<x> c 150 <x>

というコマンドを実行しておく必要があります。<x>は0~63の数値です。

FIFOを開く

ユーザースペースにてFIFOを開くには、次のようにします

	int fid = rtf_open_sized( "/dev/rtf0", O_RDWR, 1024 );

ここで、第一引数はFIFOデバイスファイル名です。

第二引数は、O_RDWR, O_RDONLY, O_WRONLY などのモードを渡します。

第三引数は、使用したいFIFOのサイズです。

FIFOに書き込む

ユーザースペースにてFIFOに書き込むには、次のようにします

	char buf[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
	write( fid, buf, sizeof(buf) );

これはファイルへの書き込みとまったく同様です。

FIFOから読み込む

ユーザースペースにてFIFOから読み込むには、次のようにします

	char buf[16];
	read( fid, buf, 16 );

これはファイルからの読み込みとまったく同様です。

セマフォ

FIFOの /dev/rtf<x> にはセマフォ機能も付いています。/dev/rtf0 ~ /dev/rtf63 の合計64個のセマフォを使う事が出来ます。

より詳しい情報は、<RTAIのソース>\doc\generated\html\api\group__fifos__sem.html を参照してください。

セマフォの概要については、こちらの記事を参照してください。

セマフォを初期化する

	/* Initialize semaphore */
	int fid = open("/dev/rtf0", O_RDWR );
	rtf_sem_init(	fid /* semaphore */,
					0 /* initial value. 0 or 1 */ );

open の第一引数が、セマフォ名です。/dev/rtf0 から /dev/rtf63 の間で指定します。

rtf_sem_initの第二引数は、セマフォの初期値です。0か1で指定しておきます。

初期値を0にしておくと、最初に wait した時にブロックしてしまいます。

初期値を1にしておくと、最初に wait した時、すでにカンバンが1つだけあるため、ブロックしません。

セマフォを wait する

	int fid = open( "/dev/rtf0", O_RDWR );
	rtf_sem_wait( fid /* semaphore */ );

open の第一引数が、セマフォ名です。/dev/rtf0 から /dev/rtf63 の間で指定します。

セマフォを post する

	int fid = open( "/dev/rtf0", O_RDWR );
	rtf_sem_post( fid /* semaphore */ );

open の第一引数が、セマフォ名です。/dev/rtf0 から /dev/rtf63 の間で指定します。

Net RPC

Net RPCを使用する事で、リモートマシン上のタスクやメールボックスを操作する事が出来ます。

Net RPCについては doc\generated には説明がありません。

概要については、こちらの記事をご覧ください。

ポートを取得する

Net RPCを使用するために、まずポートを取得します。

	struct sockaddr_in addr;
	inet_aton("192.168.0.155" /* address */ ,&addr.sin_addr );
	unsigned long node = addr.sin_addr.s_addr;
	long port = rt_request_hard_port( node );

このコードは、IPアドレス(192.168.0.155)からポートを取得するためのコードです。

ここで取得した、node, port の2つの変数が重要です。これらの変数でもって、Net RPCを使用します。

リモートのメールボックスからデータを読み込む

	MBX* mbx = (MBX*)RT_get_adr( node, port, "MBX4");
	if( NULL == mbx )
	{
		printf("Failed to connect to MBX4");
	}
	else
	{
		unsigned char buf[64];
		memset( buf, 0, sizeof(buf) );
		RT_mbx_receive( node, port, mbx, buf, 16 );
		for( int i = 0 ; i < 16 ; ++i )
		{
			printf("%02X ", buf[ i ] );
		}
		printf("\n");
	}
	rt_release_port( node, port );

このコードでは、取得したポートを元にリモートマシンのメールボックス MBX4 にアクセスしています。

そして、そのメールボックスから16バイトのデータを読み込もうとしています。

ここで、RT_get_adr や、 RT_mbx_receive などの関数名に着目します。

ローカルマシン内で、メールボックスのアドレスを取得するのは rt_get_adr です。

同様に、ローカルマシン内でメールボックスから受信するのは rt_mbx_receive です。

ところが、ここでは RT という大文字で始まっています。実は、これがポイントです。

Net RPCを使用するには、RT で始まる関数を使用します。そして、第一引数に node, 第二引数に port を与えます

この、「RTで始まる」「node, port を引数に与える」という所以外は、すべてローカルの関数と同様に扱えます。

メールボックス読み込みに限らず、メールボックス書き込み、メッセージ送信、メッセージ受信、なども、すべて RTで始まり、node, port を与えるようにすれば実現可能です。

サンプルプログラム

次回

次回はいよいよ最終回、割り込みの方法です。

One Reply to “RTAI入門(8)どう書くか?その2”

  1. 今さらかもしれませんが…ご参考までにコメントします。
    FIFO, セマフォを使用するとき、mknod /dev/rtf c 150 をあらかじめ実行する必要があるとの記事内容ですが、rtai4.0 で行ってみたところ rtai_fifos.ko を起動時にloadしておくと、自動的に0~63までの/dev/rtfが作成されており、File exists エラーとなります。
    セマフォについてはそのままで動作することを確認しました。

Comments are closed.