C

Monitor Integration to Qt Ultralite with AUTOSAR

Demonstrates how to integrate Qt Safe Renderer Monitor to a Qt Ultralite application targeting AUTOSAR-compliant environments.

This example demonstrates how to integrate the Qt Safe Renderer (QSR) Monitor module into a Qt Ultralite application with AUTOSAR CRC checking. It shows how to generate and use output verification data, and how to interact with the AUTOSAR hardware interface to verify that the rendering is correct.

For more information about implementing safety-critical elements in Qt Ultralite, see: Qt Quick Ultralite application with safety-critical items

The build system uses CMake. The example builds QSR modules, generates the golden CRC values from QML using the QSR Monitor Config Tool, and links the resulting data library into a monitor test application.

Overview

The QML layout is parsed at build time to generate output verification data. The tool produces a data library containing the golden CRC values for each safety item state. This data is later used during runtime to verify that the rendering output on the screen matches the expected results.

The verification is done by calling AUTOSAR CDD stub functions that simulate the hardware CRC checking mechanism.

Building the Project

The project uses CMake for building. The CMakeLists.txt file configures the build process and sets up the necessary dependencies:

cmake_minimum_required(VERSION 3.10)
project(QSRMonitor C CXX)

# Check for required QSR source directory
if(NOT DEFINED QSR_SOURCE_DIR)
    message(FATAL_ERROR "QSR_SOURCE_DIR must be defined. Please provide it with -DQSR_SOURCE_DIR=<path>")
endif()

# Define build options
option(BUILD_FOR_MCU "Build for MCU target" ON)
option(BUILD_LIBRARIES_ONLY "Build only libraries without executable" OFF)

# Include QSR tools macros and header export
include(${QSR_SOURCE_DIR}/cmake/qsr_tools_custom_macros.cmake)
include(${QSR_SOURCE_DIR}/cmake/export_qsr_headers.cmake)

# Set the QML file for monitor data generation
set(QSR_INPUT_QML "${CMAKE_CURRENT_SOURCE_DIR}/qml/SafeUI.qml" CACHE STRING "The QML file for the monitor data generation")

# Add QSR subdirectories with binary directories
add_subdirectory(${QSR_SOURCE_DIR}/src/saferenderer ${CMAKE_BINARY_DIR}/qsr/saferenderer)
add_subdirectory(${QSR_SOURCE_DIR}/src/adaptation/outputverifier ${CMAKE_BINARY_DIR}/qsr/outputverifier)
add_subdirectory(${QSR_SOURCE_DIR}/src/monitor ${CMAKE_BINARY_DIR}/qsr/monitor)

# Generate monitorconfig data from QML to a library
add_subdirectory(libmonitordata)

# Create a custom target for all libraries
add_custom_target(qsr_libraries
    DEPENDS
        SafeRenderer
        OutputVerifier
        SafeMonitor
        qsrmonitordata
    COMMENT "Building QSR libraries"
)

# Create the test executable
set(TEST_SRCS
    cdd_qsr_stub.c
    main.c
)

add_executable(test_exe ${TEST_SRCS})
target_link_libraries(test_exe
    SafeRenderer
    OutputVerifier
    SafeMonitor
    qsrmonitordata
)

The build configuration requires:

  • QSR_SOURCE_DIR: Path to Qt Safe Renderer Runtime sources (typically <Qt installation directory>/Src/QtSafeRenderer-2.2.0).
  • BUILD_LIBRARIES_ONLY: Optional flag to build only QSR libraries for separate AUTOSAR projects.
  • QSR_TOOLS_PATH: Path to Qt Safe Renderer tools (typically <Qt installation directory>/Tools/QSR-2.2.0/bin).
  • QSR_INPUT_QML: Path to the safety-critical UI design.

The build process includes:

  • Building QSR libraries (SafeRenderer, OutputVerifier, Monitor) into ${CMAKE_BINARY_DIR}/lib.
  • Generating monitor data from QML using the QSR Monitor Config Tool.
  • Creating a data library with CRC values for verification.
  • Linking the test executable with all required components.
  • Exporting header files to ${CMAKE_BINARY_DIR}/include for use in other projects.

The monitor data generation is configured in a separate CMakeLists.txt:

cmake_minimum_required(VERSION 3.10)

project(QSRMonitorDataLib C CXX)

# Set library properties
set(LIBRARY_NAME qsrmonitordata)

# Include directories
include_directories(
    ${CMAKE_SOURCE_DIR}
    ${CMAKE_CURRENT_BINARY_DIR}/generated
    ${CMAKE_BINARY_DIR}/include/QtSafeRenderer
)

# Generate the monitor data
qsr_generate_monitor_data(monitordata_gen
    SAFE_QML ${QSR_INPUT_QML}
    CRC_ALGORITHM ${SAFE_LAYOUT_CRC_ALGORITHM}
)

# Create an object library with the generated files
add_library(${LIBRARY_NAME} ${monitordata_gen_GENERATED_FILES})

# Add dependency on the generation target
add_dependencies(${LIBRARY_NAME} monitordata_gen)

# Set library properties
set_target_properties(${LIBRARY_NAME} PROPERTIES
    OUTPUT_NAME ${LIBRARY_NAME}
    LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
    ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib
)

# Install rules for library only
install(TARGETS ${LIBRARY_NAME}
    LIBRARY DESTINATION lib
    ARCHIVE DESTINATION lib
    RUNTIME DESTINATION bin
)

