VSCode编辑+GCC for ARM交叉编译工具链+CMake构建+OpenOCD调试(基于STM32的标准库/HAL库)

一、CMake安装

  • 进入CMake官网的下载地址Get the Software,根据系统安装对应的Binary distributions。
    在这里插入图片描述
  • 或者在CMake——国内镜像获取二进制镜像安装包。 在这里插入图片描述
  • 或者访问GitHub的xPack项目xPack CMake v3.28.6-1,下载即可。

记得添加用户/系统的环境变量,打开cmd窗口,输入cmake -version,查看CMake环境变量是否添加成功,如下图所示。
在这里插入图片描述

二、VSCode各个配置脚本文件

本文以【STM32F103ZET6】单片机为示例来进行演示,以下配置文件对于标准库/HAL库工程是通用的。
更多细节请基于【VSCode编辑+GCC for ARM交叉编译工具链+Makefile构建+OpenOCD调试(基于STM32的标准库)】参考。
下面列出几个主要的配置文件:

  • settings.json

  • c_cpp_properties.json

  • tasks.json

  • launch.json

  • CMakeLists.txt

  • settings.json、c_cpp_properties.json、tasks.json、launch.json的修改要点请参考【.vscode文件夹中各个JSON脚本需要修改的地方】。

  • MCU链接脚本.ld、MCU汇编启动文件.s、MCU寄存器文件.svd的获取方式请参考【VSCode编辑+GCC for ARM交叉编译工具链+Makefile构建+OpenOCD调试(基于STM32的标准库)】。

settings.json:

{// 字符集编码选择"files.encoding": "utf8",// 自动保存任意文件"files.autoSave": "afterDelay",// 开启 material icons"workbench.iconTheme": "office-material-icon-theme",// theme主题设置"workbench.colorTheme": "Default Dark Modern",//粘贴时格式化代码"editor.formatOnPaste": true,//保存时格式化代码"editor.formatOnSave": true,//设置字体的大小,最小值能设置为6"editor.fontSize": 15,//设置字体的粗细"editor.fontWeight": "500",//设置字体的样式// "terminal.integrated.fontFamily":"Courier New",//使用Ctrl+滚轮缩放编辑区的字体大小"editor.mouseWheelZoom": true,//使用Ctrl+滚轮缩放终端Terminal的字体大小"terminal.integrated.mouseWheelZoom": true,//设置为false,这样打开新的文件时,不会自动关闭旧的文件"workbench.editor.enablePreview": false,"security.workspace.trust.enabled": false,"VsCodeTaskButtons.showCounter": true,"VsCodeTaskButtons.tasks": [{"label": "$(tools) Build", // 显示标签"task": "CMake build", // 对应tasks.json里的任务label"tooltip": "🛠️ build" // 工具提示框},{"label": "$(notebook-delete-cell) Clean","task": "CMake clean","tooltip": "🧹 clean"},{"label": "$(notebook-delete-cell) $(tools) Re-bulid", //"$(notebook-delete-cell) & $(tools)","task": "CMake cleanRebuild","tooltip": "🛠️ rebuild" // "🧹 & 🛠️ rebuild"},{"label": "$(zap) Download",// "task": "CMake download","tasks": [{"label": "⚓ CMSIS-DAP-Link", //icon copied from https://emojipedia.org/"task": "flash with CMSIS-DAP-Link"},{"label": "⤵️ ST-Link", //icon copied from https://emojipedia.org/"task": "flash with ST-Link"},{"label": "🚀 J-Link", //icon copied from https://emojipedia.org/"task": "flash with J-Link"}],"tooltip": "⚡ download"}],
}

c_cpp_properties.json:

