尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

TouchGFX工程升级实战:从评估备份到踩坑避坑全流程

TouchGFX工程升级实战:从评估备份到踩坑避坑全流程 做TouchGFX开发最烦的事儿不是画界面也不是调时序而是老工程升级。手上跑得好好的项目因为客户要求、新芯片BOM变更或者单纯想用新版本Designer里的某个控件就不得不面对从旧版本迁移到新版本这件事。这篇文章就是我在实际项目里把TouchGFX从旧版本升级到新版本的全过程记录包括升级前怎么评估、升级时怎么操作、升级后怎么验证以及踩过的各种坑。如果你手头正好有个老工程要动这篇笔记可以直接照着走。先说清楚这不是一篇劝你“有新版就赶紧升”的文章。TouchGFX的升级路径跟普通桌面软件不太一样它牵扯到Designer工具、固件包、生成代码、HAL层、链接脚本、编译器版本一环扣一环。升得好是平滑过渡升不好就是一天的编译错误。所以我建议你先花十分钟把我下面要讲的思路过一遍再动手。1. 升级前先搞清三件事为什么要升、能不能升、怎么备份1.1 版本升级到底动的是什么很多人把TouchGFX升级理解成“换个Designer安装包”其实这只是最表层的一步。TouchGFX的版本体系大致分三层TouchGFX Designer可视化界面设计工具负责画界面、配交互、生成代码。TouchGFX Engine / Framework实际运行在MCU上的图形库源码包含控件、渲染器、字体引擎、缓存管理等模块。Designer生成的工程里会引用这个框架代码。STM32CubeMX固件包FW PackST官方把TouchGFX引擎、HAL驱动、BSP示例打包进CubeMX的固件包由CubeMX在生成工程时解包出对应版本。所以升级不光是“装个新版Designer”你项目里那份framework代码、HAL适配层、甚至BoardConfiguration都要跟着变。在旧项目里framework代码通常直接躺在工程目录的Middlewares/ST/TouchGFX或者TouchGFX文件夹下很多人的项目是直接把整个文件夹拷进工程管理的这就导致一个问题Designer升级了但工程里的framework还是一年前的版本。LAT1227这篇应用笔记的中心思想其实很简单升级要“工具链框架代码工程配置”三者同步缺一个都会出幺蛾子。我后面讲的全是围绕这三件事展开的。1.2 升级前的环境盘点与兼容性判断动手之前先把当前环境摸个底。我会把下面这些信息记在一个文本文件里省得升级到一半才发现某个组件版本对不上。当前TouchGFX Designer版本号打开Designer菜单Help - About里能看到。当前工程使用的TouchGFX版本在touchgfx/目录下的version.txt或gcc工程的Makefile里能看到框架版本号。STM32CubeMX版本号。HAL库版本工程里Drivers/STM32xxx_HAL_Driver对应的版本比如1.11.0。编译器/IDE版本MDK的AC5还是AC6IAR版本GCC版本这个非常关键新版TouchGFX某些版本开始默认要求更高的编译器标准如C14AC5在某些情况下会有兼容问题。当前使用的芯片型号和封装比如从STM32F429的老项目升级芯片没变但固件包变了HAL层驱动可能有差异。把这些信息列出来之后去ST官网或者TouchGFX的Release Notes查一下目标版本的兼容矩阵比如某个TouchGFX版本对最小HAL版本、最小CubeMX版本有没有要求。新版TouchGFX跟老版本HAL混用时最常见的症状就是编译能过运行时随机死机或者屏幕不刷新这种问题定位起来比编译报错痛苦得多。提示如果你用的是STM32CubeMX生成器方式官方建议TouchGFX Designer和CubeMX的固件包版本尽量匹配差太远的时候CubeMX在生成环节就会直接弹版本不匹配警告。遇到这种情况优先把固件包升级到和Designer匹配的版本。1.3 项目备份与状态确认很多人觉得“备份不就是拷贝一份文件夹吗”但在TouchGFX工程里没那么简单因为工程里有一部分代码是你写的有一部分是生成的还有一部分是工具链自动维护的。升级过程中Designer重新生成代码时会覆盖generated目录下的文件也会更新assets目录里的图片/字体转换结果。如果备份不完整万一升级失败想回滚会发现自己改过的代码混在生成代码里根本没法干净地还原。我的做法是分三步备份整个工程目录压缩存档一份这是最基础的保底操作。注意把.git目录或者版本管理的历史一起带上如果项目本身在Git里先确保所有修改都提交了打一个tag。单独导出用户代码区。TouchGFX用User Code区块保护用户代码这个区块在生成文件里一般用USER_CODE_BEGIN和USER_CODE_END注释标记。我习惯在升级前把每个文件里的用户代码手动过一遍确认哪些是“必须要留的”。特别是Screen1View.cpp、Screen1Presenter.cpp、MainView.cpp这些文件升级后大概率会被重新生成如果里面有大段逻辑代码最好单独复制一份放到项目外的备份目录。记录资源文件状态。字体、图片、文本资源在Designer里的配置会被存储到assets目录升级后Designer需要重新转换这些资源。如果你的项目用了很多字体特别是非拉丁语系字体升级后字体生成规则如果有变化渲染效果可能会变备份时把assets/fonts、assets/images的原始文件也单独留一份。做完这三步你手里才有了一张“后悔药”。我见过太多人升级到一半项目崩溃想回滚却发现自己之前改的代码被覆盖了最后只能加班重写。2. 核心升级操作流程从工具链到代码生成2.1 升级TouchGFX Designer与固件包先升级工具本身。如果升级跨度比较大比如从4.13直接跳到4.21我的建议是不要跳级升级最好逐步来或者至少先在新版Designer里打开项目看一下兼容性提示。TouchGFX的项目文件.part是有版本标记的新版Designer能打开旧版项目但反过来不行所以一旦你保存了新版格式旧版Designer就打不开了。升级前务必确认团队里其他同事的Designer版本也同步更新了不然项目文件来回切换会出问题。安装新版Designer之后需要到STM32CubeMX - Help - Manage embedded software packages里检查TouchGFX固件包是否需要更新。在CubeMX的固件包管理器里找到对应的MCU系列展开TouchGFX组件勾选你需要的版本。这里有个细节如果你的项目是用CubeMX生成的CubeMX在下次生成时才会使用新固件包如果你已经有独立的TouchGFX Designer工程Designer也有自己的包管理路径两者别搞混。设计师工具的升级比较简单真正容易翻车的是后面这一节。2.2 使用STM32CubeMX更新项目配置如果你的工程是CubeMX TouchGFX Designer联合生成的这是最主流的STM32工程组织方式升级核心步骤就发生在CubeMX这一层。操作路径大致是用新版CubeMX打开原来的.ioc文件。CubeMX会提示固件包版本更新确认升级到与TouchGFX配套的版本。在Middleware and Software Packs里找到TouchGFX看一下版本号是否变为目标版本。如果版本不对在软件包管理里安装正确版本后回来重新选择。重新生成代码。这里要注意一个细节CubeMX重新生成代码时会生成新的touchgfx配置头文件和链接脚本相关的配置。如果你的工程用了自定义链接脚本比如把帧缓冲Framebuffer放到外部SDRAM重新生成时CubeMX有可能覆盖或者保留取决于你的配置方式。我遇到过的情况是CubeMX重新生成后stm32f4xx_hal_msp.c里的HAL_MspInit被重新生成把我手动加进去的SDRAM GPIO初始化代码冲掉了。所以重新生成后第一件事是检查main.c、stm32f4xx_hal_msp.c、stm32f4xx_it.c这几个文件里的用户代码是否完好。如果你用的是纯TouchGFX Designer生成方式不经过CubeMX那升级路径相对简单一些直接在Designer里打开项目它会提示项目是用旧版本创建的询问是否迁移。我建议点确定之前先看一眼迁移日志新版Designer的迁移机制会尝试把旧工程配置转换成新格式但并不是所有设置都能100%保留特别是自定义控件、自定义字体、文本排版相关的配置经常需要手动调整。2.3 重新生成代码与增量迁移用户代码这一步是整个升级过程的“技术核心”。重新生成代码之后你的工程里会出现一批新文件同时有些旧文件会被删除或改名。不要急着编译先看一下目录变化。以TouchGFX 4.x版本为例生成代码的主要目录是generated/gui_generatedDesigner根据界面配置自动生成的代码包括每个Screen的View/Presenter基类。generated/texts、generated/images、generated/fonts资源和字体描述文件。gui/src、gui/include用户代码所在目录View、Presenter、Model的实际实现文件在这里。Designer里勾选了“Generate Code”的改动会改变这些文件里handleXXXX等函数的结构但USER_CODE_BEGIN/END区块会被保留。targetHAL相关代码比如STM32F4HAL.cpp、TouchGFXHAL.cpp等。升级后常见的情况是generated/gui_generated下的文件结构发生了变化比如新增了Screen1ViewBase的某些方法而gui/src下的文件里你的用户代码还在但可能因为基类接口变了而编译不过。我的建议是不要用“对比所有文件”的心态去处理先看图先编译一次收集所有编译错误。按“错误信息所属文件”分类错误在generated目录下的文件里说明是生成代码自身的问题一般不是你造成的可能是生成过程不干净尝试删掉generated目录重新生成。错误在gui目录下的文件里这才是真正的迁移工作点逐步修改你的代码以匹配新基类的API。错误在target或HAL目录这些通常是配置问题优先检查链接脚本、时钟配置、以及帧缓冲地址。增量迁移用户代码时我的习惯是先改最容易编译通过的部分再处理逻辑迁移。比如Model.cpp、ModelListener.cpp这些与界面交互逻辑相关的文件一般API变化不大而Screen1View.cpp里可能会引用新版本改动的控件方法需要逐一对齐。2.4 编译链接与初始验证代码迁移到能编译通过只是万里长征走完了一半。接下来先别急着烧录做这几步检查链接脚本检查确认.ld文件或*.sct文件里帧缓冲区和堆栈的地址是否与新固件包默认值一致。特别是芯片内部RAM比较小的型号如果新版引擎默认帧缓冲配置改了可能直接链接报错“region overflow”或者链接通过但运行时硬件异常。MPU配置检查新版TouchGFX引擎在某些芯片上默认启用了Cache和MPU配置比如STM32F7/H7系列。如果你的项目之前没开Cache升级后发现刷新率异常或者出现花屏多半是MPU配置没有和引擎的帧缓冲访问方式匹配起来。时钟与像素时钟配置TouchGFX跟LTDC/SDRAM打交道时钟一变整个显示都乱。确认CubeMX里LTDC时钟、像素时钟、SDRAM时序没有被CubeMX升级“自动优化”成另一个值这种问题通常在升级后表现为“能点亮但是画面抖动”。以上这些通过以后烧录运行先看启动logo是否正常再挨个页面点一遍确认跳转、控件刷新、触摸反馈等基本功能没退化。3. 升级过程中最常见的坑与应对方案3.1 编译报错类型一framework API变更这是所有升级操作里最避不开的一关。TouchGFX不同版本之间控件和渲染API会持续演进比如某个版本的TextArea新增了setTypedText的重载或者Container::add()的访问级别发生了变化。升级后编译报错会在所难免但好在大部分错误都有规律。我整理过一个速查表升级时经常碰到的几类错误报错特征大概率原因应对方法error: no matching function for call to setXXX控件API签名变化旧参数类型不再兼容查新版API文档确认新的参数类型或默认参数error: XXX is not a member of touchgfx::YYY某个方法或枚举被重命名或移动到其他类全局搜索旧方法名在新版framework头文件里确认对应替代error: expected class-name before { token基类文件名或类名变化比如Widget父子关系调整检查#include头文件路径和类继承声明error: Thread was not declared in this scope老版本里Thread来自某个头文件新版可能被拆开或改名查看framework的include/touchgfx目录确认头文件变化error: comparison between signed and unsigned integer expressions新版本编译器开启更严格的警告代码本身没大问题加显式类型转换或调整编译警告级别处理API变更时我的建议是别急着改你自己的代码先看framework里有没有新替代。很多情况下老方法不是消失了而是换了个名字或者接收不同参数类型。你直接在新版框架的头文件里去搜旧方法名能搜到说明只是变了签名搜不到再考虑是不是真的废弃了。3.2 编译报错类型二字体/图片资源路径变化这类问题在升级大版本时特别常见因为新版Designer可能调整了资源目录结构或者文本转换规则。具体表现包括编译时报找不到fonts/xxx.ttf或images/xxx.png。编译能过但运行时文字显示为方框或空白。图片在Designer预览里正常烧到板子上显示错位或者颜色异常。这类问题排查路径很固定先看assets目录下的文件是否还是原样再看generated/fonts/src下生成的字体描述文件确认字符集是否正确最后看generated/images/src下图片的像素格式RGB565、ARGB8888等是否与LCD面板匹配。我踩过一次很大的坑旧项目用的是一套中文字体升级后新版Designer默认把字体子集化策略改了导致转换出来的字体文件只包含ASCII字符所有中文全变成了豆腐块。排查了好久发现是字体设置界面的“Fallback Character”和“Character Set”配置被重置成了默认。解决办法是回到字体配置里手动把需要的文字范围重新选上重新生成字体资源。3.3 运行类问题显示异常、触摸不灵、内存崩溃编译通过只是第一步真正让人头皮发麻的是那些“看起来一切正常跑起来就崩”的问题。这类问题在升级后特别常见因为新框架在底层渲染机制上可能发生了变化而你的硬件配置还是按老版本调的。最常见的运行类问题有白屏/花屏先查帧缓冲地址范围。升级后如果CubeMX重新生成了stm32f4xx_hal_msp.c或链接脚本SDRAM初始化时序、帧缓冲地址、以及TouchGFXHAL里的frameBufferBegin、frameBufferEnd可能对不上。用调试器检查第一帧写入的地址是否落在有效SDRAM范围内。触摸没反应或者乱跳先看触摸屏的I2C/SPI配置是否被CubeMX重置。再查TouchGFX的TouchGFXHAL::endFrame里是否有触摸回调处理。新版框架对触摸采样点的坐标转换方式偶尔会有调整如果出现点击位置偏移检查Application::setTouchCoordinate相关逻辑是否还需要手动做坐标映射。随机死机这个最难查。百分之八十的情况是内存冲突或Cache一致性问题。STM32F7/H7这类带Cache的芯片上如果DMA2D和CPU同时访问帧缓冲没有正确配置MPU或没有做Cache clean/invalidate就会出现随机花屏和死机。升级后框架对帧缓冲的访问模式可能改变建议重新审视MPU配置和SCB_InvalidateDCache等调用是否还在关键路径上。如果你在升级后遇到这种“玄学”问题我强烈建议打开TouchGFX引擎自带的touchgfx_log或者接上调试器在hard fault handler里打上断电点把出错时的PC指针地址对应到具体的框架函数往往能直接定位到是缓存问题还是缓冲区越界。3.4 回滚策略与版本共存升级失败是很正常的所以回滚策略一定要在动手前想好。我的做法是Git分支管理升级前创建一个upgrade_touchgfz_x.x.x分支原来的master按兵不动。一旦升级失败checkout回老分支工程马上恢复可用。如果没在用Git至少把备份目录放到工程同级不要放在工程内部。因为升级过程中Designer可能会清空某些目录放在工程内的备份也有被误删的风险。版本共存技巧我的电脑上装了TouchGFX Designer的多个主版本比如4.18和4.21。这在新版Designer和老版本共产并存上是可行的只要安装目录选择不同路径。这样我就可以随时用旧版Designer打开旧工程对比新版迁移后的差异。要注意的是同一时间只开一个Designer同时打开多个版本在某些Windows机器上会有资源文件的锁冲突。4. 排查技巧实录与效率工具组合4.1 用Diff方式定位生成代码变更升级时最忌讳的经验就是“哪里报错就改哪里”改来改去自己代码变成了一锅粥。我推荐的做法是重新生成代码之后用Beyond Compare或者Meld这类工具把generated/gui_generated目录下的新文件和旧版本的同名文件做一次批量对比。Diff的价值在于它能直观告诉你新版框架在生成代码层面到底改了哪些默认行为。比如我升级后发现界面上一个按钮的位置变了Diff一查发现是generated/gui_generated/src/screen1_screen/Screen1ViewBase.cpp里的坐标常量发生了偏移。这种变更不是你的代码问题而是生成规则变了找到根因后要么在Designer里重新摆放控件要么在用户代码里显式覆盖坐标然后就不会一头雾水地瞎调了。Diff的时候我一般重点看这三个维度文件名变化旧文件是否被拆分成多个文件或合并成一个文件。类名和继承关系新旧版本中ViewBase类的继承链是否变化这直接影响你用户代码里setupScreen、handleTick这些重写方法是否能正确覆写。新增的虚函数新版引擎可能给ViewBase增加了新的虚函数比如handleGestureEvent、screenClick等。如果新版把某个事件处理方法拆成了两个你在旧版里写在一个方法里的逻辑就要按新接口重新拆开。4.2 善用TouchGFX Designer的模拟器很多嵌入式工程师习惯“直接烧板子看效果”但在升级验证阶段我反而更推荐先用TouchGFX Designer自带的模拟器Simulator做一轮快速检查。模拟器跑的是主机平台上的TouchGFX引擎能直观验证界面布局、控件行为、文本渲染这些与硬件无关的部分。升级后在模拟器里先跑一遍的好处是能快速发现文本溢出、图片缺失、布局错位这类常见问题不用反复烧录。模拟器环境下CPU/内存资源充足能把“硬件资源不够”和“代码本身有问题”这两类问题分开。模拟器支持调试器挂接可以直接在IDE里打断点调试迁移后的交互逻辑。当然模拟器测不出真实硬件的时序问题所以模拟器里过了只能说明逻辑层面没问题最终验证还是得到板子上做。我通常的做法是“双轨验证”先跑模拟器把跟UI逻辑相关的迁移问题解决掉再烧板子把跟驱动、内存、缓存相关的问题解决掉。两者各司其职效率最高。4.3 实测过的一套高效升级工作流踩过几次坑之后我现在升级TouchGFX项目基本固定用下面这套流程你们可以直接参考环境盘点确认Designer版本、CubeMX版本、固件包版本、HAL版本、编译器版本全部记录。代码备份整个工程打包并单独导出用户代码区确认Git提交干净。工具升级安装新版Designer在CubeMX里升级TouchGFX固件包。工程迁移CubeMX打开.ioc并重新生成代码确认用户代码区块完好。首次编译只改必须改的API调用先让工程跑起来。模拟器冒烟测试过一遍所有页面和交互记录所有异常。板级验证烧录后重点看显示、触摸、帧率、随机死机这四类问题。回归测试如果项目有自动化测试脚本跑一遍没有的话弄一个简单的“页面巡检”程序自动遍历所有屏幕和主要控件状态。收尾存档升级结束后更新项目的README或版本说明记录升级前后的版本号差异以及本次手动改动了哪些文件。这套流程看起来繁琐但每一步都有它在实操中的价值。尤其是第5步“先让工程跑起来”这个原则很多新手容易忽略一上来就想把所有新功能用上结果新旧代码混在一起排查困难。我始终建议迁移期间不要顺手加新功能先把老功能在新版本上原样跑通这能极大降低排查难度。4.4 升级后的长期维护建议升级不是一次性动作升级完成后的工程维护同样重要。有几个习惯我建议尽早养成把generated目录纳入代码管理虽然它是自动生成的但在升级对比和回溯问题时有历史记录会方便很多。很多团队喜欢忽略生成目录结果每次升级后想对比差异都无从下手。用户代码和生成代码严格分离永远不要改generated目录下的文件哪怕只是加一个临时调试打印。一定要改的话请想办法把你的逻辑放到gui/src或target下对应的用户文件里。这个原则能保证你每次都能安全地“重新生成”。记录每个版本的升级日志升级完成后花五分钟在项目文档里写一句“从4.18升到4.21改动X、Y、Z出现的问题A、B、C及处理方式”。下次再升级时你翻翻这个日志会省下大量时间。最后说点实际的我在项目里遇到过不止一次升级升级后“莫名其妙”多出来的Bug后来发现很多都是升级时被工具“顺手”改掉的配置比如CubeMX重新生成后某个引脚的初始电平被翻转了或者某个外设的时钟分频系数被调整了。所以升级完别急着高兴花点时间把和显示、触摸、SDRAM、DMA相关的配置项核对一遍比调半天代码都管用。这套方法我验证过几次不能说百分百无痛但至少能把升级从“开盲盒”变成“按流程走”。希望这篇笔记对你有帮助。
返回列表