C
Qt Quick Ultralite as an AUTOSAR Complex Device Driver
Overview
This topic provides instructions on how to integrate a Qt Quick Ultralite application with an AUTOSAR Classic Platform project.
A Complex Driver is a software entity not standardized by AUTOSAR that can access or be accessed via AUTOSAR Interfaces and/or Basic Software Modules APIs as defined by the AUTOSAR Classic Platform specification for the Complex Device Driver (CDD).
This document expects that the user is already familiar with AUTOSAR Classic Platform architecture and its terminology.
A reference platform adaptation and the documentation is available for the RH850 D1M1A platform.
Architecture
Qt Quick Ultralite is implemented as a CDD for AUTOSAR. The following diagram describes the complete architecture:
CDD
The Qt Quick Ultralite CDD consists of Application, Core Library, Platform Abstraction, and Platform Library.
Runtime Environment
The Qt Quick Ultralite CDD interacts with the AUTOSAR Basic Software components using the AUTOSAR interface which is generated by the AUTOSAR tools. The generated Runtime Environment(RTE) code provides runnables to initialize and update Qt Quick Ultralite periodically.
Services Layer
The Services Layer triggers the interrupt service routines of the relevant Basic Software components in response to the hardware interrupts. The Services Layer also provides access to the hardware timers, which can be used for the timestamp in Qt Quick Ultralite CDD.
Note: Accessing hardware timers using the Services Layer API may have a performance overhead.
Microcontroller Abstraction Layer
Microcontroller Abstraction Layer (MCAL) in the AUTOSAR Classic Platform standard does not have a specification for graphics device abstraction, however the Qt Quick Ultralite CDD can utilize MCAL if needed.
Microcontroller
Qt Quick Ultralite utilizes drivers from the MCU vendor for the resources that are not supported by MCAL.
Integration requirements
The AUTOSAR project
Board Support Package
The MCU vendor-specific Board Support Package (BSP) must be initialized before initializing Qt Quick Ultralite. Initialize BSP during the Basic Runtime System initialization and configure the interrupt service routines with the AUTOSAR tools.
CDD
Add a new CDD component called Cdd_Qul
to the AUTOSAR project with two runnables: Cdd_Qul_Init
for the initialization and Cdd_Qul_Update
for the normal operation.
Generate a source file for the CDD with the AUTOSAR software development tools. This is called a software component template and referred as cdd_qul.c
in the following code examples.
Task configuration for the operating system
Map Qt Quick Ultralite runnables into a new task called Cdd_Qul_Task
:
Name | Task stack size (byte) | Task type |
---|---|---|
Cdd_Qul_Task | 32768 1 | EXTENDED |
Functions mapped to the task
Triggered function | Trigger category | Trigger conditions |
---|---|---|
Cdd_Qul_Init | Init | |
Cdd_Qul_Update | Periodical | 10 ms |
Note: 1 Stack size requirements are application-specific. For reference the Qt Quick Ultralite Automotive Cluster Demo requires about 8 kB of stack.
Task scheduling control
Set the task type to EXTENDED
as a Qt Quick Ultralite platform adaptation usually waits for certain events to trigger. The EXTENDED
task type allows the operating system in AUTOSAR to schedule other tasks while Qt Quick Ultralite is waiting.
An example of waiting vertical blanking interval in the Qt Quick Ultralite platform adaptation:
platform_drawing.cpp
in the Qt Quick Ultralite platform adaptation:
void waitForVblank() { while (waitingForVblank) { Cdd_Qul_Event_WaitEvent(); } Cdd_Qul_Event_ClearEvent(); }
cdd_qul.c
in the CDD of the AUTOSAR project:
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
Application build
Build the Qt Quick Ultralite application as a static library for linking against the AUTOSAR project.
Note: If the platform adaptation name contains "autosar
", the application is built as a static library by default.
Dynamic memory
Memory allocation in Qt Quick Ultralite platform abstraction requires a heap manager to handle dynamic memory allocation requests. For an AUTOSAR project a heap manager should preferably have a pre-allocated region for the dynamic memory. The heap manager should also minimize memory fragmentation and its execution time should be deterministic.
Set a Qt Quick Ultralite memory allocator for the C++ standard containers in the application code to utilize the same pre-allocated heap region for the dynamic memory allocation requests.
Timestamp
Qt Quick Ultralite requires a timestamp for the platform adaptation.
You can query the current timestamp from the generated CDD code. In the following example a function called Cdd_Qul_Timestamp
is implemented into a CDD software component template file called cdd_qul.c
. This new function is called by the Qt Quick Ultralite plaform adaptation.
platform_context.cpp
in the Qt Quick Ultralite platform adaptation:
uint64_t currentTimestamp() QUL_DECL_OVERRIDE { return Cdd_Qul_Timestamp(); }
cdd_qul.c
in the CDD of the AUTOSAR project:
uint64 Cdd_Qul_Timestamp(void) { static uint64 timestampMilliseconds = 0; ... // Read a counter value or timestamp ... timestampMilliseconds += ...; return timestampMilliseconds; }
Note: Accessing hardware timers using the Services Layer API may have a performance overhead. It is recommended to access the timer either through a GPT driver, hardware registers, or MCU BSP API.
CDD functional operations
Initialization
Configure Cdd_Qul_Init
as an Init Runnable.
Call the following functions from the Cdd_Qul_Init
runnable:
cdd_qul.c
in the CDD of the AUTOSAR project:
#include <qul_run.h> ... void Cdd_Qul_Init(void) { qul_init_hardware(); qul_init_platform(); qul_init_application(); }
Note: C linkage functions with qul_init_*
prefix are exposed in qul_run.h
.
Note: The MCU vendor-specific BSP must be initialized before initializing Qt Quick Ultralite.
Normal operation
During normal operation, Cdd_Qul_Update
is triggered periodically. For example, every 10 milliseconds.
Note: The Qt Quick Ultralite update period should be shorter than the display refresh rate to avoid frame dropping.
Call the following function from the Cdd_Qul_Update
runnable:
cdd_qul.c
in the CDD of the AUTOSAR project:
#include <qul_run.h> ... void Cdd_Qul_Update(void) { (void)qul_update_engine(); }
Logging
Forward log data from the consoleWrite to the CDD:
platform_context.cpp
:
void consoleWrite(char character) QUL_DECL_OVERRIDE { Cdd_Qul_Log_Console_Write(character); }
The following is an example implementation for logging in cdd_qul.c
, which sends debug messages to the AUTOSAR DLT:
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; } }
Note: To use the DLT service, it must be included in the Software Integration Package (SIP), and the SendLogMessage
service port needs to be connected to the Qt Quick Ultralite CDD.
Fault operation
Fatal errors in the Qt Quick Ultralite library are reported through the error reporting API. Register a custom error handler to receive a callback for the fatal errors that are detected by the Qt Quick Ultralite.
Registering a custom error handler in 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(); ... }
Note: C linkage function qul_set_error_handler
is exposed in qul_run.h
.
Implementation for the custom error handler is project specific. However, the error handler must not return as the Qt Quick Ultralite software stack is already in an invalid state.
The following is an example error handler implementation in cdd_qul.c
, which sends an error message to the AUTOSAR DLT and an error event to the AUTOSAR DET:
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); }
Note: Recovery from an error reported by the error reporting API requires a complete reinitialization of the Qt Quick Ultralite software stack. A reset must be done for the ECU or the MCU as Qt Quick Ultralite does not support deinitialization.
Note: To use the DLT service, it must be included in the Software Integration Package (SIP), and the SendLogMessage
service port needs to be connected to the Qt Quick Ultralite CDD.
Note: To use the DET service, it must be included in the Software Integration Package (SIP), and the ReportError
service port needs to be connected to the Qt Quick Ultralite CDD.
Application development
Calls to the AUTOSAR interface
It is recommended to call AUTOSAR API functions only from the generated software component template files as shown in the earlier examples. That way, you don't need to recompile the Qt Quick Ultralite application or platform library when the software component template files are regenerated.
Controlling the user interface elements
Interaction with the AUTOSAR interface must be done in Cdd_Qul_Update
runnable before calling the Qt Quick Ultralite engine update. This ensures that all value changes are visible in the GUI application.
Add C linkage functions to the Qt Quick Ultralite application code to control the user interface elements from cdd_qul.c
:
Business logic of the Qt Quick Ultralite application:
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;
Notes
- If you want to read a value or message from the AUTOSAR interface, add and connect the receiver port to the Qt Quick Ultralite CDD using the AUTOSAR tools.
- Qul::Property::setValue() is not thread-safe and can be called only from the
Cdd_Qul_Update
runnable.
The Instrument Cluster example demonstrates how to control user interface elements from a C application.
See also Integrating C++ code with QML.
Available under certain Qt licenses.
Find out more.