VS Code + GCC 搭建 STM32 开发环境

使用GCC新建工程的好处是windows 与 linux 系统无需更改项目,都能进行编译

1. ARM-GCC 下载与安装

  1. 进入GNU Arm Embedded Toolchain Downloads ,下载gcc-arm-none-eabi-10-2020-q4-major-win32.exe

  2. 下载完毕安装后,将安装路径 D:\GNU Arm Embedded Toolchain\10 2020-q4-major\bin (根据你的安装安装路径) 添加到系统变量,打开命令行工具,输入命令 arm-none-eabi-g++.exe -v 出现如图版本号信息,表示arm-gcc安装成功

    Target: arm-none-eabi
    Configured with: /mnt/workspace/workspace/GCC-9-pipeline/jenkins-GCC-9-pipeline-100_20191030_1572397542/src/gcc/configure --…

    Thread model: single
    gcc version 9.2.1 20191025 (release) [ARM/arm-9-branch revision 277599] (GNU Tools for Arm Embedded Processors 9-2019-q4-major)
    PS C:\Users>

2. 安装mingw-make

  1. 下载mingw安装 Mingw;
  2. mingw访问较慢,可下载Dev C++软件,自带mingw,Dev c++下载;
  3. 下载安装完成后打开安装目录,进入MinGW64\bin,将mingw32-make.exe复制一份并重命名为make.exe;
  4. 将 DevC++ 安装目录下的MinGW64\bin,添加到系统变量,打开命令行输入make,出现下列提示表示安装成功。

    make: *** No targets specified and no makefile found. Stop.

3. 建立模板工程项目

  1. 新建项目文件夹Demo,创建src目录,
  2. 打开STM32F10x_StdPeriph_Lib_V3.5.0库,将Libraries文件夹复制到src目录,删除Libraries文件夹中的无用文件,保留core_cm3.c,core_cm3.h,stm32f10x.h文件,startup文件选择Libraries\CMSIS\CM3\DeviceSupport\ST\STM32F10x\startup\ gcc_ride7 里对应芯片的s文件,一定要gcc_ride7目录里的启动文件。
  3. 新建User目录,将STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Template目录下的stm32f10x_conf.h,stm32f10x_it.c,stm32f10x_it.h,system_stm32f10x.c复制到User目录,并新建main.c文件。
  4. 最终目录文件如下
    VS Code + GCC 搭建 STM32 开发环境_第1张图片

4. 建立Makefile

  1. 在项目文件夹Demo下,新建文件Makefile,(可使用stm32cube生成然后修改)
# 项目名称,编译生成的 hex和bin名称
TARGET = Demo

# 是否会进行调试
DEBUG = 1

# optimization    ## 选择优化等级,优化等级低->高,可参考Keil的设置,如果程序运行不理想,优化程序或降低优化等级
#OPT = -O0        ## 没有优化。
#OPT = -O1        ## 编译器试图减少代码大小和执行时间,而不执行任何花费大量编译时间的优化。
OPT = -Og         ## 参数 -Og 是在 -O1 的基础上,去掉了那些影响调试的优化告诉编译器,编译后的代码不要影响调试,但调试信息的生成还是靠 -g 参数的。
#OPT = -O2        ## 更加优化。GCC执行几乎所有支持的优化,不涉及空间速度权衡。此选项既增加编译时间,提高了生成代码的性能。
#OPT = -O3        ## 优化更多。
#OPT = -Os        ## 优化大小。启用所有优化,除了那些经常增加代码大小
#OPT = -Ofast     ## 不遵守严格的标准。使所有优化。它还支持并非对所有符合标准的程序都有效的优化。

# Build path      ## Build编译产生的文件存放目录 , Output生成hex与bin的存放位置
BUILD_DIR = Build
OUT_DIR = Output

# source                           ## 检索项目目录下的c文件的,注意C大小写
C_SOURCES := $(wildcard */*/*/*/*/*/*/*.c) \
	$(wildcard */*/*/*/*/*/*.c) \
	$(wildcard */*/*/*/*/*.c) \
	$(wildcard */*/*/*/*.c) \
	$(wildcard */*/*/*.c) \
	$(wildcard */*/*.c) \
	$(wildcard */*.c)


# ASM sources                      ## 检索项目目录下的s汇编文件的,注意s是小写
ASM_SOURCES  := $(wildcard */*/*/*/*/*/*/*.s) \
	$(wildcard */*/*/*/*/*/*.s) \
	$(wildcard */*/*/*/*/*.s) \
	$(wildcard */*/*/*/*.s) \
	$(wildcard */*/*/*.s) \
	$(wildcard */*/*.s) \
	$(wildcard */*.s)

# C includes                       ## 添加 h头文件的 Include路径,格式 -I + 路径,添加文件夹注意在此添加include
C_INCLUDES =  \
-Isrc\User \
-Isrc\Libraries\CMSIS\CoreSupport \
-Isrc\Libraries\CMSIS\DeviceSupport \
-Isrc\Libraries\STM32F10x_StdPeriph_Driver\inc \

# AS includes                     ## 添加 汇编的 Include路径,格式 -I + 路径,添加文件夹注意在此添加include
AS_INCLUDES =

# C defines                       ## 添加全局 Define ,std库参照stm32f10x.h,换芯片需更换 宏定义,格式 -D + dd
C_DEFS =  \
-DSTM32F10X_HD \
-DUSE_STDPERIPH_DRIVER \

