C
Qt Quick Ultralite freertos_multitask Example
Shows how the communication between Qt Quick Ultralite and the background FreeRTOS task can be implemented.
Overview
The freertos_multitask
demonstrates how multiple FreeRTOS tasks can communicate each other. It shows how events from QML can be used to control another tasks activity. There are two independent tasks running: one responsible for running Qt Quick Ultralite, second responsible for blinking the onboard LED. It has a simple QML UI where a fan image is spinning in the central part of the screen while the onboard LED is blinking. By tapping the screen user is able to change fan speed rotation and LED blinking frequency.
Target platforms
Code overview
Project structure is divided into directories:
board_utils
- static library that implements LED control routines for a given platformfreertos
- static library that provides FreeRTOS kernel for a given platformimages
- graphical resources used by the Projectsrc
- C++ source code used by the application
Code overview
CMake project file
Main CMake file checks whether an example is built for one of the supported platforms. It's done by including freertos
directory. freertos
CMake target is defined only for supported platforms. When building for a desktop backend a simplified freertos_multitask_desktop
application is built.
... add_subdirectory(freertos) if(TARGET freertos_kernel) # FreeRTOS support implemented for this platform add_subdirectory(board_utils) qul_add_target(freertos_multitask src/main.cpp src/fancontrol.cpp QML_PROJECT mcu_freertos_multitask.qmlproject ) ... elseif(NOT CMAKE_CROSSCOMPILING) # No FreeRTOS here - fallback for building on desktop platform qul_add_target(freertos_multitask_desktop src/fancontrol.cpp QML_PROJECT mcu_freertos_multitask.qmlproject GENERATE_ENTRYPOINT ) target_compile_definitions(freertos_multitask_desktop PRIVATE NO_LED) ... else() message(STATUS "Skipping generating target: freertos_multitask") endif()
BoardUtils library
This library provides the most basic, HW specific implementation of LED control. It ships an simplistic API to initialize and toggle the LED on a supported board. The board_utils/include/board_utils/led.h contains API of the library.
... namespace BoardUtils { void initLED(); void toggleLED(); } // namespace BoardUtils
Application entry point
main.cpp file is used only for freertos_multitask
target (it's not used when building for desktop). main()
function takes care of the platform initialization, additionally initializes the LED using BoardUtils
library.
... int main() { Qul::initHardware(); Qul::initPlatform(); BoardUtils::initLED(); ...
Next, a FreeRTOS tasks are created. One responsible for running Qt Quick Ultralite, the other controls the LED.
if (xTaskCreate(Qul_Thread, "QulExec", QUL_STACK_SIZE, 0, 4, &QulTask) != pdPASS) { Qul::PlatformInterface::log("Task creation failed!.\r\n"); configASSERT(false); } if (xTaskCreate(Led_Thread, "LedToggle", configMINIMAL_STACK_SIZE, 0, 4, &LedTask) != pdPASS) { Qul::PlatformInterface::log("LED task creation failed!.\r\n"); configASSERT(false); } vTaskStartScheduler(); ...
Task running Qt Quick Ultralite is as simple as setting the root item of the application and calling the exec()
function.
static void Qul_Thread(void *argument) { (void) argument; Qul::Application app; static freertos_multitask item; app.setRootItem(&item); app.exec(); }
Task controlling the LED blinking frequency uses BoardUtils::toggleLED()
API to turn the LED on and off. This API is called in the infinite loop which waits for the task notification for a right number of clock ticks. xTaskNotifyWait
FreeRTOS API is used both for waiting and receiving incoming data using task notification mechanism. newSpeed
parameter will carry the received data (new fan speed) if the notification was received by the LED task.
static void Led_Thread(void *argument) { (void) argument; uint32_t speed = 1; uint32_t newSpeed = 0; while (true) { const TickType_t ticks = speed > 0 ? (350 / (portTICK_PERIOD_MS * speed)) : portMAX_DELAY; if (xTaskNotifyWait(0, ULONG_MAX, &newSpeed, ticks) == pdTRUE) { speed = newSpeed; } BoardUtils::toggleLED(); taskYIELD(); } }
FanControl object
The src/fancontrol.h declares a FanControl
singleton object that is accessible from the QML. This is enabled by adding the file to InterfaceFiles.files
in the main CMakeLists.txt. Responsibility of this class is to report current speed value with speed
property and to change the fan speed using updateSpeed()
function.
... class FanControl : public Qul::Singleton<FanControl> { public: FanControl(); Qul::Property<int> speed; void updateSpeed(int newSpeed); private: void updateLedSpeed(); };
The updateSpeed()
method takes care of updating the speed
property value, and calling private updateLedSpeed()
API.
... void FanControl::updateSpeed(int newSpeed) { speed.setValue(newSpeed); updateLedSpeed(); }
The updateLedSpeed()
sends notification to the LED task using xTaskNotify
FreeRTOS API. Current speed
property value is sent as a notification data payload.
void FanControl::updateLedSpeed() { #ifndef NO_LED xTaskNotify(LedTask, speed.value(), eSetValueWithOverwrite); #endif }
QML part
The UI of the application is implemented in freertos_multitask.qml. A FanControl
object is used as the main integration point. Current speed value is displayed using Text
item with text
property bound to the FanControl.speed
.
... Text { color: "white" text: FanControl.speed font.pixelSize: 30; } ...
The most relevant part of the QML implementation is a reaction to screen touch events to change fan and LED speed. Calling FanControl.updateSpeed
results in sending notification to the FreeRTOS LED task and updating text
property.
MouseArea { id: ta anchors.fill: parent onPressed: { FanControl.updateSpeed((FanControl.speed + 1) % 6); } }
Data flow diagram
Given sequence diagram summarizes how an event from the QML affects background task that is in charge of the hardware.
Files:
- freertos_multitask/CMakeLists.txt
- freertos_multitask/board_utils/CMakeLists.txt
- freertos_multitask/board_utils/include/board_utils/led.h
- freertos_multitask/board_utils/src/ek-ra6m3g-freertos/led.cpp
- freertos_multitask/board_utils/src/mimxrt1050-evk-freertos/led.cpp
- freertos_multitask/board_utils/src/mimxrt1064-evk-freertos/led.cpp
- freertos_multitask/board_utils/src/mimxrt1170-evk-freertos/led.cpp
- freertos_multitask/board_utils/src/stm32f769i-discovery-freertos/led.cpp
- freertos_multitask/freertos/CMakeLists.txt
- freertos_multitask/freertos_multitask.qml
- freertos_multitask/mcu_freertos_multitask.qmlproject
- freertos_multitask/src/fancontrol.cpp
- freertos_multitask/src/fancontrol.h
- freertos_multitask/src/main.cpp
Images:
See also FreeRTOS application build process.
Available under certain Qt licenses.
Find out more.