C
Qt Quick AUTOSARコンプレックスデバイスドライバーとしてのUltralite
概要
このトピックでは、Qt Quick のUltraliteアプリケーションをAUTOSAR Classic Platformプロジェクトに統合する方法について説明します。
コンプレックス・ドライバーとは、AUTOSAR によって標準化されていないソフトウェアエンティティであり、 コンプレックス・デバイス・ドライバー(CDD)に関する AUTOSAR Classic Platform 仕様で定義されているAUTOSAR インターフェースおよび/または基本ソフトウェアモジュール API を介してアクセスしたり、アクセスを受けたりすることができます。
このドキュメントでは、ユーザーがすでにAUTOSAR Classic Platform のアーキテクチャとその用語に精通していることを前提としています。
RH850 D1M1Aプラットフォーム用のリファレンス・プラットフォームの適応版およびドキュメントが利用可能です。
アーキテクチャ
Qt Quick Ultraliteは、AUTOSAR向けのCDDとして実装されています。以下の図は、その完全なアーキテクチャを示しています:

CDD
Qt Quick のUltralite CDDは、アプリケーション、コアライブラリ、プラットフォーム抽象化、およびプラットフォームライブラリで構成されています。
実行環境
Qt Quick Ultralite CDDは、AUTOSARツールによって生成されるAUTOSARインターフェースを介して、AUTOSAR基本ソフトウェアコンポーネントと連携します。生成されたランタイム環境(RTE)コードは、Qt Quick Ultraliteを初期化し、定期的に更新するための実行可能モジュールを提供します。
サービス層
サービス層は、ハードウェア割り込みに応答して、関連する基本ソフトウェアコンポーネントの割り込みサービスルーチンをトリガーします。また、サービス層はハードウェアタイマーへのアクセスを提供し、これはQt Quick Ultralite CDDにおけるタイムスタンプに使用できます。
注: サービス・レイヤーの API を使用してハードウェア・タイマーにアクセスすると 、パフォーマンス上のオーバーヘッドが生じる場合があります。
マイクロコントローラ抽象化層
AUTOSAR Classic Platform 規格のマイクロコントローラ抽象化レイヤ (MCAL) には、グラフィックスデバイスの抽象化に関する仕様は含まれていませんが、Qt Quick Ultralite CDD では、必要に応じて MCAL を利用することができます。
マイクロコントローラ
Qt Quick Ultraliteは、MCALでサポートされていないリソースについては、MCUベンダーのドライバを利用します。
統合要件
AUTOSAR プロジェクト
ボードサポートパッケージ
Qt Quick Ultralite を初期化する前に、MCU ベンダー固有のボードサポートパッケージ (BSP) を初期化する必要があります。基本ランタイムシステムの初期化中に BSP を初期化し、AUTOSAR ツールを使用して割り込みサービスルーチンを設定してください。
CDD
AUTOSARプロジェクトに、「Cdd_Qul 」という新しいCDDコンポーネントを追加し、2つの実行可能ファイル(初期化用のCdd_Qul_Init と通常動作用のCdd_Qul_Update )を設定します。
AUTOSAR ソフトウェア開発ツールを使用して、CDD のソースファイルを生成します。これはソフトウェアコンポーネントテンプレートと呼ばれ、以下のコード例ではcdd_qul.c として参照されます。
オペレーティングシステムのタスク構成
Qt Quick Ultralite ランナブルを、Cdd_Qul_Task という新しいタスクにマッピングします:
| 名前 | タスクスタックサイズ (バイト) | タスクタイプ |
|---|---|---|
| Cdd_Qul_Task | 327681 | EXTENDED |
タスクにマッピングされた関数
| トリガーされる関数 | トリガーのカテゴリ | トリガー条件 |
|---|---|---|
Cdd_Qul_Init | 初期化 | |
Cdd_Qul_Update | 定期 | 10 ms |
注: 1スタックサイズの要件はアプリケーションによって異なります。参考までに、Qt Quick Ultralite Automotive Cluster Demoでは、約 8 kB のスタックが必要です。
タスクスケジューリング制御
Qt Quick のUltraliteプラットフォームへの適応では、通常、特定のイベントがトリガーされるのを待機するため、タスクタイプを「EXTENDED 」に設定します。「EXTENDED 」タスクタイプを使用すると、Qt Quick のUltraliteが待機している間、AUTOSARのオペレーティングシステムが他のタスクをスケジューリングできるようになります。
Qt Quick Ultraliteプラットフォーム適応における垂直ブランキング間隔の待機例:
platform_drawing.cpp Qt Quick Ultraliteプラットフォーム適応において:
void waitForVblank()
{
while (waitingForVblank) {
Cdd_Qul_Event_WaitEvent();
}
Cdd_Qul_Event_ClearEvent();
}cdd_qul.c AUTOSARプロジェクトのCDDにおいて:
void Cdd_Qul_Event_WaitEvent(void)
{
(void)WaitEvent(...); // Operating system API
}
void Cdd_Qul_Event_ClearEvent(void)
{
(void)GetEvent(...); // Operating system API
(void)ClearEvent(...); // Operating system API
}Qt Quick Ultralite
アプリケーションのビルド
Qt Quick Ultraliteアプリケーションを、AUTOSARプロジェクトに対してリンクするための静的ライブラリとしてビルドします。
注: プラットフォーム適応名に「autosar 」が含まれている場合 、アプリケーションはデフォルトで静的ライブラリとしてビルドされます。
動的メモリ
Qt Quick Ultralite プラットフォーム抽象化におけるメモリ割り当てでは、動的メモリ割り当て要求を処理するためのヒープマネージャが必要です。AUTOSAR プロジェクトの場合、ヒープマネージャには動的メモリ用に事前に割り当てられた領域があることが望ましいです。また、ヒープマネージャはメモリの断片化を最小限に抑え、その実行時間は決定論的である必要があります。
アプリケーションコード内のC++標準コンテナに対して、Qt Quick Ultraliteのmemory allocator を設定し、動的メモリ割り当て要求に対して同じ事前割り当て済みヒープ領域を利用するようにします。
タイムスタンプ
Qt Quick Ultralite では、timestamp for the platform adaptation が必要です。
生成された CDD コードから現在のタイムスタンプを照会できます。以下の例では、Cdd_Qul_Timestamp という関数が、cdd_qul.c という CDD ソフトウェアコンポーネントテンプレートファイルに実装されています。この新しい関数は、Qt Quick Ultralite プラットフォームアダプテーションによって呼び出されます。
platform_context.cpp Qt Quick のUltraliteプラットフォーム適応版では:
uint64_t currentTimestamp() QUL_DECL_OVERRIDE { return Cdd_Qul_Timestamp(); }cdd_qul.c AUTOSARプロジェクトのCDD内では:
uint64 Cdd_Qul_Timestamp(void)
{
static uint64 timestampMilliseconds = 0;
...
// Read a counter value or timestamp ...
timestampMilliseconds += ...;
return timestampMilliseconds;
}注: サービス層 API を使用してハードウェアタイマーにアクセスすると 、パフォーマンス上のオーバーヘッドが生じる可能性があります。GPT ドライバ、ハードウェアレジスタ、または MCU BSP API を通じてタイマーにアクセスすることを推奨します。
CDDの機能操作
初期化
Cdd_Qul_Init をInit Runnableとして設定します。
Cdd_Qul_Init ランナブルから以下の関数を呼び出します:
cdd_qul.c AUTOSARプロジェクトのCDD内で:
#include <qul_run.h>
...
void Cdd_Qul_Init(void)
{
qul_init_hardware();
qul_init_platform();
qul_init_application();
}注: qul_init_* というプレフィックスが付いたCリンク関数は 、qul_run.h で公開されています。
注: Qt Quick Ultraliteを初期化する前に、MCUベンダー 固有のBSPを 初期化する必要があります。
通常動作
通常動作中、Cdd_Qul_Update は定期的にトリガーされます。例えば、10ミリ秒ごとにトリガーされます。
注: フレームドロップを防ぐため、Qt Quick Ultraliteの更新周期は 、ディスプレイのリフレッシュレートよりも短くする必要があります。
Cdd_Qul_Update のrunnableから、以下の関数を呼び出してください:
cdd_qul.c AUTOSARプロジェクトのCDD内で:
#include <qul_run.h>
...
void Cdd_Qul_Update(void)
{
(void)qul_update_engine();
}ロギング
consoleWrite からCDDへログデータを転送します:
platform_context.cpp:
void consoleWrite(char character) QUL_DECL_OVERRIDE { Cdd_Qul_Log_Console_Write(character); }以下は、cdd_qul.c でのロギングの実装例であり、AUTOSARDLT にデバッグメッセージを送信します:
void Cdd_Qul_Log_Console_Write(char character)
{
static char logBuffer[256];
static uint16 logBufferIndex = 0;
logBuffer[logBufferIndex++] = character;
if ((character == 0) || (character == '\n') || (logBufferIndex == (sizeof(logBuffer) - 1))) {
logBuffer[logBufferIndex] = 0;
Dlt_MessageLogInfoType logInfo;
logInfo.Dlt_MessageLogLevelType = DLT_LOG_DEBUG;
// ...
Rte_Call_DLT_Service_SendLogMessage(
&logInfo,
(const uint8*)logBuffer,
logBufferIndex);
logBufferIndex = 0;
}
}注: DLTサービスを使用するには 、そのサービスをソフトウェア統合パッケージ(SIP)に含める必要があり、SendLogMessage のサービスポートをQt Quick Ultralite CDDに接続する必要があります。
障害時の動作
Qt Quick Ultraliteライブラリにおける致命的なエラーは、エラー報告APIを通じて報告されます。Qt Quick Ultraliteによって検出された致命的なエラーに対するコールバックを受け取るには、カスタムエラーハンドラを登録してください。
cdd_qul.c でのカスタムエラーハンドラの登録:
#include <qul_run.h>
...
void Cdd_Qul_Init(void)
{
(void)qul_set_error_handler(Cdd_Qul_Error_Handler); // Calls Qul::setErrorHandler()
qul_init_hardware();
...
}注:Cリンク 関数qul_set_error_handler は 、qul_run.h で公開されています。
カスタムエラーハンドラの実装はプロジェクトごとに異なります。ただし、Qt Quick Ultralite ソフトウェアスタックはすでに無効な状態にあるため、エラーハンドラは戻ってはなりません。
以下は、cdd_qul.c におけるエラーハンドラの実装例です。この実装では、エラーメッセージを AUTOSARDLTに送信し、エラーイベントを AUTOSARDET に送信します:
void Cdd_Qul_Error_Handler(enum QulError code, unsigned int lineNumber, int param1, int param2, int param3)
{
Dlt_MessageLogInfoType logInfo;
logInfo.Dlt_MessageLogLevelType = DLT_LOG_FATAL;
// ...
const char* logData = qul_error_code_to_string(code);
uint16 logDataLength = strlen(logData);
Rte_Call_DLT_Service_SendLogMessage(
&logInfo,
(const uint8*)logData,
logDataLength);
uint8 apiId = ...;
uint8 errorId = ...;
Rte_Call_DET_Service_ReportError(
apiId,
errorId);
// QUL CDD in an invalid state
while(1);
}注: エラー報告APIによって報告されたエラーからの回復には 、Qt Quick Ultraliteソフトウェアスタックの完全な再初期化が必要です。Qt Quick Ultraliteは初期化解除をサポートしていないため、ECUまたはMCUのリセットを行う必要があります。
注: DLTサービスを使用するには 、そのサービスをソフトウェア統合パッケージ(SIP)に含める必要があり、SendLogMessage サービスポートをQt Quick Ultralite CDDに接続する必要があります。
注: DET サービスを使用するには 、そのサービスがソフトウェア統合パッケージ(SIP)に含まれている必要があり、ReportError サービスポートをQt Quick Ultralite CDD に接続する必要があります。
アプリケーション開発
AUTOSAR インターフェースへの呼び出し
前述の例に示すように、生成されたソフトウェアコンポーネントテンプレートファイルからのみ AUTOSAR API 関数を呼び出すことをお勧めします。そうすることで、ソフトウェアコンポーネントテンプレートファイルが再生成された場合でも、Qt Quick Ultralite アプリケーションやプラットフォームライブラリを再コンパイルする必要がなくなります。
ユーザーインターフェース要素の制御
AUTOSAR インターフェースとのやり取りは、Qt Quick Ultralite エンジンの更新を呼び出す前に、Cdd_Qul_Update 実行可能ファイル内で行う必要があります。これにより、すべての値の変更が GUI アプリケーションに確実に反映されます。
cdd_qul.c からユーザーインターフェース要素を制御するために、Qt Quick UltraliteアプリケーションコードにC言語のリンケージ関数を追加します:
Qt Quick Ultraliteアプリケーションのビジネスロジック:
struct VehicleStatus : public Qul::Singleton<VehicleStatus>
{
Qul::Property<int> speed;
Qul::Property<int> rpm;
};
extern "C" {
void qul_application_set_speed(int speed)
{
VehicleStatus::instance().speed.setValue(speed);
}
void qul_application_set_rpm(int rpm)
{
VehicleStatus::instance().rpm.setValue(rpm);
}
}cdd_qul.c:
void Cdd_Qul_Update(void)
{
int speed;
// Reading a single value from the AUTOSAR Interface:
if (Rte_Read_Cdd_Qul_Speed_Value(&speed) == RTE_E_OK) {
qul_application_set_speed(speed);
}
// Reading a single message from the AUTOSAR Interface:
MyMessageQueueMessage rawMessage;
if (Rte_Receive_Qul_Message_Queue_Message(rawMessage) == RTE_E_OK) {
MyMessage* message = (MyMessage*)&rawMessage;
if (message->id == MyMessageId_RPM) {
qul_application_set_rpm(message->value);
}
}
(void)qul_update_engine(); // Calls Qul::Application::update()
}Rte_Type.h:
// Example of a raw message format
typedef uint8_t msg[8];
typedef msg MyMessageQueueMessage;my_message.h:
// Example of an user defined message ID and struct:
typedef enum {
MyMessageId_RPM,
...
} MyMessageId;
typedef struct {
int id;
int value;
} MyMessage;注
- AUTOSARインターフェースから値やメッセージを読み取りたい場合は、AUTOSARツールを使用して、Qt Quick Ultralite CDDにレシーバーポートを追加し、接続してください。
- Qul::Property::setValue() はスレッドセーフではなく、
Cdd_Qul_Updateのランナブルからのみ呼び出すことができます。
「Instrument Cluster」のサンプルでは、Cアプリケーションからユーザーインターフェース要素を制御する方法を示しています。
「C++ コードと QML の統合」も参照してください 。
特定のQtライセンスの下で利用可能です。
詳細はこちらをご覧ください。