# link script                    ## 添加 ld链接 文件,注意路径
LDSCRIPT = STM32F103ZETx_FLASH.ld

# cpu                             ## 参照 stm32cube
CPU = -mcpu=cortex-m3

# fpu
# NONE for Cortex-M0/M0+/M3

# float-abi

# mcu
MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)

# macros for gcc
# AS defines
AS_DEFS =

#######################################
# binaries
#######################################
PREFIX = arm-none-eabi-
# The gcc compiler bin path can be either defined in make command via GCC_PATH variable (> make GCC_PATH=xxx)
# either it can be added to the PATH environment variable.
ifdef GCC_PATH
CC = $(GCC_PATH)/$(PREFIX)gcc
AS = $(GCC_PATH)/$(PREFIX)gcc -x assembler-with-cpp
CP = $(GCC_PATH)/$(PREFIX)objcopy
SZ = $(GCC_PATH)/$(PREFIX)size
else
CC = $(PREFIX)gcc
AS = $(PREFIX)gcc -x assembler-with-cpp
CP = $(PREFIX)objcopy
SZ = $(PREFIX)size
endif
HEX = $(CP) -O ihex
BIN = $(CP) -O binary -S


# compile gcc flags
ASFLAGS = $(MCU) $(AS_DEFS) $(AS_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections

CFLAGS = $(MCU) $(C_DEFS) $(C_INCLUDES) $(OPT) -Wall -fdata-sections -ffunction-sections

ifeq ($(DEBUG), 1)
CFLAGS += -g -gdwarf-2
endif


# Generate dependency information
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"

# libraries
LIBS = -lc -lm -lnosys
LIBDIR =
LDFLAGS = $(MCU) -specs=nano.specs -T$(LDSCRIPT) $(LIBDIR) $(LIBS) -Wl,-Map=$(BUILD_DIR)/$(TARGET).map,--cref -Wl,--gc-sections

# default action: build all
all: $(BUILD_DIR)/$(TARGET).elf $(OUT_DIR)/$(TARGET).hex $(OUT_DIR)/$(TARGET).bin


#######################################
# build the application
#######################################
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
vpath %.s $(sort $(dir $(ASM_SOURCES)))

$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
	$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@

$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
	$(AS) -c $(CFLAGS) $< -o $@

$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
	$(CC) $(OBJECTS) $(LDFLAGS) -o $@
	$(SZ) $@

$(OUT_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(OUT_DIR)
	$(HEX) $< $@

$(OUT_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(OUT_DIR)
	$(BIN) $< $@

$(BUILD_DIR):
	mkdir $@

$(OUT_DIR):
	mkdir $@

#######################################
# clean up
#######################################
clean:
	-rm -fR $(BUILD_DIR)

#######################################
# dependencies
#######################################
-include $(wildcard $(BUILD_DIR)/*.d)

# *** EOF ***
  1. 在Demo目录建立链接文件 STM32F103ZETx_FLASH.ld (可更改文件名,需和Makefile中移植,可通过stm32cube生成)
/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = 0x20010000;    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 512K
}

/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

  /* The program code and other data goes into FLASH */
  .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 goes into FLASH */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH

  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
  .ARM : {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } >FLASH

  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH

  /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data :
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM AT> FLASH


  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _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 left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM



  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}



  1. 打开命令行,进入项目目录Demo,输入命令make,出现下列错误

     C:\416: Error: registers may not be the same -- `strexb r0,r0,[r1]'
     C:\436: Error: registers may not be the same -- `strexh r0,r0,[r1]'
    

    打开src\Libraries\CMSIS\CoreSupport\core_cm3.c文件,将 736行,753行 中的 “=r"修改为”=&r",如下

uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
   uint32_t result=0;

   __ASM volatile ("strexb %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
   return(result);
}

uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
   uint32_t result=0;

   __ASM volatile ("strexh %0, %2, [%1]" : "=&r" (result) : "r" (addr), "r" (value) );
   return(result);
}
  1. 重新运行make,出现下列信息表示编译成功
arm-none-eabi-size Build/Demo.elf
  	 text    data     bss     dec     hex filename
    948       8    1568    2524     9dc Build/Demo.elf
arm-none-eabi-objcopy -O ihex Build/Demo.elf Output/Demo.hex
arm-none-eabi-objcopy -O binary -S Build/Demo.elf Output/Demo.bin

5. 建立jlink下载脚本

  1. 安装jlink…
  2. 在Demo目录下新建文件 jlink_config , 其中 STM32F103ZE 为芯片,"./Output/Demo.hex" 为下载文件。
JTAG
JTAGConf -1 -1
speed 4000
device STM32F103ZE
r
h

loadfile "./Output/Demo.hex"
r
g
qc
  1. 新建文件 download.cmd,其中 “C:\Program Files (x86)\SEGGER\JLink_V620a\JLink.exe” 修改为你的jlink安装路径
"C:\Program Files (x86)\SEGGER\JLink_V620a\JLink.exe"  ".\jlink_config"
  1. 运行命令 ./download.cmd , 下载hex文件。

目录如下
VS Code + GCC 搭建 STM32 开发环境_第2张图片

你可能感兴趣的:(STM32,stm32,arm开发,linux)