Main Content

プロセッサインザループ (PIL) シミュレーション用のターゲット通信チャネルの作成

プロセッサインザループ (PIL) シミュレーション用の通信チャネルを実装します。

通信チャネルは異なるプロセス間のデータ交換を可能にします。この通信チャネルは、開発用コンピューター (ホスト) 上で実行される Simulink® ソフトウェア環境とターゲット ハードウェア上で実行される展開されたコードとの間でデータ交換を必要とする機能をサポートします。たとえば、PIL シミュレーションなどです。

ここでは、rtiostream インターフェイスについてと、さまざまな接続タイプのターゲット接続ドライバーとして実装可能な汎用通信チャネルを rtiostream インターフェイスで提供する方法について説明します。この例では、既定の TCP/IP 実装の使用方法について説明します。

2 つのエンティティ Station A と Station B が、rtiostream インターフェイスを使用して通信チャネルの設定とデータ交換を行います。この例では、Station A と Station B がデスクトップ コンピューターの同じプロセス内で設定されます。

ターゲット接続ドライバーはオンターゲット PIL シミュレーションをサポートします。このシミュレーションで Station A と Station B は、通信チャネル経由でデータを交換するターゲット コンピューターとホスト コンピューターを表します。ホスト側のターゲット接続ドライバーは、MATLAB® 製品に読み込まれて呼び出される共有ライブラリとして実装されます。ターゲット側のドライバーは、ターゲット上で実行されるアプリケーションにリンクされるソース コードまたはライブラリです。

さらに、以下のことができます。

  • 既定のホスト側 TCP/IP ドライバーと共に動作する TCP/IP の独自のターゲット側ドライバーを構成します。

  • 提供されたホスト側ドライバーをシリアル通信用に構成します。

  • たとえば通信チャネルのホスト側とターゲット側で CAN または USB を使用して、カスタム ターゲット接続ドライバーを実装します。

SIL シミュレーションと PIL シミュレーションを使用した生成コードのテストおよびカスタム ターゲット用のプロセッサインザループ (PIL) の構成も参照してください。

既定の TCP/IP を実装するためのソース コードの表示

ファイル rtiostream_tcpip.c では、クライアント側とサーバー側の TCP/IP 通信を実装しています。スタートアップ パラメーターによって、クライアント モードまたはサーバー モードのいずれかで動作するようにドライバーを設定します。カスタム実装の開始点としてこのソース ファイルを使用できます。通信チャネルのどちらの側でも、サーバー実装またはクライアント実装のいずれか一方のみを必要とします。クライアントのドライバーとサーバーのドライバーが異なるアーキテクチャ上で実行される場合は、それぞれのアーキテクチャ用のドライバー コードを別のソース ファイルに配置することを検討します。

