赞
踩
本教程使用VScode作为代码编辑工具、Cmake作为构建系统生成器、Make进行构建系统、使用arm-none-eabi-gcc进行交叉编译、使用OpenOCD作为代码下载与调试工具,最终搭建出适用于ARM架构系列芯片的开发环境。此教程以STM32F103ZET6芯片为例。
经验证,可满足基本基本项目需求。但我发现arm-none-eabi-gcc编译器相比于keil的AC5、AC6编译器,所编译的hex文件比较大,Flash占用较高,为了兼顾keil开发项目,也为了能够与其他人的项目兼容,这里的keil与VScode的项目文件互不干扰,满足兼容性需求。
本文涉及的软件安装包、工程模板已放在我的百度网盘中,需要自取(本教程使用的是标准库,HAL库与其基本相同,具体差异请参考分享的文件自行对照)。
链接:https://pan.baidu.com/s/1N4DI9GpaRnCr-4J0uCTTHw?pwd=wqfz
提取码:wqfz
--来自百度网盘超级会员V4的分享
已默认电脑上存在VScode,这里不讲述Vscode的安装。
涉及软件的安装配置:
下载地址:
https://cmake.org/download/
选择适合自己电脑的最新版本进行下载并安装,我这里选择cmake-3.29.2-windows-x86_64.msi
,如下图:
我们需要将cmake的可执行文件的文件夹路径添加到环境变量,方便使用命令调用cmake,我的路径为:
D:\RJ\CMake\bin
将以上目录添加到系统环境变量中去。
在终端输入以下命令,验证是否安装成功。
cmake
成功则将显示以下内容:
下载地址:
https://developer.arm.com/downloads/-/gnu-rm
选择适合自己电脑的最新版本进行下载并安装,我这里选择gcc-arm-none-eabi-10.3-2021.10-win32.exe
,如下图:
我们需要将arm-gcc的可执行文件的文件夹路径添加到环境变量,方便使用命令调用arm-gcc,我的路径为:
D:\RJ\ARM-GCC\10 2021.10\bin
将以上目录添加到系统环境变量中去。
在终端输入以下命令,验证是否安装成功。
arm-none-eabi-gcc
成功则将显示以下内容:
下载地址:
https://gnutoolchains.com/arm-eabi/openocd/
选择适合自己电脑的最新版本进行下载,直接下载的是压缩包文件,解压后可直接使用,我这里选择openocd-20231002.7z
,如下图:
我们需要将OpenOCD的可执行文件的文件夹路径添加到环境变量,方便使用命令调用OpenOCD,我的路径为:
D:\RJ\OpenOCD-20231002-0.12.0\bin
将以上目录添加到系统环境变量中去。
在终端输入以下命令,验证是否安装成功。
openOCD
成功则将显示以下内容:
下载地址:
https://sourceforge.net/projects/mingw-w64/files/
选择适合自己电脑的最新版本进行下载,直接下载的是压缩包文件,解压后的mingw64可直接使用,我这里选择MinGW-W64GCC-8.1.0下的x86_64-posix-sjlj
,如下图:
我们需要将make的可执行文件的文件夹路径添加到环境变量,方便使用命令调用make,我的路径为:
D:\RJ\mingw64\bin
将以上目录添加到系统环境变量中去。
在终端输入以下命令,验证是否安装成功(由于Window下make执行程序为mingw32-make.exe,我这里将其复制保存同目录下为副本,并改名为make.exe)。
make
成功则将显示以下内容:
要安装的插件如下:
以下是我的工程框架
与ARM-MDK工程不同,我们配置工程还需要格外的文件,分别是CMakeLists.txt、startup_stm32f10x_hd.s、STM32F103ZETx_FLASH.ld。
CMake根据CMakeLists.txt进行构建,从而创建出Makefile,再由make根据 Makefile 定义的规则调用 GCC 执行编译工作,最终生成可执行的.elf或者.hex文件。以下是CMakeLists.txt的模板,需要更改的部分我已经标明。
#THIS FILE IS AUTO GENERATED FROM THE TEMPLATE! DO NOT CHANGE! set(CMAKE_SYSTEM_NAME Generic) set(CMAKE_SYSTEM_VERSION 1) 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(SIZE arm-none-eabi-size) set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # project settings project(Project C CXX ASM) set(CMAKE_CXX_STANDARD 17) set(CMAKE_C_STANDARD 11) #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) add_compile_options(-mcpu=cortex-m3 -mthumb -mthumb-interwork) add_compile_options(-ffunction-sections -fdata-sections -fno-common -fmessage-length=0) # uncomment to mitigate c++17 absolute addresses warnings #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-register") if ("${CMAKE_BUILD_TYPE}" STREQUAL "Release") message(VERBOSE "Maximum optimization for speed") add_compile_options(-Ofast) elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "RelWithDebInfo") message(VERBOSE "Maximum optimization for speed, debug info included") add_compile_options(-Ofast -g) elseif ("${CMAKE_BUILD_TYPE}" STREQUAL "MinSizeRel") message(VERBOSE "Maximum optimization for size") add_compile_options(-Os) else () message(VERBOSE "Minimal optimization, debug info included") add_compile_options(-Og -g) endif () #添加宏定义 add_definitions(-DUSE_HAL_DRIVER -DSTM32F103xB -DUSE_STDPERIPH_DRIVER -DSTM32F10X_HD) #添加头文件路径,即.h文件 include_directories(./STM32F10x_FWLib/inc ./User ./Project/Code-Cmake) #添加源文件路径,即.c或者.s文件 file(GLOB_RECURSE SOURCES ./STM32F10x_FWLib/src/*.c ./User/*.c ./Project/Code-Cmake/*.*) #添加你的STM32F103ZETx_FLASH.ld的连接脚本路径 set(LINKER_SCRIPT ${CMAKE_SOURCE_DIR}/Project/Code-Cmake/STM32F103ZETx_FLASH.ld) add_link_options(-Wl,-gc-sections,--print-memory-usage,-Map=${PROJECT_BINARY_DIR}/${PROJECT_NAME}.map) #选择cortex-m3内核 add_link_options(-mcpu=cortex-m3 -mthumb -mthumb-interwork) add_link_options(-T ${LINKER_SCRIPT}) add_link_options(-specs=nano.specs -specs=nosys.specs -u _printf_float) add_executable(${PROJECT_NAME}.elf ${SOURCES} ${LINKER_SCRIPT}) set(HEX_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.hex) set(BIN_FILE ${PROJECT_BINARY_DIR}/${PROJECT_NAME}.bin) add_custom_command(TARGET ${PROJECT_NAME}.elf POST_BUILD COMMAND ${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}")
在我们创建ARM-MDK工程时,我们从官方的固件包中选择的是arm版本的启动文件,在这里我们要选择gcc版本的启动文件,即下图中的gcc_ride7。同时为了与ARM-MDK有所区分,我将该文件放在了/Project/Code-Cmake文件夹下。
STM32F103ZETx_FLASH.ld是一个链接脚本文件,它告诉编译器相关的编译后的可执行代码,内存变量,中断向量,链接在哪个存储区。获取方式主要有三种(请根据自己单片机型号选择):
以下是我的STM32F103ZETx_FLASH.ld:
/* ****************************************************************************** ** ** @file : LinkerScript.ld ** ** @author : Auto-generated by STM32CubeIDE ** ** @brief : Linker script for STM32F103ZETx Device from STM32F1 series ** 512Kbytes FLASH ** 64Kbytes RAM ** ** Set heap size, stack size and stack location according ** to application requirements. ** ** Set memory bank area and size if external memory is used ** ** Target : STMicroelectronics STM32 ** ** Distribution: The file is distributed as is, without any warranty ** of any kind. ** ****************************************************************************** ** @attention ** ** <h2><center>© Copyright (c) 2021 STMicroelectronics. ** All rights reserved.</center></h2> ** ** This software component is licensed by ST under BSD 3-Clause license, ** the "License"; You may not use this file except in compliance with the ** License. You may obtain a copy of the License at: ** opensource.org/licenses/BSD-3-Clause ** ****************************************************************************** */ /* Entry Point */ ENTRY(Reset_Handler) /* Highest address of the user mode stack */ _estack = ORIGIN(RAM) + LENGTH(RAM); /* end of "RAM" Ram type memory */ _Min_Heap_Size = 0x200 ; /* required amount of heap */ _Min_Stack_Size = 0x400 ; /* required amount of stack */ /* Memories definition */ MEMORY { RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K } /* Sections */ SECTIONS { /* The startup code into "FLASH" Rom type memory */ .isr_vector : { . = ALIGN(4); KEEP(*(.isr_vector)) /* Startup code */ . = ALIGN(4); } >FLASH /* The program code and other data into "FLASH" Rom type memory */ .text : { . = ALIGN(4); *(.text) /* .text sections (code) */ *(.text*) /* .text* sections (code) */ *(.glue_7) /* glue arm to thumb code */ *(.glue_7t) /* glue thumb to arm code */ *(.eh_frame) KEEP (*(.init)) KEEP (*(.fini)) . = ALIGN(4); _etext = .; /* define a global symbols at end of code */ } >FLASH /* Constant data into "FLASH" Rom type memory */ .rodata : { . = ALIGN(4); *(.rodata) /* .rodata sections (constants, strings, etc.) */ *(.rodata*) /* .rodata* sections (constants, strings, etc.) */ . = ALIGN(4); } >FLASH .ARM.extab : { . = ALIGN(4); *(.ARM.extab* .gnu.linkonce.armextab.*) . = ALIGN(4); } >FLASH .ARM : { . = ALIGN(4); __exidx_start = .; *(.ARM.exidx*) __exidx_end = .; . = ALIGN(4); } >FLASH .preinit_array : { . = ALIGN(4); PROVIDE_HIDDEN (__preinit_array_start = .); KEEP (*(.preinit_array*)) PROVIDE_HIDDEN (__preinit_array_end = .); . = ALIGN(4); } >FLASH .init_array : { . = ALIGN(4); PROVIDE_HIDDEN (__init_array_start = .); KEEP (*(SORT(.init_array.*))) KEEP (*(.init_array*)) PROVIDE_HIDDEN (__init_array_end = .); . = ALIGN(4); } >FLASH .fini_array : { . = ALIGN(4); PROVIDE_HIDDEN (__fini_array_start = .); KEEP (*(SORT(.fini_array.*))) KEEP (*(.fini_array*)) PROVIDE_HIDDEN (__fini_array_end = .); . = ALIGN(4); } >FLASH /* Used by the startup to initialize data */ _sidata = LOADADDR(.data); /* Initialized data sections into "RAM" Ram type memory */ .data : { . = ALIGN(4); _sdata = .; /* create a global symbol at data start */ *(.data) /* .data sections */ *(.data*) /* .data* sections */ *(.RamFunc) /* .RamFunc sections */ *(.RamFunc*) /* .RamFunc* sections */ . = ALIGN(4); _edata = .; /* define a global symbol at data end */ } >RAM AT> FLASH /* Uninitialized data section into "RAM" Ram type memory */ . = ALIGN(4); .bss : { /* This is used by the startup in order to initialize the .bss section */ _sbss = .; /* define a global symbol at bss start */ __bss_start__ = _sbss; *(.bss) *(.bss*) *(COMMON) . = ALIGN(4); _ebss = .; /* define a global symbol at bss end */ __bss_end__ = _ebss; } >RAM /* User_heap_stack section, used to check that there is enough "RAM" Ram type memory left */ ._user_heap_stack : { . = ALIGN(8); PROVIDE ( end = . ); PROVIDE ( _end = . ); . = . + _Min_Heap_Size; . = . + _Min_Stack_Size; . = ALIGN(8); } >RAM /* Remove information from the compiler libraries */ /DISCARD/ : { libc.a ( * ) libm.a ( * ) libgcc.a ( * ) } .ARM.attributes 0 : { *(.ARM.attributes) } }
由于gcc编译的问题,如果不更改core_cm3.c,可能出现以下报错:
我对此做出以下两处更改,并放在了/Project/Code-Cmake文件夹下,与MDK-ARM分开:
这是VScode配置文件的位置
将其C/C++模式更改为gcc-arm,注意将gcc路径替换为自己的路径
{ "configurations": [ { "name": "Win32", "includePath": [ "${workspaceFolder}/**" ], "defines": [ "_DEBUG", "UNICODE", "_UNICODE" ], "compilerPath": "D:\\RJ\\mingw64\\bin\\gcc.exe", "cStandard": "gnu17", "cppStandard": "gnu++14", "intelliSenseMode": "gcc-arm", "configurationProvider": "ms-vscode.cmake-tools" } ], "version": 4 }
2.4.1 添加并配置launch.json
这个文件是关于烧录与调试相关的,在此目录下你可以选择你的下载器型号、芯片型号。其中的stm32f103.svd可以在调试时查看看寄存器的值,请将以下路径改为自己工程的路径。
{ // 使用 IntelliSense 了解相关属性。 // 悬停以查看现有属性的描述。 // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "cwd": "${workspaceRoot}", "executable": "D:/GC/STM32F1/build/Project.elf", "name": "Debug with OpenOCD", "request": "launch", "type": "cortex-debug", "servertype": "openocd", "configFiles": [ "D:/RJ/OpenOCD-20231002-0.12.0/share/openocd/scripts/interface/stlink-v2.cfg", //在OpenOCD选择下载器 "D:/RJ/OpenOCD-20231002-0.12.0/share/openocd/scripts/target/stm32f1x.cfg" //在OpenOCD选择芯片 ], "svdFile": "D:/GC/STM32F1/stm32f103.svd", //选择寄存器文件 } ] }
如果我们配置完成后,用VScode打开CMakeLists.txt所在文件夹工程过后,Cmake tool会自动提示配置Cmake,点击配置后,会生成build文件夹,产生的Makefile及其他中间文件会存放在该目录。
点击VScode下方的配置按钮,选择gcc-arm
点击VScode下方的进行编译,生成目标文件
编译过程
在build文件夹下会生成目标文件
进入build文件夹下执行以下命令,其中将Project.hex替换为自己的目标文件,stlink-v2.cfg是选择下载器类型,stm32f1x.cfg是芯片型号
openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg -c "program Project.hex verify reset exit"
烧录成功
打开左侧的运行和调试,选择Debug with OpenOCD
点击运行,可进行断点调试,变量监测,寄存器查看等操作。
使用gcc编译时,我们一般需要告诉编译器这个变量是可变的,不然会造成内存覆盖,程序无法运行的情况,即voatile
关键词
四、参考链接
此文章参考以下文章,若描述不清,可查看下方文章
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。