免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

将基于keil的FreeRTOS+LVGL工程迁移到基于VSCode/Trae+clangd+CMake的新开发环境中

将基于keil的FreeRTOS+LVGL工程迁移到基于VSCode/Trae+clangd+CMake的新开发环境中 前言既然已经有了VSCode/TraeSTM32CubeMXclangdCMake的STM32开发环境那么以后的开发肯定是使用更优雅、更高级的平台所以将以往的FreeRTOSLVGL的keil工程迁移到新环境中。工程的迁移主要是LVGL的迁移与相关配置、添加业务代码FreeRTOS任务。1️⃣前置准备在CubeMX中重新生成一个CMake工程。将所有的硬件配置完成与原工程的配置一样不要忘记在Project Manager——Project——Linker Settings中配置堆和栈的大小默认的太小可能会导致运行失败。我设置的是Minimum Heap Size0x2000Minimum Stack Size0x2000。2️⃣添加硬件文件在新工程的根目录下新建文件夹Hardwares将原工程项目的Hardwares文件夹下的24CXX、DWT_delay、IIC、LCD、TOUCH等驱动文件复制进去原工程参考了正点原子的LVGL移植教程这里我的硬件文件可能由于具体业务原因与教程有出入但道理是一样的在CubeMX中我手动配置了FSMC所以正点原子给的文件中的FSMC的配置代码要删除当然用他们的配置也可以只要配置了就行。TOUCH中只需要touch.c和touch.h即可其他用不到不用复制。之后用VSCode打开工程后在CMakeLists.txt中添加源文件路径和头文件搜索路径。注意打开某些从原工程复制过来的文件如我这里的ads1220.c文件会发现报错这是因为cmsis_armcc.h是keil专用的CMSIS头文件里面大量使用keil编译器内置的intrinsic函数这些函数在keil中是内置的但是在arm-none-eabi-gcc中不存在GCC使用 __NOP()、__WFI() 或内联汇编因此clangd会报错。修复方法将#include cmsis_armcc.h注释掉引入新的头文件#include cmsis_gcc.h接着将所有的__NOP改为__NOP()。后面的警告是clang-tidyclangd 内置的代码风格检查器发出的可读性警告不是编译错误或功能问题意思是语句缩进太深但实际上的根本原因是这里的缩进错了只缩进了三个空格正常是一个tab即四个空格删掉前面的三个空格按一下tab即可解决。3️⃣编译LVGL为静态库将LVGL编译成静态库将原工程中Middlewares文件夹下的LVGL复制到新工程的Middlewares文件夹下。由于LVGL有非常多的源文件所以将源文件逐个添加到主工程的CMakeLists.txt中会非常繁琐而且不利于后期维护所以应该借助于CMake构建脚本。若移植的LVGL文件中有官方自带的CMakeLists.txt文件则直接使用即可它是官方已经写好的完整的CMake构建脚本维护了所有源文件列表和编译选项只需告诉CMake去哪找它即可。由于使用的是经过裁剪的LVGL文件里面没有LVGL的CMakeLists.txt所以需要自己创建。3.1在LVGL根目录Middlewares/LVGL/GUI/lvgl目录下新建一个CMakeLists.txt文件内容如下# 匹配当前目录结构的LVGL裁剪版构建脚本 cmake_minimum_required(VERSION 3.16) project(lvgl C) # 创建静态库目标 add_library(lvgl STATIC) # 1. 自动搜索所有核心源文件同时排除不需要的目录和文件 file(GLOB_RECURSE LVGL_CORE_SOURCES # examples/porting/*.c # 不需要examples目录下的所有文件移植层文件已经放入了主工程的Core/Src和Inc目录下 src/*.c # 在这里添加你想要排除的内容 EXCLUDE src/draw/nxp_pxp/*.c src/draw/nxp_vglite/*.c ) # 2. 添加核心源文件到库 target_sources(lvgl PRIVATE ${LVGL_CORE_SOURCES}) # 3. 添加头文件路径自动包含lv_conf.h和lvgl.h所在的根目录 target_include_directories(lvgl PUBLIC ${CMAKE_CURRENT_SOURCE_DIR} # 这一行已经包含了lv_conf.h和lvgl.h ) # 4. STM32嵌入式优化选项 target_compile_options(lvgl PRIVATE -Os -ffunction-sections -fdata-sections -fno-strict-aliasing )从上面的代码可以看出所有LVGL相关的构建逻辑都集中在这一个文件里顶层 CMakeLists.txt 保持干净整洁。主工程的CMakeLists.txt添加如下内容4️⃣解决CMake头文件搜索路径作用域问题一、移植层文件lv_port_indev_template.c和lv_port_disp_template.c报错报错在这两个文件中引用了lcd.h文件但是却找不到根本原因lcd.h在Hardwares/LCD/目录下而lv_port_disp_template.c这两个文件在Middlewares/LVGL/GUI/lvgl/examples/porting/目录下。1.Hardwares/LCD/只被添加到了主工程的头文件搜索路径2.lv_port_disp_template.c被编译成了LVGL 库的一部分3.LVGL 库的头文件搜索路径只有它自己的根目录不知道Hardwares/LCD/在哪里即main.c可以找到lcd.h因为它属于主工程LVGL 库内部的文件找不到lcd.h因为 LVGL 库不知道主工程的硬件目录。解决方法不要把移植层文件放在 LVGL 库里面编译。移植层代码是针对特定硬件的代码不属于通用的 LVGL 库。1.确保LVGL库中排除移植层文件确保LVGL的CMakeLists.txt中的file(GLOB_RECURSE LVGL_CORE_SOURCES ...)一项中没有递归包含examples文件夹下的源文件上文中确实没有包含。2.将移植层文件移动到主工程复制以下文件到Core/Src目录lv_port_disp_template.c → 重命名为lv_port_disp.clv_port_indev_template.c → 重命名为lv_port_indev.c复制以下文件到Core/Inc目录lv_port_disp_template.h → 重命名为lv_port_disp.hlv_port_indev_template.h → 重命名为lv_port_indev.h3.修改移植层文件的头文件引用编辑lv_port_disp.c对lv_port_disp.c做同样的操作将原来的#include lv_port_disp_template.h#include ../../lvgl.h#include lcd.h改为#include lv_port_disp.h#include lvgl.h#include lcd.h注意现在这两个文件中的lvgl.h必须要直接引用不能使用相对路径引用否则报错。4.在主工程的CMakeLists.txt中添加移植层文件在target_sources中添加这两个文件Core/Src/lv_port_disp.cCore/Src/lv_port_indev.c二、LVGL使用FreeRTOS提供的心跳报错报错构建工程失败lv_conf.h找不到FreeRTOS.hlv_hal_tick.h找不到FreeRTOS.h且找不到函数xTaskGetTickCount的定义根本原因LVGL 库的头文件搜索路径中没有包含 FreeRTOS 的头文件目录。1.在lv_conf.h中开启了LV_TICK_CUSTOM 1告诉 LVGL 使用 FreeRTOS 的系统时钟2.LVGL 内部的lv_hal_tick.c文件会自动包含指定的FreeRTOS.h并调用xTaskGetTickCount()3.但是FreeRTOS 的头文件路径只被添加到了主工程的头文件搜索路径没有被添加到 LVGL 库的头文件搜索路径4.当 LVGL 库自己的源文件lv_hal_tick.c试图包含FreeRTOS.h时编译器找不到这个文件解决方法中间层抽象。LVG 作为一个通用GUI库绝对不应该直接依赖任何特定的 RTOS。可以通过依赖倒置原则解决此问题实现LVGL与FreeRTOS的零直接耦合。1.修改lv_conf.h移除FreeRTOS直接依赖使用自己的端口头文件lv_freertos_tick.h调用自己的抽象函数lv_get_freertos_tick()。2.在主工程中新建两个文件Core/Inc下创建lv_freertos_tick.h非常简单只有函数声明注意一定要包含stdint.h否则构建后报错uint32_t找不到定义Core/Src下创建lv_freertos_tick.c唯一与FreeRTOS有耦合的地方3.将这两个文件添加到主工程的CMakeLists.txt中在target_sources里添加Core/Src/lv_freertos_tick.cFreeRTOS为LVGL提供的获取心跳节拍函数的源文件lv_freertos_tick.h位于目录Core/Inc下而target_include_directories里已经包含了Core/Inc所以不用做任何改变。4.在主工程的CMakeLists.txt中给LVGL添加lv_freertos_tick.h的头文件搜索路径若不做这一步构建后还是会报错lv_hal_tick.c找不到lv_freertos_tick.h以及调用未定义函数lv_get_freertos_tick()。原因编译 LVGL 库的时候注意不是编译主工程的时候编译器需要找到 lv_freertos_tick.h但上面只把 Core/Inc 添加到了主工程的 PRIVATE 头文件路径中这意味着只有主工程的源文件能看到 Core/IncLVGL 库的源文件完全看不到这个目录。解决方法在主工程的 CMakeLists.txt 中add_subdirectory(Middlewares/LVGL/GUI/lvgl)之后添加以下代码target_include_directories(lvgl PRIVATE ${CMAKE_SOURCE_DIR}/Core/Inc)相当于在主工程的CMakeLists.txt 中将lv_freertos_tick.h的搜索路径Core/Inc传给了lvgl目标。这个方法符合模块化设计LVGL 依赖一个抽象的接口lv_freertos_tick.h主工程提供这个接口的具体实现lv_freertos_tick.c以后换 RTOS 时只需要替换 lv_freertos_tick.c 的实现LVGL 代码一行都不用改这个解决方法的一个重要好处若使用直接在LVGL库的头文件搜索路径中包含FreeRTOS的头文件目录这一方法虽然最后也可以构建成功但是烧录程序后会发现无现象调试后发现程序卡死在DWT的微秒级延时函数delay_us的while ((DWT-CYCCNT - start_tick) target_tick);语句中调试找到的原因是程序未能成功进入DWT初始化函数DWT_Init的if (!(CoreDebug-DEMCR CoreDebug_DEMCR_TRCENA_Msk))判断中导致CYCCNT计数器没有开启必须把这个判断去掉才能使得DWT初始化成功最终程序运行成功见到正常现象详细的原因还没有真正弄清楚。但是若使用本方法则不会出现这个问题DWT_Init函数能够进入if判断正常初始化并开启CYCCNT计数器。5️⃣Git忽略无关变动配置如图在Trae中使用了git工具管理我的工程文件。有时候我只是在文件中增删了空行或者编译生成的文件发生了变动git就会检索到这些变动。而这些变动无关紧要应该被忽略。一、优先解决忽略编译生成文件这些文件每次编译都会自动生成没有版本价值还会导致Git仓库臃肿和大量无关提交。步骤 1创建 / 修改.gitignore 文件在项目根目录创建.gitignore文件添加以下针对 STM32CMakeTrae 工程的规则CMake构建产物 build/ cmake-build-*/ CMakeFiles/ CMakeCache.txt cmake_install.cmake install_manifest.txt compile_commands.json *.ninja *.cmake 编译中间文件和可执行文件 *.o *.obj *.a *.lib *.so *.dll *.exe *.elf *.hex *.bin *.map IDE和工具生成文件 .vscode/ .idea/ *.swp *.swo *~ .DS_Store Thumbs.db # Trae特定文件 # .trae/步骤 2从 Git 中移除已跟踪的编译文件注意这不会删除本地的文件只是让Gi 停止跟踪它们。在终端中运行以下命令# 移除整个build目录的跟踪 git rm -r --cached build/ # 移除其他已跟踪的编译文件 git rm --cached CMakeCache.txt git rm --cached compile_commands.json # 如有其他需要移除的文件继续添加 # 提交变更 git add .gitignore git commit -m chore: 配置.gitignore并移除编译生成文件的跟踪完成后源代码管理界面会立刻干净很多再也不会出现大量编译文件的变动了。二、VS Code (Trae) 界面忽略空白和空行差异显示对于源代码文件中只增删了空行或调整了空格的情况我们可以让VSCode的差异视图不显示这些变化只关注实质性的代码改动。全局设置1.打开IDE的设置快捷键Ctrl,2.搜索以下两个设置项并修改diffEditor.ignoreTrimWhitespace勾选忽略行首行尾的空格变化scm.diffDecorationsIgnoreTrimWhitespace设置为inherit让侧边栏的差异标记也遵循上面的设置上面的方法只能忽略空白和空行无法忽略注释的变化。如果需要忽略注释的改动需要配置自定义的 Git 差异驱动。⚠️ 重要警告这种方法有风险因为注释有时候也是重要的改动比如修改了函数说明文档。因此我没有做忽略注释的相关操作。至此原本基于keil的FreeRTOSLVGL工程成功迁移到了新的开发环境上接下来只要编写相应的业务代码比如显示任务的代码即可。以后不论是使用Trae中的原生Agent还是VSCode中的Codex插件都可以实现Agent辅助编程且无论是显示界面还是代码提示和索引等都看起来非常现代化。此外还发现迁移前后两个工程文件大小包含编译文件也有区别keil MDK的文件大小270MBTrae CMake的文件大小189MB。
返回列表