C

开发应用程序后端(TRAVEO™ T2G)

本主题将指导您如何使用 GHS MULTI IDE 创建和构建应用程序的后端,以便应用程序的 UI 可以与平台通信并从硬件获取所需信息。在本例中,设备接口获取板上用户按钮的状态。下面的图示描述了两个组件之间的交互

导出应用程序和平台源代码

本部分提供逐步说明,指导您如何将 QmlProject 创建 GHS MULTI IDE 项目,包括由 Qt for MCUs 工具导出的应用程序和平台源代码。

注意:如果使用 TRAVEO™ T2G CYT4DN 或 TRAVEO™ T2G Cluster 4M Lite Kit,在以下步骤中将 tviic2d4m-baremetal 分别替换为 tviic2d6m-baremetaltviic2d4mlite-baremetal

  1. 创建包含以下命令的批处理脚本,该脚本调用 qmlprojectexporter 以生成 GHS Multi IDE 项目
    set QUL_ROOT=C:\path\to\QtMCUs\2.8.0
    set QMLPROJECT_FILE=C:\path\to\YourProject.qmlproject
    set BOARDDEFAULTS=%QUL_ROOT%\platform\boards\cypress\tviic2d4m-baremetal\cmake\BoardDefaults_32bpp.qmlprojectconfig
    set GRAPHICS_DRIVER_DIR=C:\path\to\TVII-GraphicsDriver-V2.3.0
    set PROJECT_DIR=C:\path\to\PROJECT_DIR
    
    %QUL_ROOT%\bin\qmlprojectexporter.exe %QMLPROJECT_FILE% --platform=tviic2d4m-baremetal --toolchain=ghs-arm --boarddefaults=%BOARDDEFAULTS% --outdir=%PROJECT_DIR% --project-type=ghs --include-ide-generated-hw-code --board-sdk=%GRAPHICS_DRIVER_DIR%

    在运行脚本之前,请确保以下变量已设置

    • GRAPHICS_DRIVER_DIR 为 TRAVEO™ T2G 图形驱动程序安装路径,
    • QUL_ROOTQMLPROJECT_FILE
    • PROJECT_DIR 为 GHS 项目文件要放置的输出目录。

    现在,从命令提示符运行脚本以生成以下内容

    • %PROJECT_DIR%/QtMCUs/generated 中生成的从 QML 创建的 C++ 源代码
    • %PROJECT_DIR%/QtMCUs/platform 中导出的平台源代码
    • %PROJECT_DIR%/GHS 中的顶层项目文件和子项目文件

    生成的 GHS 项目包括以下内容

    • %PROJECT_DIR%/GHS/project.gpj:顶层项目文件。
    • %PROJECT_DIR%/GHS/prj/program.gpj:程序编译定义、包括目录、编译器和链接器选项。
    • %PROJECT_DIR%/GHS/prj/drivers.gpj:TVII 图形驱动程序源代码列表。
    • %PROJECT_DIR%/GHS/prj/QtMCUs/qul_platform.gpj:TRAVEO™ T2G CYT3DL 平台源代码列表。
    • %PROJECT_DIR%/GHS/prj/QtMCUs/qul_app.gpj:从主 .qmlproject 文件生成的源代码列表。
    • %PROJECT_DIR%/GHS/prj/QtMCUs/qul_module_<ModuleName>.gpj:每个模块一个子项目,包括为相应的模块 .qmlproject 文件生成的源代码。
    • %PROJECT_DIR%/GHS/prj/application.gpj:为应用程序提供的便利空子项目,您将在下一节中进行编辑。
    • %PROJECT_DIR%/GHS/mcu_<YourProject>_qul_workspace.gmb:包含一些额外命令以便使用的 workspace。有关详细信息,请参见 GHS Multi IDE QUL Workspace
    • %PROJECT_DIR%/GHS/qul_flash_jlink.bat:用于使用 J-Link 探测器刷写应用程序的批处理文件。
    • %PROJECT_DIR%/GHS/qul_flash_miniprog.bat:用于使用 MiniProg4 探测器刷写应用程序的批处理文件。

有关更多信息,请参阅 使用平台源导出 Qt for MCUs 项目的说明

在 GHS MULTI IDE 中构建应用程序

