# Embedded-GCC-Template **Repository Path**: End-ING/embedded-gcc-template ## Basic Information - **Project Name**: Embedded-GCC-Template - **Description**: Embedded-GCC-Template 第三方资源集合 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 1 - **Created**: 2023-11-10 - **Last Updated**: 2024-12-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: GCC, AT32, stm32, CW32, gd32 ## README ## Embedded-GCC-Template ### arm-none-eabi-gcc + makefile+openocd工程模板 ### Windows环境搭建参考 1. 参考教程 https://blog.csdn.net/weixin_42328389/article/details/119823834 2. 仓库收集 https://github.com/cjacker ### **一、本次环境搭建所用的软硬件** 1)Windows or Linux (本文以Windows为主,linux基本环境流程差不多,可能需要修改部分Makefile代码) 2)JLink、Daplink、Wch-Link烧录器 3)GNU Arm Embedded Toolchain交叉编译器 4)Mingw-w64 GCC for Windows 64 5)Debug 调试工具 openocd 6)Visual Studio Code ### **二、软件安装配置** 1. #### GNU Arm Embedded Toolchain交叉编译器 进入arm开发者官网,往下滑动选择下载解压可用的ZIP压缩包文件 [下载链接: Downloads | GNU Arm Embedded Toolchain Downloads – Arm Developer](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) ![](GCC-Pic/gcc1.png) 将下载好的压缩包文件解压在gcc-arm-none-eabi”文件夹中,并记住文件内“bin”文件的路径,后续需添加到系统环境变量Path中。 ![](GCC-Pic/gcc2.png) ![](GCC-Pic/gcc3.png) 添加完环境变量后,进行测试,检测是否安装好。 ![](GCC-Pic/gcc4.png) 2. #### 安装**Mingw-w64 GCC** 点击链接进入到SourceForge官网,往下翻可以找到很多版本的下载链接,选择红色框内型号即可,不同前后缀的具体差异请参考: [MinGW gcc下载链接及sjlj、dwarf、seh异同以及gcc安装_AMDDMA的博客-CSDN博客_seh和sjlj](https://blog.csdn.net/AMDDMA/article/details/111600238) 下载链接: [MinGW-w64 - for 32 and 64 bit Windows - Browse Files at SourceForge.net](https://sourceforge.net/projects/mingw-w64/files/) ![](GCC-Pic/gcc5.png) 同样,将下载好的文件解压到“gcc-arm-none-eabi”文件夹下,记住目录下的“bin”文件路径 ![](GCC-Pic/gcc6.png) 进入“bin”文件内找到“mingw32-make”应用程序文件,复制一份并重命名为“make”。这么做有利于在命令行执行make指令,而不是输入mingw32-make。 ![](GCC-Pic/gcc7.png) ​ 添加完环境变量后,进行测试,检测是否安装好。 ​ ![](GCC-Pic/gcc8.png) ​ ![](GCC-Pic/gcc9.png) #### 3. 安装调试软件Download pre-built OpenOCD for Windows 默认安装Vscode,安装过程比较简单,参考其他文章。有了以上三个软件的支持,已经可以在VScode中编译并生成bin文件和hex文件了,但众所周知,程序员最大的工作是Debug,那就免不了需要一款调试软件了。 Debug常用的硬件有STLink、JLink,WCH-Link,DapLink. Download pre-built OpenOCD for Windows下载链接:[OpenOCD for Windows](https://gnutoolchains.com/arm-eabi/openocd/) ​ ![](GCC-Pic/gcc10.png) 同样将下载好的压缩包解压至“OpenOCD-20231002-0.12.0”,记住文件内“bin”文件的路径。 ![](GCC-Pic/gcc11.png) ![](GCC-Pic/gcc12.png) ![](GCC-Pic/gcc13.png) 综上所述,基本的软件环境已经配置好。 ### **三、STM32-GCC-Template工程配置** 1. 工程结构 STM32-GCC-Template 使用的标准固件库开发,当然你可以使用HAL开发(这个不重要,有库就行了) ![](GCC-Pic/gcc14.png) ```bash - Application Application/inc Application/src - BspLibraries BspLibraries/inc BspLibraries/src - FwlibLibraries FwlibLibraries/CMSIS/Include FwlibLibraries/inc FwlibLibraries/src - Kernel Kernel/inc Kernel/src - SystemLibraries SystemLibraries/inc SystemLibraries/src - Build //编译过程输出文件 - tools tools/startup_stm32f407xx.s tools/STM32F407ZGTx_FLASH.ld - Makefile Makefile脚本文件,重点,构建全流程脚本 //OpenOCD 调试下载配置文件 cmsis-dap.cfg stm32f4x.cfg ``` 2. Makefile文件编写(重点) ```makefile Author = dele ###################################### # target 构建目标 ###################################### TARGET = stm32f407-gcc-template ###################################### # building variables ###################################### # debug build? DEBUG = 1 # optimization OPT = -Og ####################################### # paths ####################################### # source path # firmware library path PERIFLIB_PATH = # Build path BUILD_DIR = Build ###################################### # source # ###################################### # 修改1 C源文件添加 参加文件工程,按照下面格式添加所有的c文件 # C sources C_SOURCES = \ Kernel/src/stm32f4xx_it.c \ Kernel/src/system_stm32f4xx.c \ FwlibLibraries/src/misc.c \ FwlibLibraries/src/stm32f4xx_adc.c \ FwlibLibraries/src/stm32f4xx_can.c \ FwlibLibraries/src/stm32f4xx_crc.c \ FwlibLibraries/src/stm32f4xx_cryp_aes.c \ FwlibLibraries/src/stm32f4xx_cryp.c \ FwlibLibraries/src/stm32f4xx_cryp_des.c \ FwlibLibraries/src/stm32f4xx_cryp_tdes.c \ FwlibLibraries/src/stm32f4xx_dac.c \ FwlibLibraries/src/stm32f4xx_dbgmcu.c \ FwlibLibraries/src/stm32f4xx_dcmi.c \ FwlibLibraries/src/stm32f4xx_dma2d.c \ FwlibLibraries/src/stm32f4xx_dma.c \ FwlibLibraries/src/stm32f4xx_exti.c \ FwlibLibraries/src/stm32f4xx_flash.c \ FwlibLibraries/src/stm32f4xx_flash_ramfunc.c \ FwlibLibraries/src/stm32f4xx_gpio.c \ FwlibLibraries/src/stm32f4xx_hash.c\ FwlibLibraries/src/stm32f4xx_hash_md5.c \ FwlibLibraries/src/stm32f4xx_hash_sha1.c \ FwlibLibraries/src/stm32f4xx_i2c.c \ FwlibLibraries/src/stm32f4xx_iwdg.c \ FwlibLibraries/src/stm32f4xx_ltdc.c \ FwlibLibraries/src/stm32f4xx_pwr.c \ FwlibLibraries/src/stm32f4xx_rcc.c \ FwlibLibraries/src/stm32f4xx_rng.c \ FwlibLibraries/src/stm32f4xx_rtc.c \ FwlibLibraries/src/stm32f4xx_sai.c \ FwlibLibraries/src/stm32f4xx_sdio.c \ FwlibLibraries/src/stm32f4xx_spi.c \ FwlibLibraries/src/stm32f4xx_syscfg.c \ FwlibLibraries/src/stm32f4xx_tim.c \ FwlibLibraries/src/stm32f4xx_usart.c \ FwlibLibraries/src/stm32f4xx_wwdg.c \ BspLibraries/src/key.c \ BspLibraries/src/led.c \ SystemLibraries/src/delay.c \ SystemLibraries/src/usart.c \ SystemLibraries/src/sys.c \ SystemLibraries/src/timer.c \ Application/src/main.c \ # ASM sources # 修改2 汇编启动源文件添加 ASM_SOURCES = \ tools/startup_stm32f407xx.s ####################################### # binaries ####################################### # 修改3 gcc-arm-none-eabi工具链地址 PREFIX = arm-none-eabi- GCC_PATH = /SoftwareApplication/gcc-arm-none-eabi/bin 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 ####################################### # CFLAGS ####################################### # cpu 架构 CPU = -mcpu=cortex-m4 # fpu FPU = -mfpu=fpv4-sp-d16 # float-abi FLOAT-ABI = -mfloat-abi=hard # mcu MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI) # macros for gcc # AS defines AS_DEFS = # C defines # 修改4 全局宏定义 -DXXX C_DEFS = \ -DSTM32F40_41xxx \ -DUSE_STDPERIPH_DRIVER\ # AS includes AS_INCLUDES = # C includes # 修改5 H源文件添加 参加文件工程,按照下面格式添加所有的文件夹 C_INCLUDES =\ -I Kernel/inc \ -I FwlibLibraries/inc \ -I FwlibLibraries/CMSIS/Include \ -I BspLibraries/inc \ -I SystemLibraries/inc \ -I Application/inc \ # 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)" -MT"$(@:%.o=%.d)" ####################################### # LDFLAGS ####################################### # link script # 修改6 link script 链接脚本文件添加 链接脚本如何获取看参考stm32cubemx官方工程 LDSCRIPT = \ tools/STM32F407ZGTx_FLASH.ld # 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 $(BUILD_DIR)/$(TARGET).hex $(BUILD_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) @echo "[CC] $<" @$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@ $(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR) @echo "[AS] $<" @$(AS) -c $(CFLAGS) $< -o $@ $(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile @echo "[HEX] $< -> $@" @$(CC) $(OBJECTS) $(LDFLAGS) -o $@ @$(SZ) $@ $(BUILD_DIR)/%.hex: $(BUILD_DIR)/%.elf | $(BUILD_DIR) @echo "[HEX] $< -> $@" @$(HEX) $< $@ $(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf | $(BUILD_DIR) @echo "[BIN] $< -> $@" @$(BIN) $< $@ $(BUILD_DIR): @mkdir $@ ####################################### # clean up ####################################### # make clean 清除编译中间文件 # Windows环境不支持 rm 因此写成 -del # Linux环境 clean: -del /q $(BUILD_DIR) # Openocd 调试下载工具 # 修改7 cmsis-dap.cfg -f stm32f4x.cfg # 配置文件 修改成为自己使用的工具和芯片文件 如 stlink.cfg jlink.cfg stm32f1xx.cfg flash: openocd -f cmsis-dap.cfg -f stm32f4x.cfg -c init -c halt -c "program $(BUILD_DIR)/$(TARGET).bin 0x8000000" -c reset -c shutdown ####################################### # dependencies ####################################### -include $(wildcard $(BUILD_DIR)/*.d) # *** EOF *** ``` ### **四、STM32-工程测试** 1. make 构建工程 ![](GCC-Pic/gcc15.png) ![](GCC-Pic/gcc16.png) 2. make flash ![](GCC-Pic/gcc17.png) 接上串口线,打开串口软件,查看终端输出情况(如果是从MDK-Keil工程移植过来,printf应该是不支持的,因此终端没有输出,需要修改相关代码,后面写修改文件)(图片中的情况是修改之后的效果) ![](GCC-Pic/gcc19.png) 3. make clean 清除工程,修改main.c代码,重新构建代码 ![](GCC-Pic/gcc18.png) ![](GCC-Pic/gcc20.png) ![](GCC-Pic/gcc21.png) 4. 注意修改的部分(仅我的工程,不代表全部) (1)usart.c printf重定向问题 ```c //重定向c库函数printf到串口,重定向后可使用printf函数 // int fputc(int ch, FILE *f) // { // /* 发送一个字节数据到串口 */ // USART_SendData(DEBUG_USART, (uint8_t) ch); // /* 等待发送完毕 */ // while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET); // return (ch); // } int _write (int fd, char *pBuffer, int size) { for (int i = 0; i < size; i++) { while((USART1->SR&0X40)==0);//等待上一次串口数据发送完成 USART1->DR = (uint8_t) pBuffer[i]; //写DR,串口1将发送数据 } return size; } ``` (2)sys.c 汇编代码 (注意,由于工程来源于正点原子的工程修改,可能与其他工程模板不一样,非不要) ```c //THUMB指令不支持汇编内联 //采用如下方法实现执行汇编指令WFI __asm void WFI_SET(void) { WFI; } //关闭所有中断(但是不包括fault和NMI中断) __asm void INTX_DISABLE(void) { CPSID I BX LR } //开启所有中断 __asm void INTX_ENABLE(void) { CPSIE I BX LR } //设置栈顶地址 //addr:栈顶地址 __asm void MSR_MSP(u32 addr) { MSR MSP, r0 //set Main Stack value BX r14 } ``` ```c //THUMB指令不支持汇编内联 //采用如下方法实现执行汇编指令WFI void WFI_SET(void) { __ASM volatile("WFI"); } //关闭所有中断(但是不包括fault和NMI中断) void INTX_DISABLE(void) { __ASM volatile("CPSID I"); __ASM volatile("BX LR"); } //开启所有中断 void INTX_ENABLE(void) { __ASM volatile("CPSIE I"); __ASM volatile("BX LR"); } //设置栈顶地址 //addr:栈顶地址 void MSR_MSP(u32 addr) { __ASM volatile("MSR MSP, r0"); __ASM volatile("BX r14"); } ``` ### **五、测试效果** ​ 使用Vscode进行工程修改编辑,编译,下载代码(可以使用Cortex-Debug进行调试) ![](GCC-Pic/gcc23.png) ![](GCC-Pic/gcc24.png) ![](GCC-Pic/gcc22.png)