このページでは

C

Qt Quick AUTOSAR複合デバイスドライバとしてのUltralite

概要

このトピックでは、Qt Quick Ultralite アプリケーションをAUTOSAR Classic Platform プロジェクトと統合する方法について説明します。

コンプレックスドライバとは、AUTOSARClassic Platformのコンプレックスデバイスドライバ(CDD)仕様で定義されているAUTOSARインターフェイスおよび/または基本ソフトウェアモジュールAPIにアクセスできる、またはアクセスされる、AUTOSARで標準化されていないソフトウェアエンティティです。

このドキュメントは、ユーザが既にAUTOSAR Classic Platformのアーキテクチャとその用語に精通していることを想定しています。

RH850 D1M1Aプラットフォーム用のリファレンスプラットフォームとドキュメントが用意されています。

アーキテクチャ

Qt Quick UltraliteはAUTOSARのCDDとして実装されています。以下の図に、完全なアーキテクチャを示します:

Qt Quick Ultralite Complex Device Driver Architecture Overview for AUTOSAR.

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(Microcontroller Abstraction Layer)にはグラフィックデバイスの抽象化の仕様はありませんが、Qt Quick Ultralite CDDは必要に応じてMCALを利用できます。

マイクロコントローラ

Qt Quick Ultraliteは、MCALでサポートされていないリソースについては、MCUベンダーのドライバを利用します。

統合要件

AUTOSARプロジェクト

ボードサポートパッケージ

Qt Quick Ultraliteを初期化する前に、MCUベンダー固有のボードサポートパッケージ(BSP)を初期化する必要があります。基本ランタイムシステムの初期化中にBSPを初期化し、AUTOSARツールで割り込みサービスルーチンを設定します。

CDD

AUTOSARプロジェクトに、初期化用のCdd_Qul_Init と通常動作用のCdd_Qul_Update の2つのランナブルを持つ新しいCDDコンポーネントCdd_Qul を追加する。

AUTOSARソフトウェア開発ツールを使用してCDDのソースファイルを生成する。これはソフトウェアコンポーネントテンプレートと呼ばれ、以下のコード例ではcdd_qul.c

オペレーティングシステムのタスク構成

Qt Quick UltraliteランナブルをCdd_Qul_Task という新しいタスクにマップします:

名前タスクスタックサイズ(バイト)タスクタイプ
Cdd_Qul_Task327681拡張

タスクにマッピングされた関数

トリガー関数トリガーカテゴリートリガ条件
Cdd_Qul_Init初期
Cdd_Qul_Update周期的10 ms

注: 1スタック・サイズの要件はアプリケーション固有です。参考として、Qt Quick Ultralite Automotive Cluster Demoは約8kBのスタックを必要とします。

タスク・スケジューリング制御

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

アプリケーションのビルド

AUTOSAR プロジェクトとリンクするためのスタティックライブラリとして Qt Quick Ultraliteアプリケーションをビルドします。

注記: プラットフォーム適合名に "autosar" が含まれている場合、アプリケーションはデフォルトでスタティックライブラリとしてビルドされます。

動的メモリ

Qt Quick Ultraliteプラットフォーム抽象化におけるメモリ割り当てには、動的メモリ割り当て要求を処理するためのヒープマネージャが必要です。AUTOSARプロジェクトでは、ヒープマネージャは動的メモリ用にあらかじめ割り当てられた領域を持つことが望ましい。また、ヒープマネージャはメモリの断片化を最小化し、その実行時間は決定論的であるべきです。

アプリケーションコード内の C++ 標準コンテナにQt Quick Ultralitememory allocator を設定し、動的メモリ割り当て要求に対して同じ事前割り当て済みヒープ領域を使用する。

タイムスタンプ

Qt Quick Ultralite はtimestamp for the platform adaptation を必要とします。

生成されたCDDコードから現在のタイムスタンプを問い合わせることができます。次の例では、Cdd_Qul_Timestamp という関数が、cdd_qul.c という CDD ソフトウェア・コンポーネント・テンプレート・ファイルに実装されています。この新しい関数は、Qt Quick Ultralite plaform adaptationから呼び出されます。

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 runnableから以下の関数を呼び出します:

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); }

以下は、AUTOSARDLT にデバッグメッセージを送信するcdd_qul.c のロギング実装例です:

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_handlerqul_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 runnable で行う必要があります。こ れに よ り 、 すべての値変更が 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 runnableからのみ呼び出すことができます。

Instrument Clusterの例では、Cアプリケーションからユーザーインターフェース要素を制御する方法を示します。

C++コードとQMLの統合もご参照ください

特定の Qt ライセンスの下で利用可能です。
詳細をご覧ください。