以下说明将指导您完成构建应用程序所需的 GHS 项目适配步骤。

  1. 启动 GHS MULTI 启动程序 (mstart.exe)
  2. 选择 文件 > 从文件加载 workspace... 并导航到上一节中导出的 %PROJECT_DIR%/GHS。选择 workspace 文件 mcu_<YourProject>_qul_workspace.gmb
  3. 在工作区中双击 项目经理 条目以在项目管理器中打开项目。
  4. 在任何目录下创建一个名为 main.cpp 的新文件。该目录将被引用为 BACKEND_DIR
    #include "YourProject.h"
    
    #include <qul/application.h>
    #include <qul/qul.h>
    
    int main()
    {
        Qul::initHardware();
        Qul::initPlatform();
        Qul::Application app;
        static YourProject item;
        app.setRootItem(&item);
        app.exec();
        return 0;
    }

    此文件包含应用程序的默认入口点。您将使用额外的配置步骤扩展此入口点以使用 LED 和用户按钮。有关更多信息,请参阅 在应用程序中运行 Qt Quick Ultralite 的文档。请确保使用与早期章节中相同的相同项目名称 (YourProject)。

  5. 右键单击 application.gpj 并选择 编辑。将其内容替换为以下内容。
    #!gbuild
    
    macro APPLICATION_EXPORT_DIR=C:/path/to/PROJECT_DIR/QtMCUs/generated
    macro BACKEND_DIR=C:/path/to/BACKEND_DIR
    
    [Subproject]
        -DQUL_STD_STRING_SUPPORT
        -I${APPLICATION_EXPORT_DIR}
    
    # ----- backend -----
    ${BACKEND_DIR}/main.cpp

    确保将宏 APPLICATION_EXPORT_DIR设置为包含导出 UI 源的目录,将宏 BACKEND_DIR 设置为包含后端源和 main.cpp 的目录。

    注意:.gpj 项目文件中缩进很重要。确保在包括源文件在内的行开头没有空格。有关更多信息,请参阅 MULTI IDE 文档。

  6. 默认情况下,应用程序的二进制名称为 application.elf。要使用不同的名称,请将 -o application.elfprogram.gpj 项目文件中更改为 -o YourProject.elf
  7. 此时,为了验证迄今为止所采取的步骤是否正确,您可以使用 GHS MULTI IDE 工作区中由 qmlprojectexporter 生成并用于导出项目的批处理文件快捷方式构建部分实现的您的应用程序,并将其刷写到 TRAVEO™ T2G 板上。

    注意:TRAVEO™ T2G Cluster 4M Lite (KIT_T2G_C-2D-4M_LITE) 平台端口板默认设置为 USB 显示输出,有关更多信息,请参阅 显示输出(TRAVEO™ T2G CYT3DL 4M LITE KIT)

    批处理文件(qul_flash_jlink.batqul_flash_miniprog.bat)与主项目文件放置在同一个目录中,并且包含用于使用 J-Link 或 MiniProg4 探测器刷写应用程序的命令。

    您可以直接从 GHS MULTI IDE 工作区中运行与您的探测器对应的批处理文件。

    注意:有关这些批处理文件中运行命令的详细信息,请参阅 Infineon 板的刷写说明

    批处理文件假定 Infineon Auto Flash Utility 1.4 已安装在其默认位置,或者其路径存储在环境变量 INFINEON_AUTO_FLASH_UTILITY_DIR 中。

    您还需要将引导加载程序刷写到 TRAVEO™ T2G 板的 CM0+ 核心上。有关详细信息,请参阅 Infineon 板的引导加载程序刷写说明

在下一节中,您将添加逻辑以启用应用UI和用户按钮与硬件之间的交互。

开发C++后端

