使用 vscode+cmake 开发 G32R501
本帖最后由 wangqy_ic 于 2025-6-14 10:22 编辑#技术资源# #申请原创# @21小跑堂
概述
目前极海官方提供的 IDE 开发环境有 Keil/IAR/Eclipse。都能很好的完成开发,但是 VS Code 配合 CMake 工具是更加“现代”的C/C++开发环境,本文提供了在 VS Code 环境下的开发经验,以供参考。
准备工作
必需的软件有:
[*]cmake: 官网 https://cmake.org
[*]ninja: 官网 https://ninja-build.org
[*]VS Code:官网 https://code.visualstudio.com
[*]arm-clang 编译套件,keil 自带~
请从上述网站下载所需软件,版本采用最新版即可。此外,为了更好的使用 VS Code,还需要安装两个扩展:
[*]C/C++ Extension Pack
[*]CMake Tools
这里不再赘述扩展的安装方法。
Note:
ninja 的功能,也可以由 make 提供。
文件组织
为便于叙述,本文约定了如下的文件组织形式:
下面一一描述各项内容:
.vscode 文件夹
VS Code 的配置文件夹。
cmake 文件夹
针对编译器的必须文件。
G32R501_SDK 文件夹
G32R501 SDK 库,直接使用极海官网提供的 SDK 库。解压缩文件时请确保文件层级与上文所列一致。
projects 文件夹
用户项目文件夹。
子目录需要满足以下的目录结构:
├─INC --- 头文件目录
└─SRC --- C 文件 目录
如果实际目录结构与上面的不一致,则需要修改 CMakeLists.txt 文件。
CMakeLists.txt 文件
CMake 构建所必需的文件,下一节会详细说明。
详细说明
CMakeLists.txt 文件
CMake 构建 C/C++ 工程,是从工程根目录(或者指定的某个目录)下的 CMakeLists.txt 文件开始。CMakeLists.txt 描述了构建工程的源代码,编译选项。CMake 工具根据这个文件生成 Makefile 或者 ninja.build 文件。最后由 make 工具或者 ninja 工具执行编译工作。
CMakeLists.txt 遵循 CMake 相关语法,具体可以参考官方说明或者相应教程。这里贴出了 CMakeLists.txt 的内容。文中以“#”开始的行为注释行,可以参考注释行理解相关内容。
# Geehy, G32R5xx
cmake_minimum_required(VERSION 3.20)
cmake_policy(SET CMP0123 NEW)
project(g32r5xx_fw)
set(TARGET_NAME g32r5xx_fw)
# 检查 SDK 目录
set(SDK_ROOT G32R5xx_SDK)
get_filename_component(SDK_ROOT_ABS ${SDK_ROOT} ABSOLUTE)
if(NOT EXISTS ${SDK_ROOT_ABS})
message(FATAL_ERROR"SDK_ROOT: \"${SDK_ROOT}\" is not exists")
endif()
# 检查 APP 目录
get_filename_component(APP_ROOT_ABS ${APP_ROOT} ABSOLUTE)
if(NOT EXISTS ${APP_ROOT_ABS})
message(FATAL_ERROR"APP_ROOT: \"${APP_ROOT}\" is not exists")
endif()
# 检查分散加载文件
set(SCATTER_FILE_ABS ${SDK_ROOT_ABS}/device_support/g32r501/common/sct/${SCATTER_FILE})
if(NOT EXISTS ${SCATTER_FILE_ABS})
message(FATAL_ERROR"SCATTER_FILE: \"${SCATTER_FILE_ABS}\" is not exists")
endif()
# 打印项目信息
message(STATUS "LIBRARY_TYPE: ${LIBRARY_TYPE}")
message(STATUS " SDK_ROOT: ${SDK_ROOT_ABS}")
message(STATUS " APP_ROOT: ${APP_ROOT_ABS}")
message(STATUS "SCATTER_FILE: ${SCATTER_FILE_ABS}")
# 编译选项
set(MCPU_FLAGS "-mcpu=cortex-m52+cdecp0+pacbti -mfloat-abi=hard -fno-rtti -funsigned-char -fshort-enums -fshort-wchar -mlittle-endian -ffunction-sections")
set(CMAKE_C_FLAGS "${CMAKE_CXX_FLAGS} ${MCPU_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MCPU_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --strict --scatter ${SCATTER_FILE_ABS} --info summarysizes --map --load_addr_map_info --xref --callgraph --symbols --info sizes --info totals --info unused --info veneers --list project.map")
# 源码
file(GLOB APP_SRC ${APP_ROOT_ABS}/source/*c)
add_executable(${TARGET_NAME}
${APP_SRC}
)
set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".axf")
# 宏定义
target_compile_definitions(${TARGET_NAME} PRIVATE "-DG32R501_EVAL -D__CORE_CPU0__ -D__G32R501XX__ -D__G32R501__ -D__ARM_ARCH_8_1M_MAIN___ -D__ARM_TARGET_COPROC")
# include 目录
target_include_directories(${TARGET_NAME} PRIVATE ${APP_ROOT}/INC)
target_include_directories(${TARGET_NAME} PRIVATE ${APP_ROOT}/include)
target_include_directories(${TARGET_NAME} PRIVATE ${SDK_ROOT_ABS}/device_support/g32r501/common/device/Geehy)
target_include_directories(${TARGET_NAME} PRIVATE ${SDK_ROOT_ABS}/device_support/g32r501/common/device/CMSIS/Core/Include)
target_include_directories(${TARGET_NAME} PRIVATE ${SDK_ROOT_ABS}/device_support/g32r501/common/device/Geehy/system_eval/include)
target_include_directories(${TARGET_NAME} PRIVATE ${SDK_ROOT_ABS}/device_support/g32r501/common/include)
target_include_directories(${TARGET_NAME} PRIVATE ${SDK_ROOT_ABS}/driverlib/g32r501/driverlib)
target_include_directories(${TARGET_NAME} PRIVATE ${SDK_ROOT_ABS}/driverlib/g32r501/driverlib/inc)
# SDK 源码
file(GLOB_RECURSE CMSIS_SRC ${SDK_ROOT_ABS}/device_support/g32r501/common/device/Geehy/*.c)
target_sources(${TARGET_NAME} PRIVATE ${CMSIS_SRC})
file(GLOB DRIVERLIB_SRC ${SDK_ROOT_ABS}/driverlib/g32r501/driverlib/*.c)
target_sources(${TARGET_NAME} PRIVATE ${DRIVERLIB_SRC})
target_sources(${TARGET_NAME} PRIVATE ${SDK_ROOT_ABS}/device_support/g32r501/common/source/device.c)
# devicelib 类型项目必须添加的源码
if(${LIBRARY_TYPE} STREQUAL "device_lib")
file(GLOB DEVICE_SUPPORT_SRC ${SDK_ROOT_ABS}/device_support/g32r501/common/source/*.c)
list(APPEND DEVICE_SUPPORT_SRC ${SDK_ROOT_ABS}/device_support/g32r501/common/g32r501_globalvariabledefs.c)
target_include_directories(${TARGET_NAME} PRIVATE ${SDK_ROOT_ABS}/device_support/g32r501/headers/include)
target_sources(${TARGET_NAME} PRIVATE ${DEVICE_SUPPORT_SRC})
endif()
# 生成 HEX 文件
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND ${FROMELF_EXECUTABLE} --i32 --output ${TARGET_NAME}.hex [ DISCUZ_CODE_50 ]lt;TARGET_FILE:${TARGET_NAME}>
COMMENT "Creating HEX file")
# 生成 BIN 文件
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
COMMAND ${FROMELF_EXECUTABLE} --bin --output ${TARGET_NAME}.bin [ DISCUZ_CODE_50 ]lt;TARGET_FILE:${TARGET_NAME}>
COMMENT "Creating HEX file")
工程构建
使用 CMake 搭建的开发C/C++工程,编译前需要先进行配置(configure)再进行编译。
配置
执行类似下面的命令行可以配置一个工程:
cmake -DCMAKE_BUILD_TYPE:STRING=Debug -DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE -DCMAKE_TOOLCHAIN_FILE:STRING=cmake/g32r501.cmake -DLIBRARY_TYPE:STRING=device_lib -DSCATTER_FILE:STRING=g32r501xe_cbus_flash.sct -DAPP_ROOT:STRING=projects/app1 -B_build -G Ninja
参数说明:
[*]CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=TRUE 可选参数,用于生成 compile_commands.json 文件,便于 VS Code 开发使用。
[*]CMAKE_TOOLCHAIN_FILE:STRING=cmake/g32r501.cmake 必选参数,指定 MCU 是 g32r501。
[*]CMAKE_BUILD_TYPE:STRING=Debug 构建类型,可选的值有:Debug,Release,RelWithDebInfo 和 MinSizeRel,具体参考 cmake 文档。
[*]LIBRARY_TYPE:STRING=device_lib SDK 库类型,可选值有:device_lib,driver_lib。
[*]SCATTER_FILE:STRING=g32r501xe_cbus_flash.sct 分散加载文件的文件名,参考 G32R501_SDK*\device_support\g32r501\common\sct 目录。
[*]APP_ROOT:STRING=projects/app1 用户项目目录
打开命令行窗口,切换到工程根目录。执行上述命令前,请先定义一个环境变量 ARMCLANG_PATH,值是 armclang.exe 所在目录:
set ARMCLANG_PATH=C:\Users\<USER_NAME>\AppData\Local\Keil_v5\ARM\ARMCLANG\bin
其中 C:\Users\<USER_NAME>\AppData\Local\Keil_v5\ARM\ARMCLANG\bin 就是我的电脑上 ARM-CLANG 编译器的目录,请替换成实际值。
编译
在命令行里执行如下命令,就可以编译整个工程:
ninja -C _build
编译的固件会在 _build 文件夹下:g32r5xx_fw.hex 和 g32r5xx_fw.bin。
在 VS Code 里编辑和编译
“一个小手术”
为了能让 VS Code 更好的工作,我们在打开 VS Code 前,先弄好 VS Code的配置。在 .vsode 下,用文本编辑器创建 settings.json 文件,并写入如下内容:
文件中 cmake.configureArgs 部分内容与前文所述的“配置”部分大致相同,作用也就很明显了。这些参数控制着VS Code 更好的为我们工作。
经过前面的步骤,就可以启动 VS Code 打开工程所在根目录,就可以在 VS Code 里愉快地编码了。
更便捷地使用 VS Code
VS Code 提供了“任务”机制能让我们更好的进行开发。这里列举作者认为非常有助于提高效率的一个功能:实现“一键下载”。
点击 VS Code 菜单【终端】→ 【配置任务...】,在弹出的下拉列表里,选择【使用模板创建 tasks.json 文件】→ 【Others 运行任意外部命令的示例】。操作完成后会在 .vscode 目录下生成一个 tasks.json 文件,并打开。编辑这个文件:
tasks.json 文件里 tasks列表定义了若干可执行的命令及响应的命令参数。上述示例中名为 “Flash(MDK)” 的任务实际调用 keil 进行烧录;“Flash(JLINK)”任务是调用 JLink 进行烧录。
开发人员可以照例编排其他任务以提高开发效率。
附录
CMakeLists.txt 一些语法
变量
set(TARGET_NAME g32r5xx_fw)
上面的 set 语句定义了一个名为 TARGET_NAME 的变量,赋值:g32r5xx_fw。需要使用变量的值,需要用 \$\{\} 包含变量名,如:\$\{TARGET_NAME\}。
显示/打印信息
message(FATAL_ERROR"SCATTER_FILE \"${SCATTER_FILE}\" is not exists")message(STATUS "TOP_DIR: ${TOP_DIR}")
message 可以在配置过程中显示/打印一些信息。如果是 FATAL_ERROR 类型的信息,表明发生严重错误,配置构建过程立即结束,配置失败。
获取文件夹下的源文件列表
file(GLOB APP_SRC ${APP_ROOT}/SRC/*.c)file(GLOB_RECURSE APP_SRC ${APP_ROOT}/SRC/*.c)
第一句获取 ${APP_ROOT}/SRC 目录下全部的 C 代码文件。第二句获取 ${APP_ROOT}/SRC 目录及其子目录下全部的 C 代码文件(递归)。
如果只是个别文件,可以这样写:
set(APP_SRC ${APP_ROOT}/SRC/a.c ${APP_ROOT}/SRC/b.c ${APP_ROOT}/SRC/c.c)
一些内置的变量
cmake 有一些有用的内置变量:
[*]CMAKE_SOURCE_DIR:指向顶级 CMakeLists.txt 文件所在的目录,也称为源目录。
[*]CMAKE_BINARY_DIR:指向构建目录,即 CMake 构建的输出目录。
[*]CMAKE_CURRENT_LIST_DIR: 当前 CMakeLists.txt 所在目录。
[*]CMAKE_BUILD_TYPE:指定构建类型,如 Debug、Release、RelWithDebInfo 和 MinSizeRel。
/// 全文完
CMake 在使用GCC编译器时是一个开发辅助的优秀工具 星云狂想曲 发表于 2025-5-29 16:24
CMake 在使用GCC编译器时是一个开发辅助的优秀工具
除了 GCC,ARMCC, ARMCLANG, IAR 都可以 Keil又没有被禁止使用,干嘛要这么费劲去弄GCC呀!
看着都难,而且还不好调试 分形梦想家 发表于 2025-5-30 17:26
Keil又没有被禁止使用,干嘛要这么费劲去弄GCC呀!
看着都难,而且还不好调试 ...
vscode 里,调试确实不方便。但是 vscode 里编码确实方便很多。
特别是当前版本的 keil 中使用 Cortex-M52 内核的工程,代码提示和跳转符号定义的功能都没有,全手工编码真的很不方便:
- 写代码时,keil 左下角会显示:“Module error!textcompletion deactivated.”。
- 右键单击某个符号,弹出的菜单中,关于 “Go to Definition“那些菜单项全是灰色的~~~
wangqy_ic 发表于 2025-6-5 09:09
vscode 里,调试确实不方便。但是 vscode 里编码确实方便很多。
特别是当前版本的 keil 中使用 Cortex-M ...
keil编译,用source编辑代码不是也挺方便的吗? wangqy_ic 发表于 2025-6-5 09:09
vscode 里,调试确实不方便。但是 vscode 里编码确实方便很多。
特别是当前版本的 keil 中使用 Cortex-M ...
R501是不是一定要5.40版本的keil,我用5.38版本的keil根本无法编译。 本帖最后由 wangqy_ic 于 2025-6-24 22:09 编辑
dw772 发表于 2025-6-24 15:44
R501是不是一定要5.40版本的keil,我用5.38版本的keil根本无法编译。
是的,需要 5.40 或以上版本。具体可以参考官方应用笔记《AN1126_G32R501 IDE与工具链使用说明》:
这个应用笔记还说明其他 IAR, Eclipse 等工具链的使用。
极海没有自己的ide的吗? 更新Keil版本真是一件头疼的事情。
话说,现在jlink 已经到了v12的版本了吗?!
我这才从v8转到v9不久时间啊 wangqy_ic 发表于 2025-6-24 22:07
是的,需要 5.40 或以上版本。具体可以参考官方应用笔记《AN1126_G32R501 IDE与工具链使用说明》:
谢谢,现在真是麻烦啊,我更新了5.40版本后LKS又不能用了,又 卸载了5.40换回5.38了。 dw772 发表于 2025-7-4 17:11
谢谢,现在真是麻烦啊,我更新了5.40版本后LKS又不能用了,又 卸载了5.40换回5.38了。 ...
一台机器上可以同时安装两个版本的呀~
如果需要特定版本的 keil 打开工程,就先启动对应版本的 keil,在从菜单打开工程文件。
页:
[1]