C

Porting Qt Quick Ultralite to an RTOS

Porting Qt Quick Ultralite to an RTOS platform follows similar steps as bare metal platforms presented in the other sections of this guide. The following sections outline some of the differences compared to the bare metal platforms.

A Qt Quick Ultralite application on the RTOS platform is started as an RTOS task/thread using Qul::Application::exec. This call leads eventually to PlatformContext::exec, which will act as the main loop of that process. This is explained in more detail on the Using Qt Quick Ultralite with FreeRTOS page.

All of the platform APIs presented in the platform porting guide may be adapted to use platform provided services or APIs. One example of such adaptation is the memory allocation API in FreeRTOS ports of Qt Quick Ultralite that may be implemented by the API provided by the OS.

extern void *pvPortMalloc(size_t xWantedSize);
void *qul_malloc(std::size_t size)
{
    return pvPortMalloc(size);
}

Yielding

If your RTOS supports task/thread yielding, it is possible to yield the Qt Quick Ultralite RTOS task/thread to free up computing resources. Yielding could be called in the following places:

  • Inside the exec() function in the main loop
    void ExamplePlatform::exec()
    {
        while (true) {
            logFlush(); // Flush partially filled log buffer
            const uint64_t timestamp = this->update();
    
            if (timestamp > Platform::getPlatformInstance()->currentTimestamp()) {
                // The device may yield or go into sleep mode
            }
        }
    }
  • Another appropriate place where to invoke the yielding function could be when waiting for the back buffer to be released by the display controller.
    static volatile bool waitingForBufferFlip = false;
    static uint32_t idleTimeWaitingForDisplay = 0;
    
    static void waitForBufferFlip()
    {
        // Has there already been a buffer flip?
        if (!waitingForBufferFlip)
            return;
        const uint64_t startTime = getPlatformInstance()->currentTimestamp();
        while (waitingForBufferFlip) {
            // The device may yield or go into sleep mode
        }
    
        idleTimeWaitingForDisplay = getPlatformInstance()->currentTimestamp() - startTime;
    }
    
    // Note: This line clearing waitingForBufferFlip will need to be moved to the
    // actual interrupt handler for the display available on the target platform.
    // It's needed to inform about when the buffer address used to scan out pixels
    // to the display has been updated, making the buffer free in order to start
    // drawing the next frame.
    void LCD_BufferFlipInterruptHandler()
    {
        waitingForBufferFlip = false;
    }

    It is also possible to yield in case there is enough time before the next refresh interval is scheduled

    static void waitForRefreshInterval()
    {
        if (refreshCount < requestedRefreshInterval) {
            uint64_t startTime = getPlatformInstance()->currentTimestamp();
            while (refreshCount < requestedRefreshInterval) {
                // The device may yield or go into sleep mode
            }
            idleTimeWaitingForDisplay += getPlatformInstance()->currentTimestamp() - startTime;
        }
    
        refreshCount = 0;
    }

    For more information on waitForBufferFlip() and waitForRefreshInterval() please refer to the Implementing basic graphics section.

  • In case your hardware platform supports layers, it is possible to yield in the presentFrame() function.
    FrameStatistics ExampleLayerEngine::presentFrame(const PlatformInterface::Screen *screen,
                                                     const PlatformInterface::Rect &rect)
    {
        static unsigned int lastFrame = 0xffffffff;
        while (currentFrame == lastFrame) {
            // The device may yield or go into sleep mode
        }
        lastFrame = currentFrame;
    
        PlatformInterface::Rgba32 color = screen->backgroundColor();
        // HW_SetScreenBackgroundColor(color.red(), color.blue(), color.green());
    
        // No frame skip compensation implemented for layers
        return FrameStatistics();
    }

    Please refer to this section for further details.

FreeRTOS specific details

To enable using the app_common framework, set the QUL_OS variable either using the -DQUL_OS=FreeRTOS CMake command line option or include the QUL_OS in the platform name:

<platform_name>-freertos

Available under certain Qt licenses.
Find out more.