{"configurations": [{"name": "Win32-arm-gcc-dev","includePath": [    // 设置编辑器中的头文件查找目录"${workspaceFolder}/**"],"defines": ["_DEBUG","UNICODE","_UNICODE","__CC_ARM"      // 解决编辑器中提示无法识别uint32_t, uint16_t, uint8_t的问题],"compilerPath": "E:/embedded_dev_tools/xpack-arm-none-eabi-gcc-13.3.1-1.1/bin/arm-none-eabi-gcc.exe","cStandard": "gnu17",   // 设置使用的C标准"cppStandard": "gnu++17", // 设置使用的C++标准"intelliSenseMode": "gcc-arm", // 设置编译器类型,解决编辑器中提示无法识别例如__attribute__((weak))等gcc编译器功能选项"configurationProvider": "ms-vscode.cmake-tools"}],"version": 4
}

tasks.json:

{//快捷键ctrl+shift+B调出各个task命令"tasks": [{"type": "cmake","label": "CMake build","command": "build","targets": ["${workspaceRootFolderName}.elf"],"group": "build","problemMatcher": ["$gcc"]},{"type": "cmake","label": "CMake cleanRebuild","command": "cleanRebuild","targets": ["${workspaceRootFolderName}.elf"],"group": "build","problemMatcher": ["$gcc"]},{"type": "cmake","label": "CMake clean","command": "clean","problemMatcher": ["$gcc"]},{"type": "shell","label": "flash with CMSIS-DAP-Link","command": "openocd","args": ["-f","interface/cmsis-dap.cfg","-f","target/stm32f1x.cfg","-c","program build/${workspaceRootFolderName}.elf verify reset exit"],"problemMatcher": ["$gcc"],"group": "build"},{"type": "shell","label": "flash with ST-Link","command": "openocd","args": ["-f","interface/stlink.cfg","-f","target/stm32f1x.cfg","-c","program build/${workspaceRootFolderName}.elf verify reset exit"],"problemMatcher": ["$gcc"],"group": "build"},{"type": "shell","label": "flash with J-Link","command": "openocd","args": ["-f","interface/jlink-swd.cfg","-f","target/stm32f1x.cfg","-c","program build/${workspaceRootFolderName}.elf verify reset exit"],"problemMatcher": ["$gcc"],"group": "build"}],"version": "2.0.0"
}

launch.json:

{// 使用 IntelliSense 了解相关属性。// 悬停以查看现有属性的描述。// 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387"version": "0.2.0","configurations": [{"name": "Debug with CMSIS-DAP-Link","cwd": "${workspaceRoot}","executable": "./build/${workspaceRootFolderName}.elf","request": "launch","type": "cortex-debug","servertype": "openocd","device": "STM32F103VET6",// "openOCDLaunchCommands": [//     "adapter speed 10000"// ],"configFiles": ["interface/cmsis-dap.cfg", // D:/Software/arm_riscv_develop_tools/openocd/openocd/scripts/interface"target/stm32f1x.cfg" // D:/Software/arm_riscv_develop_tools/openocd/openocd/scripts/target],"svdFile": "./STM32F103.svd", //选择寄存器文件"liveWatch": {"enabled": true,"samplesPerSecond": 4},"searchDir": [],"runToEntryPoint": "main","showDevDebugOutput": "none","preLaunchTask": "flash with CMSIS-DAP-Link"},{"name": "Debug with ST-Link","cwd": "${workspaceRoot}","executable": "./build/${workspaceRootFolderName}.elf","request": "launch","type": "cortex-debug","servertype": "openocd","device": "STM32F103VET6",// "openOCDLaunchCommands": [//     "adapter speed 10000"// ],"configFiles": ["interface/stlink.cfg", // D:/Software/arm_riscv_develop_tools/openocd/openocd/scripts/interface"target/stm32f1x.cfg" // D:/Software/arm_riscv_develop_tools/openocd/openocd/scripts/target],"svdFile": "./STM32F103.svd", //选择寄存器文件"liveWatch": {"enabled": true,"samplesPerSecond": 4},"searchDir": [],"runToEntryPoint": "main","showDevDebugOutput": "none","preLaunchTask": "flash with ST-Link"},{"name": "Debug with J-Link","cwd": "${workspaceRoot}","executable": "./build/${workspaceRootFolderName}.elf","request": "launch","type": "cortex-debug","servertype": "openocd","device": "STM32F103VET6",// "openOCDLaunchCommands": [//     "adapter speed 10000"// ],"configFiles": ["interface/jlink-swd.cfg", // D:/Software/arm_riscv_develop_tools/openocd/openocd/scripts/interface"target/stm32f1x.cfg" // D:/Software/arm_riscv_develop_tools/openocd/openocd/scripts/target],"svdFile": "./STM32F103.svd", //选择寄存器文件"liveWatch": {"enabled": true,"samplesPerSecond": 4},"searchDir": [],"runToEntryPoint": "main","showDevDebugOutput": "none","preLaunchTask": "flash with J-Link"}]
}

三、CMakeLists.txt——构建文件

CMakeLists.txt:

#THIS FILE IS AUTO GENERATED FROM THE TEMPLATE! DO NOT CHANGE!
set(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_SYSTEM_VERSION 1)
# cmake最低版本需求
cmake_minimum_required(VERSION 3.20)# 设置交叉编译器:specify cross compilers and tools
# 当编译工具链路径被加到环境变量中,可以直接写编译工具的名称;若未加入环境变量,此处应写对应交叉编译工具链的绝对路径。
set(CMAKE_C_COMPILER arm-none-eabi-gcc)
set(CMAKE_CXX_COMPILER arm-none-eabi-g++)
set(CMAKE_ASM_COMPILER arm-none-eabi-gcc)
set(CMAKE_AR arm-none-eabi-ar)
set(CMAKE_OBJCOPY arm-none-eabi-objcopy)
set(CMAKE_OBJDUMP arm-none-eabi-objdump)
set(CMAKE_SIZE arm-none-eabi-size)
set(CMAKE_READELF arm-none-eabi-readelf)
set(CMAKE_NM arm-none-eabi-nm)
# 链接的类型设置为STATIC, 以便嵌入式ARM-GNU通过CMake的"编译器检查"
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)# 设置CMake生成器:指定生成目标文件的构建工具
set(CMAKE_GENERATOR "Unix Makefiles")# project : 定义工程名称,并可以指定工程可支持的语言,语法格式为 project(项目域名 语言)
# .HEX  .bin  .elf  .map的文件名设置
project(Led_Toggle  C CXX ASM)
# C/C++语言标准版本配置
set(CMAKE_C_STANDARD 17)
set(CMAKE_CXX_STANDARD 17)#Uncomment for hardware floating point
#add_compile_definitions(ARM_MATH_CM4;ARM_MATH_MATRIX_CHECK;ARM_MATH_ROUNDING)
#add_compile_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16)
#add_link_options(-mfloat-abi=hard -mfpu=fpv4-sp-d16)#Uncomment for software floating point
#add_compile_options(-mfloat-abi=soft)#编译选项定义
#   对于 cortex-m0 / cortex-m0+ / cortex-m1
#   +---------------------------------------------------+
#   | -mthumb -mcpu=cortex-m0/cortex-m0+/cortex-m1 或 -mthumb -march=armv6-m |
#   +---------------------------------------------------+#   对于 cortex-m3
#   +---------------------------------------------------+
#   | -mthumb -mcpu=cortex-m3 或 -mthumb -march=armv7-m |
#   +---------------------------------------------------+#   对于 cortex-m4
#   +---------------------------------------------------+
#   | -mthumb -mcpu=cortex-m4 或 -mthumb -march=armv7-m|
#   +---------------------------------------------------+#   对于 cortex-m7
#   +---------------------------------------------------+
#   | -mthumb -mcpu=cortex-m7 或 -mthumb -march=armv7-m |
#   +---------------------------------------------------+# -mcpu=cortex-m3 告诉编译器为 ARM Cortex-M3 处理器生成代码
# -mthumb 启用 Thumb 指令集,Thumb 指令集是一种 16 位指令集
# -march=armv7-m 指定目标架构,ARMv7-M 是 Cortex-M3 处理器使用的架构
set(MCU_FLAGS -mcpu=cortex-m3 -mthumb -mthumb-interwork)    #   编译选项定义修改处#-fdata-sections用于将每个符号创建为一个sections,其中每个sections名与data名保持一致。
#-ffunction-sections用于将每个函数创建为一个sections,其中每个sections名与function名保持一致。
#用于代码的分割和裁剪,会将每一个函数都拆分成.text(Code+RO-data)段、.data(RW-data)段、.bss(ZI-data)段,这部分和对象文件的链接有关。如果没有这两个参数,编译器就会按文件分段而不是按照函数分段。
#加上这两个参数,配合链接器可以#去除代码中无用的部分,减少最终可执行文件的大小。
#-fno-common用于未初始化的全局变量当成强符号,重复定义就会报错。
#开启-fmessage-length=0会让编译器展示所有的消息而不会限制错误和警告输出的长度
set(OPTIMIZE_COMPILE_FLAGS -ffunction-sections -fdata-sections -fno-common -fmessage-length=0)
# 针对所有编译器,开启编译警告 (包括C、C++编译器),-Wall可开启所有警告;-Werror将所有警告视为error
# add_compile_options("-Wall -Werror")
add_compile_options(${MCU_FLAGS})
add_compile_options(${OPTIMIZE_COMPILE_FLAGS})# /*
# 编译等级选项:优化等级
# -O0:无任何优化,关闭所有优化选项
# -O、-O1:1级优化,
# -O2: 2级优化,
# -Os: 2.5级优化,-Os启用所有通常不会增加代码大小的-O2优化。 它还执行旨在减少代码大小的进一步优化。
# -O3: 最高级优化。
# -Og:优化调试体验。 -Og启用不会干扰调试的优化。 它是标准编辑 - 编译 - 调试周期可以选择的优化级别,提供合理的优化级别,同时保持快速编译和良好的调试体验。
# -Ofast:无视严格的标准合规性。 -Ofast启用所有-O3优化。 它还打开并非对所有符合标准的程序有效的优化。
# */#设置代码调试等级
set(CMAKE_BUILD_TYPE "Debug")
#   +---------------+---------------+--------------+--------------+----------+
#   |               |               | optimization | assert works | stripped |
#   +---------------+---------------+--------------+--------------+----------|
#   |               |     None      |              |              |          |
#   |    -g         |     Debug     |     no       |     yes      |    no    |
#   |-O3 -DNDEBUG   |    Release    |    full      |      no      |   yes    |
#   |-O2 -g -DNDEBUG| RelWithDebInfo|    good      |      no      |    no    |
#   |-Os -DNDEBUG   |   MinSizeRel  |    size      |      no      |   yes    |
#   +---------------+---------------+--------------+--------------+----------+
# Release 进行优化,提高速度 -排除调试信息
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release")message(VERBOSE "Maximum optimization for speed")add_compile_options(-Ofast)
# RelWithDebInfo 进行优化,提高速度 -包含调试信息
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo")message(VERBOSE "Maximum optimization for speed, debug info included")add_compile_options(-Ofast -g)
# MinSizeRel 优化二进制大小 -排除调试信息
elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "MinSizeRel")message(VERBOSE "Maximum optimization for size")add_compile_options(-Os)
# Debug 禁用优化 -包含调试信息
else ()message(VERBOSE "Minimal optimization, debug info included")add_compile_options(-Og -g)
endif ()#添加C文件编译宏定义
add_definitions(-DUSE_HAL_DRIVER-DSTM32F103xE-DUSE_STDPERIPH_DRIVER-DSTM32F10X_HD)
# add_definitions(-DUSE_STDPERIPH_DRIVER -DSTM32F10X_HD)#添加头文件路径,即.h文件
include_directories(./STM32F10x_FWLib/inc./SYSTEM/delay./SYSTEM/sys./SYSTEM/usart./HARDWARE/inc./USER/inc./CORE/inc./CMSIS/inc)#   这三个变量指代的内容是一致的,指的是工程编译产生的目录
#   +------------------+--------------------+--------------------------+
#   | CMAKE_BINARY_DIR | PROJECT_BINARY_DIR | <projectname>_BINARY_DIR |
#   +------------------+--------------------+--------------------------+#   这三个变量指代的内容是一致的,指的是工程顶级目录
#   +------------------+--------------------+--------------------------+
#   | CMAKE_SOURCE_DIR | PROJECT_SOURCE_DIR | <projectname>_SOURCE_DIR |
#   +------------------+--------------------+--------------------------+#添加汇编启动文件路径,startup文件是STM32CubeMX生成的(需要gcc版本,不要使用MDK版本)
ENABLE_LANGUAGE(ASM) #为了让cmake识别启动文件
set(SRC_STARTUP "${CMAKE_SOURCE_DIR}/startup_s/startup_stm32f103xe.s")#添加源文件路径,即.c文件
#file语法,前一个参数是固定的GLOB_RECURSE, 后面一个参数自行定义
file(GLOB_RECURSE SOURCES./STM32F10x_FWLib/src/*.c./USER/src/*.c./CMSIS/src/*.c./CORE/src/*.c./SYSTEM/delay/*.c./SYSTEM/sys/*.c./SYSTEM/usart/*.c./HARDWARE/src/*.c)# -Wl,--gc-sections 链接使用的分段方式,需要配合C文件/汇编生成obj的时候同样选型分段方式,
# 好处是链接的时候源文件中的未使用变量和未调用函数将不会被链接到elf文件中,最终可执行文件elf会很精简。
# -no-warn-rwx-segments:消除 LOAD segment with RWX permissions 警告
# -flto, 链接时优化,会减少程序体积,同时也会略微降低性能(当测试coremark时)
# -specs=nano.specs选择链接精简C库newlib-nano,而非标准C库glibc或newlib。
# -specs=nosys.specs禁止链接任何系统库(如glibc或newlib)。
# -u_printf_float显式启用浮点数打印 -u_scanf_float显式启用浮点数输入
set(OPTIMIZE_LD_FLAGS -Wl,--gc-sections,--no-warn-rwx-segments -flto -specs=nano.specs -specs=nosys.specs -u_printf_float -u_scanf_float) #-u_printf_float -u _scanf_float#添加.ld链接脚本路径
# -T$(LDSCRIPT)依赖的可执行文件链接脚本
set(LINKER_SCRIPT "${CMAKE_SOURCE_DIR}/link_script/STM32F103VETx_FLASH.ld")#-cref则生成交叉引用表方便查找未定义的符号引用(比如编译时出现的undefined reference)
#--print-memory-usage选项提供链接器文件中定义的每个内存区域使用的内存的详细信息
# -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref 生成map文件
set(MAP_FLAGS -Wl,--print-memory-usage,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map,--cref)#链接选项配置
add_link_options(${MCU_FLAGS})
# add_link_options(-Wl,--no-warn-rwx-segments,--print-memory-usage,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map)
# add_link_options(-specs=nano.specs -specs=nosys.specs -u _printf_float)   # -u _scanf_float
add_link_options(${OPTIMIZE_LD_FLAGS})
add_link_options(-T ${LINKER_SCRIPT})
add_link_options(${MAP_FLAGS})#根据源文件、汇编启动文件、链接脚本 生成 .elf可执行文件
add_executable(${PROJECT_NAME}.elf ${SRC_STARTUP} ${SOURCES} ${LINKER_SCRIPT})set(ELF_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.elf)
set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex)
set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin)# Print executable size
add_custom_command(TARGET "${PROJECT_NAME}.elf" POST_BUILDCOMMAND ${CMAKE_SIZE} ${PROJECT_NAME}.elf)
# Create hex & bin file
add_custom_command(TARGET "${PROJECT_NAME}.elf" POST_BUILDCOMMAND ${CMAKE_OBJCOPY} -Oihex $<TARGET_FILE:${PROJECT_NAME}.elf> ${HEX_FILE}COMMAND ${CMAKE_OBJCOPY} -Obinary $<TARGET_FILE:${PROJECT_NAME}.elf> ${BIN_FILE}COMMENT "Building ${HEX_FILE}
Building ${BIN_FILE}")

CMakeLists.txt文件及注释的参考链接如下:
1)使用VScode开发STM32:基于CMake(包含标准库和HAL库工程)
2)VSCode 和 CMake 搭建嵌入式开发环境
3) 在Windows上使用VS Code搭建开发环境-基于STM32F103C8T6
4)cmake:设置编译选项
5)CMake进阶(一)设置编译选项
6)跨平台编译工具-CMake的语法特性与常用变量
7)【gcc】gcc优化等级 -O1 -O2 -O3 -Os -Ofast -Og|gcc关闭优化
8)arm-none-eabi-gcc编译、链接选项详解
9)gcc for arm 工具链使用(一)
10)arm gcc编译选项
11)【ARMv8M Cortex-M33 系列 3.1 – RT-Thread renesas/ra4m2-eco 移植编译篇 nosys.specs 介绍】
12)GCC编译器的常用参数及用法,你都清楚吗?
13)用CMake提升STM32开发效率:完整配置与构建流程(一)

四、tips和遗留问题

📚① 默认情况下,CMake使用本地编译器,如gcc,而嵌入式开发使用的是交叉编译器,如arm-none-eabi-gcc。CMake无法知道该使用哪种编译器,因此需要明确地告知CMake。在VSCode中,CMake选择配置本地的arm-gcc或gcc工具链的方法步骤如下图所示,
在这里插入图片描述
同时修改c_cpp_properties.json"compilerPath"处为arm-none-eabi-gcc.exe的绝对路径,如下图所示,
在这里插入图片描述

📚② 如果读者将上述的CMakeLists.txt文件移植到自己的标准库 / HAL库工程后,需要重新生成CMake和当前项目相关的配置,否则会报错。参考方法的截图如下,
在这里插入图片描述
📚③ 设置CMake构建生成器
查看CMake在操作系统中的默认构建生成器:打开cmd→输入cmake -G→下拉观察到有*符号在前的选项,是默认选择的CMake构建生成器,如下图所示:笔者的Windows操作系统默认选择NMake Makefiles
在这里插入图片描述

设置CMake构建生成器:

  • 在Windows操作系统中:按下键盘的开始菜单键→直接打出“高级”→查看高级系统设置→设置环境变量→在用户变量区新建环境变量,设置变量名为CMAKE_GENERATOR和变量值为Unix Makefiles,之后一直点击确定即可。
    NOTE:Windows操作系统的CMake构建生成器可选择不设置环境变量,这里只是作个拓展说明。
    在这里插入图片描述
    再次打开cmd,输入cmake -G,可以看到CMake在操作系统中的默认构建生成器已被修改为Unix Makefiles,如下图所示。
    在这里插入图片描述

  • 在VSCode中:依次打开VSCode左侧的CMake Tools→项目大纲右侧的【更多操作】→编辑CMake缓存(UI)→进入到CMake本地构建树→找到CMAKE_GENERATOR,可以看到VSCode中的CMake默认调用了Unix Makefiles笔者目前修改仍然不生效,待解决
    INFO:CMake缓存(UI)中有很多常见的CMake命令,各位读者可自行研究。
    在这里插入图片描述
    或者在CMakeLists.txt中用脚本命令设置,如下图所示:笔者目前修改仍然不生效,待解决
    在这里插入图片描述

📚④ /build构建目录
GNU/Linux上,CMake默认生成Unix Makefile来构建项目:

  • CMakeFiles:包含临时文件的目录,CMake用于检测操作系统、编译器等。此外,根据所选的生成器,它还包含特定的文件。
  • cmake_install.cmake:处理安装规则的CMake脚本,在项目安装时使用。
  • CMakeCache.txt:如文件名所示,CMake缓存。CMake在重新运行配置时使用这个文件
  • Makefile: make将运行指令来构建项目。(如果选择ninja构建生成器,则该文件为build.ninja和rules.ninja:包含Ninja的所有的构建语句和构建规则)

📚⑤ 显式启用 “浮点数输入” 的问题(已解决)

arm-none-eabi-gcc工具链发布时自带有2个基于newlib的预构建C库:一个是标准的newlib,另一个是newlib-nano(优化了代码大小)。
要使用newlib-nano,用户应该提供额外的gcc编译和链接时选项:-specs=nano.specs。
在编译时,如果-specs=nano.specs被传递给编译器,那么一个专门为newlib-nano配置的“newlib.h”头文件会被使用。
nano.specs还能处理另外两个gcc库:libstdc++_nano.a和libsupc++_nano.a,它们同样针对代码大小进行了优化。
newlib-nano相比newlib,不仅仅是库的名字上的区别。浮点数的格式化input/output被实现为弱符号(隐式)。
如果要使用%f,则必须通过显式指定"-u"命令选项来引入该符号。

#显式指定"-u"命令选项-u _scanf_float-u _printf_float

参考链接:
1)Newlib 与 Newlib-Nano区别
2) [开发工具]为什么gcc编译出来的程序大小和Keil差别这么大
3)Shrink Your MCU code size with GCC ARM Embedded 4.7
4)嵌入式GCC库: newlib与nanolib区别
5)CoIDE 1.6.2下使用ARM GCC 4.7 Newlib-nano printf 重定向到UART

CMakeLists.txt的可选链接选项配置中,如果仿照Makefile中一样的-u _printf_float -u _scanf_float显式启用,即如下图所示,则会发生报错:无法找到_scanf_float。

在这里插入图片描述
因此在CMakeLists.txt中,笔者去掉-u后面的空格,修改显式启用为-u_printf_float -u_scanf_float,如下图所示,即可去除报错并能正常打印浮点数。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/502747.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【数据结构】链表(2):双向链表和双向循环链表

双向链表&#xff08;Doubly Linked List&#xff09; 定义&#xff1a; 每个节点包含三个部分&#xff1a; 数据域。前驱指针域&#xff08;指向前一个节点&#xff09;。后继指针域&#xff08;指向下一个节点&#xff09;。 支持从任意节点向前或向后遍历。 #define dat…

RK3588+麒麟国产系统+FPGA+AI在电力和轨道交通视觉与采集系统的应用

工业视觉识别系统厂家提供的功能主要包括&#xff1a; 这些厂家通过先进的视觉识别技术&#xff0c;实现图像的采集、处理与分析。系统能够自动化地完成质量检测、物料分拣、设备监控等任务&#xff0c;显著提升生产效率和产品质量。同时&#xff0c;系统具备高度的灵活性和可扩…

3 抢红包系统

我们还是按照我们分析问题的方法论开展 一 场景分析 我们分析的是集体活动的抢红包&#xff0c;比如春晚&#xff0c;大型活动红包&#xff0c;需要在网页操作的抢红包 抢红包的问题也是多个人抢资源的问题&#xff0c;可以和秒杀进行比对。但是也有很多不同的地方。 用户打…

数据库中的并发控制

并发操作带来的数据不一致性 1、并发控制:为了保证事务的隔离性和一致性&#xff0c;数据库管理系统需要对并发操作进行正确调度 并发控制的主要技术有:封锁、时间戳、乐观控制法、多版本并发控制等 并发操作带来的数据不一致性: ① 丟失修改:两个事务 T1 和 T2 读入同一数据…

ArcGIS Server 10.2授权文件过期处理

新的一年&#xff0c;arcgis server授权过期了&#xff0c;服务发不不了。查看ecp授权文件&#xff0c;原来的授权日期就到2024.12.31日。好吧&#xff0c;这里直接给出处理方法。 ArcGIS 10.2安装时&#xff0c;有的破解文件中会有含一个这样的注册程序&#xff0c;没有的话&…

学英语学压测:02jmeter组件-测试计划和线程组ramp-up参数的作用

&#x1f4e2;&#x1f4e2;&#x1f4e2;&#xff1a;先看关键单词&#xff0c;再看英文&#xff0c;最后看中文总结&#xff0c;再回头看一遍英文原文&#xff0c;效果更佳&#xff01;&#xff01; 关键词 Functional Testing功能测试[ˈfʌŋkʃənəl ˈtɛstɪŋ]Sample样…

MCGS学习记录

软件包 用户窗口 主窗口 元件&#xff1a;工具箱->输入框上面 数据对象 在工作台的实时数据库可以新增数据对象 理解为中间变量&#xff0c;控件改变其值&#xff0c;控件监测其值做出变化 基本属性 设定变量名和初始值 指针化&#xff1f; 变化时自动保存初始值&#x…

【网络协议】IPv4 地址分配 - 第一部分

文章目录 十进制与二进制网络如何被寻址地址类型网络地址广播地址主机地址 如何确定网络和主机部分的位数&#xff1f;网络中的主机数量与前缀号的关系计算每个前缀的主机数量公式 子网掩码二进制与操作&#xff08;Binary ANDing&#xff09;与操作&#xff08;AND Operation&…

数据挖掘——集成学习

数据挖掘——集成学习 集成学习Bagging&#xff1a;有放回采样随机森林 BoostingStacking 集成学习 集成学习&#xff08;Ensemble learning&#xff09;方法通过组合多种学习算法来获得比单独使用任何一种算法更好的预测性能。 动机是为了提高但分类器的性能 Bagging&…

ansible-性能优化

一. 简述&#xff1a; 搞过运维自动化工具的人&#xff0c;肯定会发现很多运维伙伴们经常用saltstack和ansible做比较&#xff0c;单从执行效率上来说&#xff0c;ansible确实比不上saltstack(ansible使用的是ssh,salt使用的是zeromq消息队列[暂没深入了解])&#xff0c;但其实…

NLP CH10 问答系统复习

1. 专家系统 特点 问题聚焦&#xff1a;限定在特定领域。数据结构化&#xff1a;使用结构化的领域知识。数据库支持&#xff1a;后台有一个数据库&#xff0c;保存系统可提供的各种数据。查询机制&#xff1a;用户提问时&#xff0c;系统将问题转换为 SQL 查询语句&#xff0…

vite6+vue3+ts+prettier+eslint9配置前端项目(后台管理系统、移动端H5项目通用配置)

很多小伙伴苦于无法搭建一个规范的前端项目&#xff0c;导致后续开发不规范&#xff0c;今天给大家带来一个基于Vite6TypeScriptVue3ESlint9Prettier的搭建教程。 目录 一、基础配置1、初始化项目2、代码质量风格的统一2.1、配置prettier2.2、配置eslint2.3、配置typescript 3、…

【2025年最新】OpenWrt 更换国内源的指南(图形界面版)

在上一篇文章中我们讲解了如何使用命令行更换国内源&#xff0c;如果你没有终端工具&#xff0c;或者不喜欢命令行&#xff0c;那么图形界面方式将会是更简单有效的方式。 命令行版本&#xff1a;【2025年最新】OpenWrt 更换国内源的指南(命令行)-CSDN博客 为什么选择通过图形…

uni-app:实现普通选择器,时间选择器,日期选择器,多列选择器

效果 选择前效果 1、时间选择器 2、日期选择器 3、普通选择器 4、多列选择器 选择后效果 代码 <template><!-- 时间选择器 --><view class"line"><view classitem1><view classleft>时间</view><view class"right&quo…

NVIDIA DLI课程《NVIDIA NIM入门》——学习笔记

先看老师给的资料&#xff1a; NVIDIA NIM是 NVIDIA AI Enterprise 的一部分&#xff0c;是一套易于使用的预构建容器工具&#xff0c;目的是帮助企业客户在云、数据中心和工作站上安全、可靠地部署高性能的 AI 模型推理。这些预构建的容器支持从开源社区模型到 NVIDIA AI 基础…

深度学习中的步数指的是什么

Lora微调的截图如下: 在深度学习中,步数(steps) 是指模型参数更新的次数。每次参数更新通常对应一个或多个批次的梯度计算和优化器更新。以下是计算总步数的方法以及步数的具体含义: 1. 步数的计算公式 总步数(Total Optimization Steps)可以通过以下公式计算: [ \te…

【可实战】测试用例组成、用例设计方法、用例编写步骤、测试用例粒度、用例评审(包含常见面试题)

一、测试用例组成 &#xff08;一&#xff09;测试用例的组成 用例编号&#xff0c;模块&#xff0c;测试点&#xff08;测试标题&#xff09;&#xff0c;优先级&#xff0c;前提条件&#xff0c;测试步骤&#xff0c;期望结构&#xff0c;实际结果并不是每一项都必须&#…

Redis两种主要的持久化方式是什么?

Redis支持两种主要的持久化方式&#xff0c;它们分别是RDB&#xff08;Redis Database Snapshotting&#xff09;和AOF&#xff08;Append Only File&#xff09;。以下是这两种持久化方式的详细介绍&#xff1a; 一、RDB&#xff08;Redis Database Snapshotting&#xff09; …

【强化学习】演员评论家Actor-Critic算法(万字长文、附代码)

&#x1f4e2;本篇文章是博主强化学习&#xff08;RL&#xff09;领域学习时&#xff0c;用于个人学习、研究或者欣赏使用&#xff0c;并基于博主对相关等领域的一些理解而记录的学习摘录和笔记&#xff0c;若有不当和侵权之处&#xff0c;指出后将会立即改正&#xff0c;还望谅…

《新概念模拟电路》-电流源电路

电流源电路 本系列文章主要学习《新概念模拟电路》中的知识点。在工作过程中&#xff0c;碰到一些问题&#xff0c;于是又翻阅了模电这本书。我翻阅的是ADI出版的&#xff0c;西安交通大学电工中心杨建国老师编写的模电书。 本文主要是基于前文《新概念模拟电路》-三极管的基础…