以下说明指导您开发应用程序的后端C++。

  1. 创建新的C++源和头文件,分别命名为deviceinterface.cppdeviceinterface.h,并将这些文件保存到您刚刚创建的BACKEND_DIR目录中。
  2. deviceinterface.h的内容替换为以下内容
    #ifndef DEVICEINTERFACE_H
    #define DEVICEINTERFACE_H
    
    #include <qul/signal.h>
    #include <qul/singleton.h>
    #include <qul/eventqueue.h>
    
    typedef int HWButtonEvent;
    
    class DeviceInterface : public Qul::Singleton<DeviceInterface>, public Qul::EventQueue<HWButtonEvent>
    {
    public:
        Qul::Signal<void(int button)> buttonEvent;
        void onEvent(const HWButtonEvent &inputEvent);
    
        void toggleLED();
    };
    
    #endif //DEVICEINTERFACE_H

    该头文件声明了从Qul::SingletonQul::EventQueue继承的DeviceInterface类。它还声明了buttonEventSignal和事件类型HWButtonEvent。这允许Singleton实例全局可用。它提供了一个从C++到QML的接口,以在接收到HWButtonEvent输入事件时发出changed信号。有关更多信息,请参阅定义QML的Singleton从中断处理程序传输数据到QML

  3. 同样,将deviceinterface.cpp的内容替换为以下内容
    #include "deviceinterface.h"
    #include "boardutils.h"
    
    #include <platforminterface/log.h>
    
    extern "C" void DeviceInterface_handleButtonEvent()
    {
        DeviceInterface::instance().postEventFromInterrupt(0);
    }
    
    void DeviceInterface::onEvent(const HWButtonEvent &inputEvent)
    {
        buttonEvent(inputEvent);
    }
    
    void DeviceInterface::toggleLED()
    {
        Qul::PlatformInterface::log("Toggling LED\n");
        BoardUtils_toggleLED();
    }
  4. 创建新的C源和头文件,分别命名为boardutils.cboardutils.h,并将这些文件保存在BACKEND_DIR目录中。
  5. boardutils.h中的代码替换为以下内容
    #ifndef BOARDUTILS_H
    #define BOARDUTILS_H
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    void BoardUtils_configure();
    void BoardUtils_toggleLED();
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif //BOARDUTILS_H
  6. BoardUtils_configure()BoardUtils_toggleLED()的TRAVEO™ T2G特定实现添加到boardutils.c
    #include "boardutils.h"
    
    #include <stdint.h>
    
    #include <cy_project.h>
    
    #define USER_LED1_PORT CY_USER_LED1_PORT
    #define USER_LED1_PIN CY_USER_LED1_PIN
    #define USER_LED1_PIN_MUX CY_USER_LED1_PIN_MUX
    
    #define USER_BUTTON1_PORT CY_USER_BUTTON_WAKE_PORT
    #define USER_BUTTON1_PIN CY_USER_BUTTON_WAKE_PIN
    #define USER_BUTTON1_PIN_MUX CY_USER_BUTTON_WAKE_PIN_MUX
    #define USER_BUTTON1_IRQN CY_USER_BUTTON_WAKE_IRQN
    
    extern void DeviceInterface_handleButtonEvent();
    
    void ButtonInterruptHandler(void)
    {
        uint32_t interruptStatus = Cy_GPIO_GetInterruptStatusMasked(USER_BUTTON1_PORT, USER_BUTTON1_PIN);
        if (interruptStatus) {
            DeviceInterface_handleButtonEvent();
            Cy_GPIO_ClearInterrupt(USER_BUTTON1_PORT, USER_BUTTON1_PIN);
        }
    }
    
    void BoardUtils_configure()
    {
        // GPIO configuration for LED
        cy_stc_gpio_pin_config_t user_led_port_pin_cfg = {
            .outVal = 0x00,
            .driveMode = CY_GPIO_DM_STRONG_IN_OFF,
            .hsiom = USER_LED1_PIN_MUX,
            .intEdge = 0,
            .intMask = 0,
            .vtrip = 0,
            .slewRate = 0,
            .driveSel = 0,
            .vregEn = 0,
            .ibufMode = 0,
            .vtripSel = 0,
            .vrefSel = 0,
            .vohSel = 0,
        };
    
        Cy_GPIO_Pin_Init(USER_LED1_PORT, USER_LED1_PIN, &user_led_port_pin_cfg);
    
        // GPIO configuration for button
        static cy_stc_gpio_pin_config_t user_button1_port_pin_cfg = {
            .outVal = 0x00,
            .driveMode = CY_GPIO_DM_HIGHZ,
            .hsiom = USER_BUTTON1_PIN_MUX,
            .intEdge = CY_GPIO_INTR_FALLING,
            .intMask = 1,
            .vtrip = 0,
            .slewRate = 0,
            .driveSel = 0,
            .vregEn = 0,
            .ibufMode = 0,
            .vtripSel = 0,
            .vrefSel = 0,
            .vohSel = 0,
        };
    
        Cy_GPIO_Pin_Init(USER_BUTTON1_PORT, USER_BUTTON1_PIN, &user_button1_port_pin_cfg);
    
        // IRQ configuration for button
        cy_stc_sysint_irq_t irq_cfg = {
            .sysIntSrc = USER_BUTTON1_IRQN,
            .intIdx = CPUIntIdx2_IRQn,
            .isEnabled = true,
        };
    
        Cy_SysInt_InitIRQ(&irq_cfg);
        Cy_SysInt_SetSystemIrqVector(irq_cfg.sysIntSrc, ButtonInterruptHandler);
    
        NVIC_SetPriority(CPUIntIdx2_IRQn, 3);
        NVIC_ClearPendingIRQ(CPUIntIdx2_IRQn);
        NVIC_EnableIRQ(CPUIntIdx2_IRQn);
    }
    
    void BoardUtils_toggleLED()
    {
        Cy_GPIO_Inv(USER_LED1_PORT, USER_LED1_PIN);
    }

    配置函数初始化LED和按钮引脚。然后它使用TRAVEO™ T2G图形驱动程序的GPIO和IRQ API将 ButtonsInterruptHandler() 注册为用户按钮事件的中断请求处理程序。

    注意:后端逻辑实现后,按板上的SW5硬件按钮可触发按钮事件。

  7. 要正确配置TRAVEO™ T2G LED和按钮,将main.cpp中的代码更改为包括boardutils.h头文件,并在正常平台初始化后调用BoardUtils_configure()
    #include "boardutils.h"
    ...
    
    int main()
    {
        Qul::initHardware();
        Qul::initPlatform();
        BoardUtils_configure();
        ...
    }
  8. 将新源文件添加到application.gpj
    #!gbuild
    ...
    
    # ----- backend -----
    ${BACKEND_DIR}/main.cpp
    
    ${BACKEND_DIR}/boardutils.c
    ${BACKEND_DIR}/deviceinterface.cpp

