このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
XCP サーバー ソフトウェアのカスタマイズ
Simulink® エクスターナル モード シミュレーション用の XCP 通信プロトコルは、クライアント/サーバー方式の通信プロトコルです。既定では、ソフトウェアは次の XCP エクスターナル モード シミュレーションをサポートします。
ERT (
ert.tlc
) および GRT (grt.tlc
) システム ターゲット ファイルを使用して生成されるコードのための開発用コンピューター上。
カスタム ターゲット ハードウェアのシステム ターゲット ファイルが ERT または GRT システム ターゲット ファイルから派生している場合、用意された API を使用して XCP ターゲットの接続性を提供できます。XCP エクスターナル モードの制限事項が適用されます。
エクスターナル モードのターゲット接続性ソフトウェアは以下で構成されます。
エクスターナル モード抽象化レイヤー
XCP サーバー プロトコル層
XCP サーバー トランスポート層
XCP プラットフォーム抽象化レイヤー
エクスターナル モード抽象化レイヤー
エクスターナル モード シミュレーション中に Simulink と通信するには、ターゲット アプリケーションはエクスターナル モード抽象化レイヤーから関数を呼び出さなければなりません。
ソース コード ファイルの親フォルダーは次のとおりです。
matlabroot\toolbox\coder\xcp\src\target\ext_mode
この層の API は include\ext_mode.h
で宣言され、src\xcp_ext_mode.c
で実装されます。
Simulink と通信するために、ターゲット アプリケーションはエクスターナル モード抽象化レイヤーで公開されたサービスを使用します。このフロー チャートは、Simulink との通信を確立するために必要なターゲット アプリケーションの段階を表しています。
次の表は、ターゲット アプリケーションが各段階で呼び出さなければならない関数を示しています。
段階 | 関数 | 目的 |
---|---|---|
| エクスターナル モードのコマンド ライン引数を抽出する。 | |
| 生成された Simulink モデル コードを初期化する。 | |
エクスターナル モードのターゲット接続性を初期化する。 | ||
| [実行] ボタンをクリックしたときに作成される、開発用コンピューターからの開始要求を待機する。 | |
|
| 生成された Simulink モデル コードの 1 つのステップを実行する。 |
モデルのサンプル時間 ID の場合、モデル ステップ関数によって生成された信号をサンプリングし、開発用コンピューターに送信するために通信プロトコルのトランスポート層にパケットの内容を渡す。 | ||
物理的な通信インターフェイスとのパケットの送受信を行い、選択した通信プロトコルに従ってパケットの内容を処理する。 | ||
HOST STOP REQUEST OR SIMULATION COMPLETE | エクスターナル モード シミュレーションの停止要求を開発用コンピューターのモデルから受信するかどうかをチェックする。この要求は、[停止] ボタンをクリックしたときに作成される。 | |
生成されたモデル コードの実行が完了したかどうかをチェックする。 | ||
RESET |
| 生成された Simulink モデル コードを終了する。 |
エクスターナル モードのターゲット接続性を初期状態にリセットする。 |
以下の疑似コード例は、ターゲット アプリケーションでさまざまなフローチャート段階を実装する方法を示しています。RUN
段階の間は、エクスターナル モードの実行時環境には少なくとも 2 つのスレッドが必要です。
生成されたモデル コードの実行を行う周期的なスレッド。
エクスターナル モード通信スタックの実行とパケットの送信と受信を行うバックグラウンド スレッド。
疑似コードは、同じ while()
ループ内で periodicThread
と extmodeBackgroundRun
を逐次的に実行することで、マルチスレッドのシミュレーションを行います。
/*------------- Pseudo-Code Example -------------*/ /* Define periodic thread */ void periodicThread(void) { /* Run model step function */ modelName_step(); /* Notify external mode abstraction layer about periodic event */ extmodeEvent(PERIODIC_EVENT_ID, currentSimulationTime); } /* Main function for target application */ main(int argc, char *argv[]) { /*------------- INITIALIZE -------------*/ /* Parse external mode command line arguments */ extmodeParseArgs(argc, argv); /* Initialize model */ modelName_initialize(); /* Initialize external mode target connectivity */ extmodeInit(extModeInfo, finalSimulationTime); /*------------- HOST START REQUEST -------------*/ /* Wait until a start request is received from development computer */ extmodeWaitForHostRequest(EXTMODE_WAIT_FOREVER); /*------- HOST STOP REQUEST OR SIMULATION COMPLETE -------*/ /* While simulation is not complete and stop request is not received */ while (!extmodeSimulationComplete() && !extmodeStopRequested()) { /*------------- RUN -------------*/ periodicThread(); extmodeBackgroundRun(); } /*------------- RESET -------------*/ /* Terminate model */ modelName_terminate(); /* Reset external mode target connectivity */ extmodeReset(); return 0; }
関数を呼び出すコードを表示するには、[システム ターゲット ファイル] を [ert.tlc]
に設定してXCP 通信を使用したエクスターナル モード シミュレーションの例を実行します。次に、コード ジェネレーター フォルダーにある ert_main.c
を開きます。
メモ
システム ターゲット ファイルが grt.tlc
または GRT ベースの場合、コード ジェネレーターは rt_main.c
を作成し、既定では、内部ファイル ext_work.h
で定義された API を使用します。ext_mode.h
API の使用を有効にするには、ターゲット アプリケーションをビルドする前に以下を実行します。
set_param(model, 'TLCOptions', '-aExtModeXCPClassicInterface=0');
システム ターゲット ファイルが ert.tlc
または ERT ベースであり、GenerateSampleERTMain
が 'on'
に設定されている場合、コード ジェネレーターは ert_main.c
を作成し、既定では、ext_mode.h
で定義された API を使用します。ext_work.h
API の使用を有効にするには、ターゲット アプリケーションをビルドする前に以下を実行します。
set_param(model, 'TLCOptions', '-aExtModeXCPClassicInterface=1');
XCP サーバー プロトコル層
XCP サーバー プロトコル層では、自動化システムと測定システムの国際標準化団体 (ASAM) の規格である ASAM MCD-1 XCP に従って XCP コマンドとデータを解釈します。
ソース コード フォルダーは次のとおりです。
matlabroot\toolbox\coder\xcp\src\target\server\protocol\src
XCP サーバー トランスポート層
XCP サーバー トランスポート層は、ASAM の仕様に従って通信メディアに対してメッセージを送受信します。
ソース フォルダーは以下のとおりです。
matlabroot\toolbox\coder\xcp\src\target\server\transport\src
XCP プラットフォーム抽象化レイヤー
XCP プラットフォーム抽象化レイヤーは次のものを提供します。
物理的な通信インターフェイスを通じて生データを送受信するための XCP ドライバー。
静的なメモリ アロケーターの実装。
その他のターゲット ハードウェア固有の機能。
target
パッケージを使用して Simulink とターゲット ハードウェアの間の接続性を指定できます。次のようにして指定します。
XCP ドライバーには
target.CommunicationInterface
クラスを使用します。XCP プラットフォーム抽象化レイヤーの他の部分には
target.XCPPlatformAbstraction
クラスを使用します。
XCP プラットフォーム抽象化レイヤーを指定しない場合、ソフトウェアで既定のプラットフォーム抽象化レイヤーが使用されます。Linux®、Windows®、および Mac の各プラットフォームがサポートされています。詳細については、XCP エクスターナル モード シミュレーションの接続性のカスタマイズを参照してください。
カスタマイズの例については、カスタム抽出化レイヤーの作成を参照してください。
XCP ドライバー
XCP ドライバーは通信チャネルを通じて XCP メッセージを送受信します。エクスターナル モード シミュレーションでは、ビルド プロセスによってドライバー ファイルがビルド情報に自動的に追加されます。
XCP ドライバーは rtiostream
API に基づいています。たとえば、ホストベースのエクスターナル モード シミュレーションでは以下の rtiostream
ファイルが使用されます。
matlabroot
\toolbox\coder\rtiostream\src\rtiostreamtcpip\rtiostream_tcpip.cmatlabroot
\toolbox\coder\rtiostream\src\rtiostreamserial\rtiostream_serial.c
rtiostream
通信チャネルの実装とテストの詳細については、以下を参照してください。
Communications rtiostream API (Embedded Coder)
rtiostream
の情報は次のようにして指定します。
接続性に
target
パッケージを使用する場合は、target.CommunicationInterface
クラスを使用します。XCP エクスターナル モード シミュレーションの接続性のカスタマイズを参照してください。target
パッケージを使用しない場合は、rtiostream
ファイルをビルド情報オブジェクトに追加します。
詳細については、カスタム抽出化レイヤーの作成を参照してください。
メモリ アロケーター
XCP サーバー ソフトウェアでは、内部データ構造体を保持するために、可変サイズの連続メモリ ブロックを動的に割り当てる必要があります。エクスターナル モード シミュレーションでは、ビルド プロセスによってメモリ アロケーター ファイルがビルド情報オブジェクトに自動的に追加されます。
XCP_MEM_ALIGNMENT
プリプロセッサ マクロによるメモリ アロケーターのアライメントを構成します。次に例を示します。
#define XCP_MEM_ALIGNMENT 8
接続性にtarget
パッケージを使用する場合は、target.XCPPlatformAbstraction
クラスの BuildDependencies
プロパティを使用します。次に例を示します。
xcpPlatformAbstraction.BuildDependencies.Defines = {'XCP_MEM_ALIGNMENT=8'};
その他のプラットフォーム抽象化レイヤーの機能
このファイルでは、プラットフォーム抽象化レイヤー インターフェイスが定義されます。
matlabroot\toolbox\coder\xcp\src\target\server\platform\include\xcp_platform.h
以下の表では、ターゲット ハードウェアで展開する XCP サーバー ソフトウェアに提供しなければならない機能について説明します。
機能 | 詳細 |
---|---|
相互排除 | "相互排除" サポートを使用してシステムのデータ構造にアクセスするために、XCP ドライバーは基本 API に依存して定義、初期化、ロックおよびロック解除を行います。 ターゲット ハードウェアの相互排除をサポートするには、カスタム実装を提供します。 Linux および Windows の既定の実装では、相互排除がサポートされています。 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) ... #define XCP_MUTEX_DEFINE(lock) HANDLE lock #define XCP_MUTEX_INIT(lock) lock = CreateMutex(0, FALSE, 0) #define XCP_MUTEX_LOCK(lock) WaitForSingleObject((lock), INFINITE) #define XCP_MUTEX_UNLOCK(lock) ReleaseMutex(lock) #else ... #include <pthread.h> #define XCP_MUTEX_DEFINE(lock) pthread_mutex_t lock #define XCP_MUTEX_INIT(lock) pthread_mutex_init(&(lock), NULL) #define XCP_MUTEX_LOCK(lock) pthread_mutex_lock(&(lock)) #define XCP_MUTEX_UNLOCK(lock) pthread_mutex_unlock(&(lock)) ... #endif |
スリープ | 指定された時間が経過するまで呼び出しスレッド スリープを作成するスリープ API を提供します。Linux および Windows システムの既定の実装は次のとおりです。 #if defined(_WIN32) || defined(__WIN32__) || defined(WIN32) ... #define XCP_SLEEP(seconds,microseconds) Sleep((seconds) * 1000 \ + (((microseconds) + 1000 - 1) / 1000)) #else ... #if _POSIX_C_SOURCE >= 199309L #define XCP_SLEEP(seconds,microseconds) do {struct timespec t;\ t.tv_sec = seconds; t.tv_nsec = microseconds * 1000; nanosleep(&t, NULL);} while(0) #else /* nanosleep is not available. Use select instead. */ #define XCP_SLEEP(seconds,microseconds) do {struct timeval t; t.tv_sec = seconds;\ t.tv_usec = microseconds; select(0, NULL, NULL, NULL, &t);} while(0) #endif /* _POSIX_C_SOURCE >= 199309L */ ... #endif |
ログ | 診断メッセージを生成するために、XCP サーバー ソフトウェアにはターゲット ハードウェアによって提供されるログ サービスをサポートするカスタム出力 API が必要です。 |
アドレス変換 | XCP 標準は、メモリ内の変数のアドレスを 32 ビットのアドレスと 8 ビット拡張として表します。 XCP クライアントは、ビルド プロセスによって作成されるデバッグ情報を解析して、モデルの信号およびパラメーターのアドレスを抽出します。デバッグ情報は DWARF または PDB 形式です。 XCP クライアントは、引数
#if defined(__MINGW32__) || defined(__MINGW64__) #define XCP_ADDRESS_GET(addressExtension, address) \ (uint8_T*) ((uintptr_t) address) #else #define XCP_ADDRESS_GET(addressExtension, address) \ (uint8_T*) ((address) + (uint8_T*)&__ImageBase) #endif addressExtension は 0 です。 |
メモリの設定およびコピー | メモリのコピー操作およびメモリの設定操作の最適化されたバージョンを指定できます。
#ifndef XCP_MEMCPY #define XCP_MEMCPY memcpy #endif #ifndef XCP_MEMSET #define XCP_MEMSET memset #endif |
コマンド ライン引数の解析 | ターゲット ハードウェアでコマンド ライン引数の解析がサポートされていない場合、プリプロセッサ マクロ
set_param(modelName, 'OnTargetWaitForStart', 'on'); -DON_TARGET_WAIT_FOR_START=1 ) をコンパイラに提供します。 |
構造体のパッキングと配置 | XCP ソフトウェア スタックの実装では、一部の内部 C 構造体のパッキングと配置が必要です。プラットフォーム抽象化レイヤーでは、コンパイラ固有のプリプロセッサ命令を使用してパッキングと配置の情報を提供します。 C 構造体をパッキングおよび配置するために、以下のプリプロセッサ命令を提供します。 #define XCP_PRAGMA_PACK_BEGIN(n) #define XCP_PRAGMA_PACK_END() #define XCP_ATTRIBUTE_ALIGNED(n) #define XCP_ATTRIBUTE_PACKED XCP_PRAGMA_PACK_BEGIN(1) typedef struct XCP_ATTRIBUTE_PACKED XcpSetDaqListModeCmdPacketFrame { uint8_T PID; /* Packet identifier, always XCP_PID_SET_DAQ_LIST_MODE */ uint8_T mode; /* DAQ list mode (XCP DAQ Mode bit masks) */ uint16_T daqListId; /* DAQ list Id */ uint16_T eventId; /* Event Channel Id */ uint8_T prescaler; /* Transmission rate prescaler */ uint8_T priority; /* DAQ list priority (0xFF -> highest) */ } XcpSetDaqListModeCmdPacketFrame; XCP_PRAGMA_PACK_END() XCP_PRAGMA_PACK_BEGIN(XCP_MEM_ALIGNMENT) struct XCP_ATTRIBUTE_ALIGNED(XCP_MEM_ALIGNMENT) xcpFifoEntry { struct xcpFifoEntry *next; size_t msgFrameSize; /* in AG units */ }; XCP_PRAGMA_PACK_END() GCC コンパイラでは、以下の命令を使用します。 #define XCP_PRAGMA_PACK_BEGIN(n) #define XCP_PRAGMA_PACK_END() #define XCP_ATTRIBUTE_ALIGNED(n) __attribute__((aligned(n))) #define XCP_ATTRIBUTE_PACKED __attribute__((packed)) Microsoft® Visual C++® コンパイラでは、以下の命令を使用します。 #define PRAGMA(n) _Pragma(#n) #define XCP_PRAGMA_PACK_BEGIN(n) PRAGMA(pack(push, n)) #define XCP_PRAGMA_PACK_END() PRAGMA(pack(pop)) #define XCP_ATTRIBUTE_ALIGNED(n) #define XCP_ATTRIBUTE_PACKED |
カスタム抽出化レイヤーの作成
カスタム プラットフォーム抽象化レイヤーを作成するには、以下を実行します。
ヘッダー ファイル
xcp_platform_custom.h
を指定します。この Linux の例では必要な関数が定義されます。#ifndef XCP_PLATFORM_CUSTOM_H #define XCP_PLATFORM_CUSTOM_H /* XCP_ADDRESS_GET */ #include <stdint.h> #define XCP_ADDRESS_GET(addressExtension, address) (uint8_T*) ((uintptr_t) address) /* XCP_MUTEX */ #include <pthread.h> #define XCP_MUTEX_DEFINE(lock) pthread_mutex_t lock #define XCP_MUTEX_INIT(lock) pthread_mutex_init(&(lock), NULL) #define XCP_MUTEX_LOCK(lock) pthread_mutex_lock(&(lock)) #define XCP_MUTEX_UNLOCK(lock) pthread_mutex_unlock(&(lock)) /* XCP_SLEEP */ #include <sys/time.h> /* gettimeofday */ #if _POSIX_C_SOURCE >= 199309L #include <time.h> /* for nanosleep */ #else #include <stddef.h> #include <sys/select.h> /* for select */ #endif /* _POSIX_C_SOURCE >= 199309L */ #if _POSIX_C_SOURCE >= 199309L #define XCP_SLEEP(seconds,microseconds) do {struct timespec t;\ t.tv_sec = seconds; t.tv_nsec = microseconds * 1000; nanosleep(&t, NULL);} while(0) #else /* nanosleep is not available. Use select instead. */ #define XCP_SLEEP(seconds,microseconds) do {struct timeval t; t.tv_sec = seconds;\ t.tv_usec = microseconds; select(0, NULL, NULL, NULL, &t);} while(0) #endif /* _POSIX_C_SOURCE >= 199309L */ #endif
ヘッダー ファイルを登録します。
接続性に
target
パッケージを使用する場合は、target.XCPPlatformAbstraction
クラスのBuildDependencies
プロパティを使用して必要な情報を指定します。XCP エクスターナル モード シミュレーションの接続性のカスタマイズを参照してください。接続性に
target
パッケージを使用しない場合は、コード生成後のコマンドを定義します。function myXCPTargetPostCodeGenCommand(buildInfo) buildInfo.addDefines('-DXCP_CUSTOM_PLATFORM', 'OPTS'); % Add my rtiostream buildInfo.addSourceFiles(customRtIOStreamFileName, ... customRtIOStreamSrcPath); % If the target hardware does not support parsing of command % line arguments buildInfo.addDefines('-DEXTMODE_DISABLE_ARGS_PROCESSING', 'OPTS'); end
参考
extmodeBackgroundRun
| extmodeEvent
| extmodeGetFinalSimulationTime
| extmodeInit
| extmodeParseArgs
| extmodeReset
| extmodeSetFinalSimulationTime
| extmodeSimulationComplete
| extmodeStopRequested
| extmodeWaitForHostRequest
関連するトピック
- エクスターナル モード シミュレーションによるパラメーター調整、信号監視、コード実行プロファイリング
- XCP 通信を使用したエクスターナル モード シミュレーション
- Simulink とターゲット ハードウェアの間のエクスターナル モードの接続性の設定