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-baremetal
或 tviic2d4mlite-baremetal
。
- 创建包含以下命令的批处理脚本,该脚本调用
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_ROOT
和QMLPROJECT_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 项目适配步骤。
- 启动 GHS MULTI 启动程序 (
mstart.exe
) - 选择 文件 > 从文件加载 workspace... 并导航到上一节中导出的 %PROJECT_DIR%/GHS。选择 workspace 文件
mcu_<YourProject>_qul_workspace.gmb
。 - 在工作区中双击 项目经理 条目以在项目管理器中打开项目。
- 在任何目录下创建一个名为
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)。
- 右键单击
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 文档。 - 默认情况下,应用程序的二进制名称为
application.elf
。要使用不同的名称,请将-o application.elf
在program.gpj
项目文件中更改为-o YourProject.elf
。 - 此时,为了验证迄今为止所采取的步骤是否正确,您可以使用 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.bat
和qul_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++。
- 创建新的C++源和头文件,分别命名为
deviceinterface.cpp
和deviceinterface.h
,并将这些文件保存到您刚刚创建的BACKEND_DIR
目录中。 - 将
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::Singleton和Qul::EventQueue继承的
DeviceInterface
类。它还声明了buttonEvent
Signal和事件类型HWButtonEvent
。这允许Singleton实例全局可用。它提供了一个从C++到QML的接口,以在接收到HWButtonEvent
输入事件时发出changed
信号。有关更多信息,请参阅定义QML的Singleton和从中断处理程序传输数据到QML。 - 同样,将
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(); }
- 创建新的C源和头文件,分别命名为
boardutils.c
和boardutils.h
,并将这些文件保存在BACKEND_DIR
目录中。 - 将
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
- 将
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硬件按钮可触发按钮事件。
- 要正确配置TRAVEO™ T2G LED和按钮,将
main.cpp
中的代码更改为包括boardutils.h
头文件,并在正常平台初始化后调用BoardUtils_configure()
#include "boardutils.h" ... int main() { Qul::initHardware(); Qul::initPlatform(); BoardUtils_configure(); ... }
- 将新源文件添加到
application.gpj
#!gbuild ... # ----- backend ----- ${BACKEND_DIR}/main.cpp ${BACKEND_DIR}/boardutils.c ${BACKEND_DIR}/deviceinterface.cpp
在Design Studio中集成UI和后端
使用Qt Design Studio中的DeviceInterface Singleton对象,以访问您在前一节中实现的后端低级函数。
- 在Qt Design Studio中打开您的项目并选择连接视图。
- 在连接选项卡选择按钮,添加新的连接。
- 选择新的连接并使用连接面板打开代码视图。
- 在代码视图中,添加第一个连接,将
statusRect
作为目标
,将DeviceInterface.toggleLED()
作为onPressedChanged
信号的行事。 - 在代码视图中,添加第二个连接,将
DeviceInterface
作为目标
,将statusRect.pressed = !statusRect.pressed
作为onButtonEvent
信号的行事。现在当你按下按钮时,事件传播到 QML 上下文,这将修改
statusRect.pressed
属性。这会导致 UI 元素的颜色发生变化。在响应statusRect.pressed
属性变化时,DeviceInterface.toggleLED()
方法切换 LED。 - 使用文本编辑器修改
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 项目。以下列出了以下方法之一
- 在 GHS MULTI Launcher 工作区中,使用
Sync Qmlproject files
下的预定义命令。在 UI 中双击它来更新项目文件。 - 使用以下批处理脚本手动调用
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 许可证下可用。
了解更多信息。