C

将 Qt Quick Ultralite 移植到实时操作系统

将 Qt Quick Ultralite 移植到实时操作系统平台遵循与本指南其他部分中介绍的裸机平台类似的步骤。以下各节概述了一些与裸机平台的区别。

RTOS 平台上的 Qt Quick Ultralite 应用程序使用 Qul::Application::exec 作为 RTOS 任务/线程启动。此调用最终导致调用 PlatformContext::exec,该调用将作为该进程的主循环。这在本指南的 使用 Qt Quick Ultralite 与 FreeRTOS 页面上有更详细的解释。

平台移植指南中介绍的所有平台 API 都可以适应使用平台提供的服务或 API。一个这样的适应示例是 Qt Quick Ultralite 的 FreeRTOS 端的内存分配 API,可以通过 OS 提供的 API 实现。

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

让步

如果您的 RTOS 支持任务/线程让步,则可以释放 Qt Quick Ultralite RTOS 任务/线程以释放计算资源。让步可以在以下地方调用

  • 主循环exec() 函数内部
    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
            }
        }
    }
  • 另一个适当地调用让步函数的位置是等待显示控制器释放后缓冲区时
    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;
    }

    如果直到下一次刷新间隔之前有足够的时间,也可以让步

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

    有关 waitForBufferFlip()waitForRefreshInterval() 的更多信息,请参阅 实现基本图形 部分。

  • 如果您的硬件平台支持 ,则可以在 presentFrame() 函数中进行让步。
    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();
    }

    有关更多详细信息,请参阅 本节

FreeRTOS 特定细节

要启用使用 app_common 框架,请使用 -DQUL_OS=FreeRTOS 的 CMake 命令行选项设置 QUL_OS 变量,或将 QUL_OS 包含在平台名称中

<platform_name>-freertos

在特定 Qt 许可下使用。
了解详情。