在Design Studio中集成UI和后端

使用Qt Design Studio中的DeviceInterface Singleton对象,以访问您在前一节中实现的后端低级函数。

  1. 在Qt Design Studio中打开您的项目并选择连接视图。
  2. 连接选项卡选择按钮,添加新的连接。

  3. 选择新的连接并使用连接面板打开代码视图。

  4. 代码视图中,添加第一个连接,将statusRect作为目标,将DeviceInterface.toggleLED()作为onPressedChanged信号的行事。

  5. 代码视图中,添加第二个连接,将DeviceInterface作为目标,将statusRect.pressed = !statusRect.pressed作为onButtonEvent信号的行事。

    现在当你按下按钮时,事件传播到 QML 上下文,这将修改 statusRect.pressed 属性。这会导致 UI 元素的颜色发生变化。在响应 statusRect.pressed 属性变化时,DeviceInterface.toggleLED() 方法切换 LED。

  6. 使用文本编辑器修改 yourproject.qmlproject 生成必要的 C++/QML 接口以用于单例对象。
    InterfaceFiles {
        files: ["C:/path/to/BACKEND_DIR/deviceinterface.h"]
    }

    BACKEND_DIR 路径更改为包含 deviceinterface.h 文件的目录。

    有关更多信息,请参阅 QmlProject 界面文件

在修改 UI 之后更新 GHS 项目

由于您已修改应用程序的 UI 部分,请使用 qmlprojectexporter 再次导出 UI 源代码。

使用以下命令行参数 --update-project 将 UI 代码中的新更改应用到现有的 GHS 项目。以下列出了以下方法之一

  1. 在 GHS MULTI Launcher 工作区中,使用 Sync Qmlproject files 下的预定义命令。在 UI 中双击它来更新项目文件。
  2. 使用以下批处理脚本手动调用 qmlprojectexporter
    set QUL_ROOT=C:\path\to\QtMCUs\2.8.0
    set QMLPROJECT_FILE=C:\path\to\YourProject.qmlproject
    set PROJECT_DIR=C:\path\to\PROJECT_DIR
    set QMLPROJECT_DIR=%PROJECT_DIR%\QtMCUs\generated
    
    %QUL_ROOT%\bin\qmlprojectexporter.exe %QMLPROJECT_FILE% --update-project=%PROJECT_DIR%/GHS/project.gpj

在特定的 Qt 许可证下可用。
了解更多信息。