CAPL 概要
Controller Area Network(CAN)および Diagnostic Communication Over LAN(DoIP)などの通信プロトコル解析や ECU のテスト自動化を行う際、Vector社のツールチェーン内で用いられるプログラミング言語として CAPL(Communication Access Programming Language)が機能します。CANoe や CANalyzer といったツール上でカスタムロジックを実装し、シミュレーションや実機検証において高度な制御を行うためには、CAPLの理解と運用スキルが不可欠となります。
CAPL の主要特性
- C 言語準拠の文法:構造的には C/C++に近似しているため、既存のソフトウェアエンジニアにとって学習コストは低めです。ただし、車両ネットワークに特化した拡張機能や API が用意されています。
- イベント駆動アーキテクチャ:手続き型の記述も可能ですが、本質的には外部トリガー(タイマー、メッセージ受信、キーボード入力など)に応答してコードが実行される形式をとります。
- 標準ライブラリ機能:CANフレームの生成・解析、信号値の変換、ノードの管理、診断サービスの応答処理などを担う多数の組み込み関数が提供されています。
- リアルタイム処理能力:ECU との相互作用を含むテストシーケンスにおいて、厳密なタイミングを確保したリアルタイムシミュレーションが可能です。
- カスタマイズ性:独自関数や定数の定義により、特定のプロジェクト要件に合わせて機能を拡張できます。
開発ワークスペース設定
CANoe のSimulation Setup メニューより、対象となる ECU ノードを選択します。その後、画面上に表示されるペンアイコンをクリックすることで、CAPL エディタが起動します。新しいスクリプトファイルを作成する際は、適切なパスに保存先を指定し、拡張子 .can を付与したファイル名を登録してください。保存後に開かれるインターフェースは「CAPL Browser」と呼ばれ、スクリプトの作成およびコンパイルを行える中心画面となります。
データ型体系
C/C++の継承された基本型に加え、ネットワーク通信に特化した独自データ型をサポートしています。
基本数値型
byte: 8 ビット符号なし整数word: 16 ビット符号なし整数dword: 32 ビット符号なし整数qword: 64 ビット符号なし整数int: 16 ビット符号付き整数long: 32 ビット符号付き整数int64: 64 ビット符号付き整数char: 文字データ(8 ビット)、byte と互換性ありfloat: 単精度浮動小数点数(32 ビット)double: 倍精度浮動小数点数(64 ビット)
専用データ型
以下は CAN/ LIN / Ethernet デバイスや通信関連で主に使用されるタイプです。
message: CAN フレームデータの保持用linframe: LIN バス上のフレーム表現timer/mstimer: 秒単位およびミリ秒単位のタイマー定義ethernetPacket: イーサネットパケット構造体pdu: 送信 PDU の定義diagrequest/diagresponse: UDS 等の診断コマンド定義
複合型
複数の型を組み合わせたデータ構造も定義可能です。配列の宣言時は要素数を固定する必要があります。
// 変数と配列、構造体の例示
// 基本型変数
short sensorValue = 0; // 符号付き整数宣言
unsigned char byteVal = 255; // 符号なし 8 ビット宣言
// 配列宣言(サイズ必須)
double tempData[10]; // 2 倍精度浮動小数点の配列 10 要素
// 構造体定義
struct FrameControl {
short id;
byte status;
};
// 列挙型
enum SwitchState { OFF = 0, ON };
キャプラー内のスコープ規則
変数は定義される位置によって生存期間と参照範囲が異なります。スコープは大別して以下の 2 つに分類されます。
- グローバル領域: .can ファイルの上部に定義され、すべてのイベントハンドラや関数から参照可能です。
- ローカル領域: イベントハンドラ(
on ...ブロック内)や関数内部で宣言されます。その処理ブロック内のみ有効であり、終了すると破棄されます。宣言はブロックの先頭で行うことが推奨されます。
// グローバル変数の例
int globalCounter = 0;
on start
{
// ローカル変数の例
short localVar = 10;
globalCounter++; // グローバルへのアクセス可能
// ローカル変数のみ
write("ローカル変数はこの範囲内でのみ存在します");
}
コードの実行フローとイベント駆動
CAPL は完全にイベント駆動です。トップレベルに配置された文はコンパイラエラーとなり、必ずイベントハンドラの中に入る必要があります。実行の流れは、特定の状態変化が検知されると対応するイベントブロックが呼び出される形を取ります。
代表的なイベントには以下のものがあります:
preStart: システム起動前start: システム起動完了時preStop: システム停止時message: CAN ボード経由でデータを受信した時timer: 設定された時間経過時linframe: LIN 通信の到着時key: キーボード操作時
主要イベントの処理実装例
各イベントが発火した際の動作確認として、CANoe の Write ウィンドウへログを出力する手法を以下に示します。write() 関数は標準的なデバッグ用出力機能です。
初期化イベント
アプリケーションが開始された直後に実行されます。
on start
{
write("システムの初期化が完了しました。");
}
停止イベント
CANoe プロジェクトの計測が中断・終了するタイミングで発生します。
on preStop
{
write("測定セッションを終了する準備を行います。");
}
キーボードインタラクション
ホスト PC のキーボードが入力されたイベントに対応できます。ここでは 'X' キーを押下した時の挙動を示します。
on key'X'
{
write("ユーザーによるキー入力が検出されました。");
}
通信用タイマリング
定期的に実行したい処理にはタイマイベントを使用します。
on timer MyPeriodicTimer
{
// タイマ発火時に実行される処理
write("周期処理が実行されました");
}
上記のようなコードを記述した後、左側のコンパイルボタンを押して文法のチェックを行い、エディタが正常であることを確認してからメインプログラムを実行します。Write ウィンドウを表示させると、イベント対応したログ出力を確認することができ、スクリプトの期待通りの動作を検証できます。