This configuration:

  • Uses qsr_generate_monitor_data to process the QML file.
  • Creates a library containing the generated CRC data in ${CMAKE_BINARY_DIR}/lib.
  • The CRC algorithm for the target platform is set in the build configuration:
    • crc32 for Renesas RH850.
    • mpeg2 for Infineon Traveo II.

To build the project, run:

mkdir build
cd build
cmake .. -G Ninja -DCMAKE_TOOLCHAIN_FILE=<Qt installation directory>/Src/QtSafeRenderer-2.2.0/cmake/ghs.cmake -DQSR_TARGET_TOOLCHAIN_DIR="<GHS compiler installation>" -DQSR_SOURCE_DIR=<Qt installation directory>/Src/QtSafeRenderer-2.2.0 -DQSR_TOOLS_PATH=<Qt installation directory>/Tools/QSR-2.2.0/bin
cmake --build .

If you modify the QML layout, rebuild the project to regenerate the CRC data.

Output Verification

The QML layout defines safety items that need to be verified. Each item is identified by its QML id:

import QtQuick
import Qt.SafeRenderer

Window {
    id: test
    width: 640
    height: 480

    SafeImage {
        id: iconBattery
        objectName: "iconBattery"
        width: 64
        height: 64
        anchors.centerIn: parent
        fillColor: "black"
        source: "battery_icon.png"
    }
}

The item ID used in verification is calculated from the QML id using the qsafe_hash function:

// Calculate item ID from QML id using qsafe_hash
const char *itemName = "iconBattery";
const quint32 itemId = qsafe_hash(itemName, strlen(itemName));
const quint32 stateId = 1U; //visible
const qint32 ret = addItemToVerification(itemId, stateId);

The main.c file initializes the output verification, adds items for CRC checking, and runs the verification sequence:

// main.c
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "errorcode.h"
#include "qsafeglobal.h"
#include "qsafechecksum.h"
#include "outputverifier_capi.h"
#include "qsrmonitor.h"

int main(void)
{
    const char *itemName = "iconBattery";
    const quint32 itemId = qsafe_hash(itemName, strlen(itemName));
    const quint32 stateId = 1U; //visible
    int ret = addItemToVerification(itemId, stateId);

    printf("Testing monitor integration\n");
    initVerifierDevice(100U, 100U);
    printf("Item id: %d State id: %d\n", itemId, stateId);
    if (ret == 0) {
       OutputVerifier_verifyOutput();
       verifyOutput(defaultErrorHandler);
       return 0;
    } else {
        printf("Failed to add item for verification\n");
        return 1;
    }
}

The API addItemToVerification() adds an item and its expected state to the verification queue. Items are verified using OutputVerifier_verifyOutput() followed by verifyOutput().

The queue is FIFO-based and supports state updates automatically. The application code only needs to enqueue the new item state; internal logic ensures the latest state is verified.

The verification device is initialized with offset values to position the verification area:

void initVerifierDevice(quint32 xOffset, quint32 yOffset) {
    static SafeRenderer::OutputVerifierDevice outputVerifierDevice(xOffset, yOffset, getStaticOutputVerifier());
}

The AUTOSAR CRC checking stubs used by this example are:

void Cdd_Qsr_RequestCrc(quint32 x, quint32 y, quint32 width, quint32 height)
{
    // Define region to verify
    // In real implementation, this would configure the hardware CRC unit
    (void)x;
    (void)y;
    (void)width;
    (void)height;
}
void Cdd_Qsr_WaitForResult(void)
{
    // Wait for CRC calculation to complete
    // In real implementation, this would wait for hardware CRC unit
}
quint32 Cdd_Qsr_ReadCrc(void)
{
    // Read the calculated CRC value
    // In real implementation, this would read from hardware CRC unit
    return 0U;
}

These stub functions represent the device API:

For details about implementing the AUTOSAR CDD interface, see: Adapting Output Monitor to AUTOSAR

  • Cdd_Qsr_RequestCrc() - Defines the region to verify.
  • Cdd_Qsr_WaitForResult() - Waits for the result.
  • Cdd_Qsr_ReadCrc() - Reads the actual CRC.

The read CRC value is compared against the pre-generated golden CRCs. If the values do not match, the error handler is invoked to handle the verification failure.

Customizing Error Handling

The default error handler prints the error to the debug output. In production systems, implement your own version to raise alerts or initiate system recovery.

static void defaultErrorHandler(ErrorCode errorType, qint64 arg1, qint64 arg2)
{
    printf("Error: %s\n", errorCodeToString(errorType));
    printf("Item id: %d, CRC checking failed. Actual value: %x\n", (quint32)arg1, (quint32)arg2);
}

AUTOSAR HW Integration

The example includes only a stub implementation of the AUTOSAR CDD interface. Real implementations must provide CRC access logic using MCU hardware features.

The Qt Ultralite reference implementation supports the following HW targets:

  • Infineon Traveo II.
  • Renesas RH850.

For more information and a reference AUTOSAR project for the platforms, contact The Qt Company.

Example Files

  • CMakeLists.txt - Build setup.
  • main.c - Monitor test loop and verification setup.
  • cdd_qsr_stub.c - AUTOSAR CDD interface stubs for CRC verification.
  • SafeUI.qml - Safety-critical UI layout.

Files:

Images:

Available under certain Qt licenses.
Find out more.