ヘッダー ファイル rtiostream.h には、関数 rtIOStreamOpen/Send/Recv/Close のプロトタイプが含まれています。カスタム実装のためには、これをインクルードします (#include を使用)。

TCP/IP ドライバーのソース コードの場所を抽出します。

rtiostream_src_dir=fullfile(matlabroot,'toolbox','coder','rtiostream','src');
tcpip_dir=fullfile(rtiostream_src_dir,'rtiostreamtcpip');

rtiostream_tcpip.c を表示します。

edit(fullfile(tcpip_dir,'rtiostream_tcpip.c'));

rtiostream.h を表示します。

edit(fullfile(rtiostream_src_dir,'rtiostream.h'));

共有ライブラリ ファイルの場所

MATLAB 製品からターゲット接続ドライバーにアクセスするには、ターゲット接続ドライバーを共有ライブラリにコンパイルしなければなりません。この共有ライブラリはシステム パスに存在しなければなりません。既定の TCP/IP ドライバーの共有ライブラリは、matlabroot/bin/$ARCH ($ARCH はシステム アーキテクチャ、たとえば win64) に存在します。

共有ライブラリのファイル名の拡張子と場所は、オペレーティング システムによって異なります。

[~, ~, sharedLibExt] = coder.BuildConfig.getStdLibInfo;

Station A と Station B の共有ライブラリを特定します。

libTcpip = ['libmwrtiostreamtcpip' sharedLibExt];
disp(libTcpip)
libmwrtiostreamtcpip.dll

ターゲット接続ドライバーのテスト

カスタム ターゲット接続ドライバーを実装する場合は、MATLAB からこれをテストすると便利です。以下の例では、既定の TCP/IP ターゲット接続ドライバーを読み込む方法、およびこのドライバーを使用して Station A と Station B 間でのデータの交換を行う方法について説明します。

ドライバーにアクセスするには、MEX ファイル rtiostream_wrapper を使用します。この MEX ファイルを使用すると、共有ライブラリを読み込み、関数 rtiostream にアクセスして、rtiostream チャネルを開閉したり、データを送受信したりすることができます。

Station A と Station B はホスト コンピューター上で実行されています。Station A は TCP/IP サーバーとして、Station B は TCP/IP クライアントとして設定されます。ホストからターゲットへの通信を行う場合、通常、ホストは TCP/IP クライアントとして、ターゲットは TCP/IP サーバーとして設定します。

TCP のポート番号を選択します。

if usejava('jvm')
    % Find a free port
    tempSocket = java.net.ServerSocket(0);
    port = num2str(tempSocket.getLocalPort);
    tempSocket.close;
else
    % Use a hard-coded port
    port = '14646';
end

Station A の rtiostream を TCP/IP サーバーとして開きます。

stationA = rtiostream_wrapper(libTcpip,'open',...
                                 '-client', '0',...
                                 '-blocking', '0',...
                                 '-port',port);

通信チャネルが開いた場合、戻り値はこの接続のハンドルになります。-1 の戻り値はエラーを表します。

戻り値をチェックします。

assert(stationA~=(-1))

Station B の rtiostream を TCP/IP クライアントとして開きます。

stationB = rtiostream_wrapper(libTcpip,'open',...
                                 '-client','1',...
                                 '-blocking', '0',...
                                 '-port',port,...
                                 '-hostname','localhost');

通信チャネルが開いた場合、戻り値はこの接続のハンドルになります。-1 の戻り値はエラーを表します。

戻り値をチェックします。

assert(stationB~=(-1))

Station B から Station A へのデータの送信

ターゲット接続ドライバーは、8 ビット バイトでデータ ストリームを送信します。プロセッサがバイトでアドレスを指定できない場合、データはアドレスを指定可能な最小のワード サイズで送信されます。

Station B から Station A にメッセージ データを送信します。

msgOut = uint8('Station A, this is Station B. Are you there? OVER');

[retVal, sizeSent] = rtiostream_wrapper(libTcpip,...
                                       'send',...
                                       stationB,...
                                       msgOut,...
                                       length(msgOut));

戻り値 0 は成功を示します。

assert(retVal==0);

送信されたメッセージのバイト数を確認します。

assert(sizeSent==length(msgOut));

データ転送が完了するまでの時間を与えます。

pause(0.2)

Station A でデータを受信します。

[retVal, msgRecvd, sizeRecvd] = rtiostream_wrapper(libTcpip,...
                                                 'recv',...
                                                 stationA,...
                                                 100);

戻り値 0 は成功を示します。

assert(retVal==0);

メッセージのバイト数が受信されたことを確認します。

assert(sizeRecvd==sizeSent);

受信したデータを表示します。

disp(char(msgRecvd))
Station A, this is Station B. Are you there? OVER                                                   

Station A から Station B への応答の送信

Station A から Station B に応答データを送信します。

msgOut = uint8('Station B, this is Station A. Yes, I''m here! OVER.');
[~, sizeSent] = rtiostream_wrapper(libTcpip,... %#ok
                                       'send',...
                                       stationA,...
                                       msgOut,...
                                       length(msgOut));

データ転送が完了するまでの時間を与えます。

pause(0.2)

Station B でデータを受信します。

[~, msgRecvd, sizeRecvd] = rtiostream_wrapper(libTcpip,... %#ok
                                                 'recv',...
                                                 stationB,...
                                                 100);

受信したデータを表示します。

disp(char(msgRecvd))
Station B, this is Station A. Yes, I'm here! OVER.                                                  

接続の終了と共有ライブラリのアンロード

Station B で rtiostream を閉じます。

retVal = rtiostream_wrapper(libTcpip,'close',stationB);

戻り値 0 は成功を示します。

assert(retVal==0);

Station A で rtiostream を閉じます。

retVal = rtiostream_wrapper(libTcpip,'close',stationA);

戻り値 0 は成功を示します。

assert(retVal==0)

共有ライブラリをアンロードします。

rtiostream_wrapper(libTcpip, 'unloadlibrary');

シリアル通信用のホスト側ドライバー

TCP/IP のドライバーの代替としてシリアル通信に指定されたホスト側ドライバーを使用できます。シリアル ドライバーの設定については、『Embedded Coder® リファレンス』ドキュメンテーションのrtiostream_wrapperを参照してください。

独自のターゲット側ドライバーの設定

ターゲットにイーサネット接続が存在し、TCP/IP スタックを使用できる場合は、次の手順に従います。

  1. rtiostream.h で定義された rtiostream インターフェイス経由で使用できるように TCP/IP スタックのラッパーを記述します。

  2. データを送受信するターゲットのテスト アプリケーションを記述します。

  3. MEX ファイル rtiostream_wrapper とホスト側の TCP/IP ドライバーを使用して、ターゲットで実行されているドライバー ソフトウェアをテストできます。

  4. 稼働中のターゲット側ドライバーが存在する場合は、自動生成されるコードのビルドにドライバー ソース ファイルを含めます。

PIL の既定のホスト側ドライバーは、TCP/IP クライアントとして設定されているため、ターゲット側ドライバーを TCP/IP サーバーとしてのみ動作するように設定できます。

ホスト側でサポートされていない通信チャネルを使用する必要がある場合は、ホストとターゲットのドライバーを記述します。この場合でも、MEX ファイル rtiostream_wrapper を使用して rtiostream ドライバーをテストできます。

独自のホスト側ドライバーの設定

さまざまな通信チャネルを使用して、ターゲット接続ドライバーを実装できます。たとえば、特殊なシリアル接続を経由するホストとターゲット間の通信を実装できます。この場合、ホストとターゲットのドライバーを提供する必要があります。

ホスト側では、MEX ファイル rtiostream_wrapper を使用してドライバーをテストできます。独自のドライバーに printf ステートメントからの診断出力が含まれており、rtiostream_wrapper が共有ライブラリを読み込む場合、printf ステートメントを mexPrintf ステートメントに置き換えなければなりません。

稼働中のホスト側デバイス ドライバーが存在する場合、これを Simulink ソフトウェア環境で使用できるようにしなければなりません。PIL シミュレーションの場合、sl_customization を介して共有されるホスト側の共有ライブラリを登録します。

関連するトピック