当前位置:网站首页>keil 采用 makefile 实现编译
keil 采用 makefile 实现编译
2022-07-27 14:37:00 【xhoufei2010】
1 说明
由于keil 软件需要收费,故有许多公司或者个人希望能够使用makefile 实现编译功能。如此一来,就可以脱离了keil 公司的限制,自由开发。
2 开发环境
(1) windows 操作系统的PC一台。
(2)arm-gcc windows端交叉编译工具链(个人使用版本:gcc-arm-none-eabi-4_7)。
如需下载,可到本人的上传链接下载:
http://download.csdn.net/download/xhoufei2010/10223874
(3) gd32f10x (cortex-m3内核)开发板一块。
3 编写对应的代码
本人的keil 安装目录为D:\develop\keil\,采用makefile 实现编译,操作步骤如下。
3.1 修改启动汇编文件 gd32f10x.s
gd32f10x.s 为系统的启动汇编文件,参考keil 软件安装之后标准的gcc编译器汇编文件修改而来,如果想了解标准源码,可查看keil 的安装目录:D:\develop\keil\ARM\Device\ARM\ARMCM3\Source\GCC\startup_ARMCM3.S
startup_ARMCM3.S 为cortex-m3的启动汇编文件,用于加载向量表等信息,设置环境,让程序可以正常跳转到C代码的main函数。
代码如下:
/* File: startup_ARMCM3.S * Purpose: startup file for Cortex-M3 devices. Should use with * GCC for ARM Embedded Processors * Version: V1.3 * Date: 08 Feb 2012 * * Copyright (c) 2012, ARM Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the ARM Limited nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL ARM LIMITED BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
.syntax unified
.arch armv7-m
.section .stack
.align 3
#ifdef __STACK_SIZE
.equ Stack_Size, __STACK_SIZE
#else
.equ Stack_Size, 0x400
#endif
.globl __StackTop
.globl __StackLimit
__StackLimit:
.space Stack_Size
.size __StackLimit, . - __StackLimit
__StackTop:
.size __StackTop, . - __StackTop
.section .heap
.align 3
#ifdef __HEAP_SIZE
.equ Heap_Size, __HEAP_SIZE
#else
.equ Heap_Size, 0x200
#endif
.globl __HeapBase
.globl __HeapLimit
__HeapBase:
.if Heap_Size
.space Heap_Size
.endif
.size __HeapBase, . - __HeapBase
__HeapLimit:
.size __HeapLimit, . - __HeapLimit
.section .isr_vector
.align 2
.globl __isr_vector
__isr_vector:
.long __StackTop /* Top of Stack */
.long Reset_Handler /* Reset Handler */
.long NMI_Handler /* NMI Handler */
.long HardFault_Handler /* Hard Fault Handler */
.long MemManage_Handler /* MPU Fault Handler */
.long BusFault_Handler /* Bus Fault Handler */
.long UsageFault_Handler /* Usage Fault Handler */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long 0 /* Reserved */
.long SVC_Handler /* SVCall Handler */
.long DebugMon_Handler /* Debug Monitor Handler */
.long 0 /* Reserved */
.long PendSV_Handler /* PendSV Handler */
.long SysTick_Handler /* SysTick Handler */
/* External interrupts */
.long WWDG_IRQHandler @; Vector Number 16,Window Watchdog
.long LVD_IRQHandler @; Vector Number 17,LVD through EXTI Line detect
.long TAMPER_IRQHandler @; Vector Number 18,Tamper Interrupt
.long RTC_IRQHandler @; Vector Number 19,RTC through EXTI Line
.long FMC_IRQHandler @; Vector Number 20,FMC
.long RCC_IRQHandler @; Vector Number 21,RCC
.long EXTI0_IRQHandler @; Vector Number 22,EXTI Line 0
.long EXTI1_IRQHandler @; Vector Number 23,EXTI Line 1
.long EXTI2_IRQHandler @; Vector Number 24,EXTI Line 2
.long EXTI3_IRQHandler @; Vector Number 25,EXTI Line 3
.long EXTI4_IRQHandler @; Vector Number 26,EXTI Line 4
.long DMA1_Channel1_IRQHandler @; Vector Number 27,DMA1 Channel 1
.long DMA1_Channel2_IRQHandler @; Vector Number 28,DMA1 Channel 2
.long DMA1_Channel3_IRQHandler @; Vector Number 29,DMA1 Channel 3
.long DMA1_Channel4_IRQHandler @; Vector Number 30,DMA1 Channel 4
.long DMA1_Channel5_IRQHandler @; Vector Number 31,DMA1 Channel 5
.long DMA1_Channel6_IRQHandler @; Vector Number 32,DMA1 Channel 6
.long DMA1_Channel7_IRQHandler @; Vector Number 33,DMA1 Channel 7
.long ADC1_2_IRQHandler @; Vector Number 34,ADC1 and ADC2
.long USB_HP_CAN1_TX_IRQHandler @; Vector Number 35,USB Device High Priority or CAN1 TX
.long USB_LP_CAN1_RX0_IRQHandler @; Vector Number 36,USB Device Low Priority or CAN1 RX0
.long CAN1_RX1_IRQHandler @; Vector Number 37,CAN1 RX1
.long CAN1_SCE_IRQHandler @; Vector Number 38,CAN1 SCE
.long EXTI9_5_IRQHandler @; Vector Number 39,EXTI Line 9..5
.long TIMER1_BRK_IRQHandler @; Vector Number 40,TIMER1 Break
.long TIMER1_UP_IRQHandler @; Vector Number 41,TIMER1 Update
.long TIMER1_TRG_COM_IRQHandler @; Vector Number 42,TIMER1 Break, Update, Trigger and Commutation
.long TIMER1_CC_IRQHandler @; Vector Number 43,TIMER1 Capture Compare
.long TIMER2_IRQHandler @; Vector Number 44,TIMER2
.long TIMER3_IRQHandler @; Vector Number 45,TIMER3
.long TIMER4_IRQHandler @; Vector Number 46,TIMER4
.long I2C1_EV_IRQHandler @; Vector Number 47,I2C1 Event
.long I2C1_ER_IRQHandler @; Vector Number 48,I2C1 Error
.long I2C2_EV_IRQHandler @; Vector Number 49,I2C2 Event
.long I2C2_ER_IRQHandler @; Vector Number 50,I2C1 Error
.long SPI1_IRQHandler @; Vector Number 51,SPI1
.long SPI2_IRQHandler @; Vector Number 52,SPI2
.long USART1_IRQHandler @; Vector Number 53,USART1
.long USART2_IRQHandler @; Vector Number 54,USART2
.long USART3_IRQHandler @; Vector Number 55,USART3
.long EXTI15_10_IRQHandler @; Vector Number 56,External Line[15:10]
.long RTCAlarm_IRQHandler @; Vector Number 57,RTC Alarm through EXTI Line
.long USBWakeUp_IRQHandler @; Vector Number 58,USB Device WakeUp from suspend through EXTI Line
.long TIMER8_BRK_IRQHandler @; Vector Number 59,TIMER8 Break
.long TIMER8_UP_IRQHandler @; Vector Number 60,TIMER8 Update
.long TIMER8_TRG_COM_IRQHandler @; Vector Number 61,TIMER8 Trigger and Commutation
.long TIMER8_CC_IRQHandler @; Vector Number 62,TIMER8 Capture Compare
.long ADC3_IRQHandler @; Vector Number 63,ADC3
.long EXMC_IRQHandler @; Vector Number 64,EXMC
.long SDIO_IRQHandler @; Vector Number 65,SDIO
.long TIMER5_IRQHandler @; Vector Number 66,TIMER5
.long SPI3_IRQHandler @; Vector Number 67,SPI3
.long UART4_IRQHandler @; Vector Number 68,UART4
.long UART5_IRQHandler @; Vector Number 69,UART5
.long TIMER6_IRQHandler @; Vector Number 70,TIMER6
.long TIMER7_IRQHandler @; Vector Number 71,TIMER7
.long DMA2_Channel1_IRQHandler @; Vector Number 72,DMA2 Channel1
.long DMA2_Channel2_IRQHandler @; Vector Number 73,DMA2 Channel2
.long DMA2_Channel3_IRQHandler @; Vector Number 74,DMA2 Channel3
.long DMA2_Channel4_5_IRQHandler @; Vector Number 75,DMA2 Channel4 and Channel5
.size __isr_vector, . - __isr_vector
.text
.thumb
.thumb_func
.align 2
.globl Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
/* Loop to copy data from read only memory to RAM. The ranges * of copy from/to are specified by following symbols evaluated in * linker script. * __etext: End of code section, i.e., begin of data sections to copy from. * __data_start__/__data_end__: RAM address range that data should be * copied to. Both must be aligned to 4 bytes boundary. */
ldr r1, =__etext
ldr r2, =__data_start__
ldr r3, =__data_end__
#if 1
/* Here are two copies of loop implemenations. First one favors code size * and the second one favors performance. Default uses the first one. * Change to "#if 0" to use the second one */
.flash_to_ram_loop:
cmp r2, r3
ittt lt
ldrlt r0, [r1], #4
strlt r0, [r2], #4
blt .flash_to_ram_loop
#else
subs r3, r2
ble .flash_to_ram_loop_end
.flash_to_ram_loop:
subs r3, #4
ldr r0, [r1, r3]
str r0, [r2, r3]
bgt .flash_to_ram_loop
.flash_to_ram_loop_end:
#endif
#ifndef __NO_SYSTEM_INIT
ldr r0, =SystemInit
blx r0
#endif
ldr r0, =_start
bx r0
.pool
.size Reset_Handler, . - Reset_Handler
/* Macro to define default handlers. Default handler * will be weak symbol and just dead loops. They can be * overwritten by other handlers */
.macro def_irq_handler handler_name
.align 1
.thumb_func
.weak \handler_name
.type \handler_name, %function
\handler_name :
b .
.size \handler_name, . - \handler_name
.endm
/* Dummy Exception Handlers (infinite loops which can be modified) */
def_irq_handler NMI_Handler
def_irq_handler HardFault_Handler
def_irq_handler MemManage_Handler
def_irq_handler BusFault_Handler
def_irq_handler UsageFault_Handler
def_irq_handler SVC_Handler
def_irq_handler DebugMon_Handler
def_irq_handler PendSV_Handler
def_irq_handler SysTick_Handler
def_irq_handler Default_Handler
/* ToDo: Add here the export definition for the device specific external interrupts handler */
def_irq_handler WWDG_IRQHandler
def_irq_handler LVD_IRQHandler
def_irq_handler TAMPER_IRQHandler
def_irq_handler RTC_IRQHandler
def_irq_handler FMC_IRQHandler
def_irq_handler RCC_IRQHandler
def_irq_handler EXTI0_IRQHandler
def_irq_handler EXTI1_IRQHandler
def_irq_handler EXTI2_IRQHandler
def_irq_handler EXTI3_IRQHandler
def_irq_handler EXTI4_IRQHandler
def_irq_handler DMA1_Channel1_IRQHandler
def_irq_handler DMA1_Channel2_IRQHandler
def_irq_handler DMA1_Channel3_IRQHandler
def_irq_handler DMA1_Channel4_IRQHandler
def_irq_handler DMA1_Channel5_IRQHandler
def_irq_handler DMA1_Channel6_IRQHandler
def_irq_handler DMA1_Channel7_IRQHandler
def_irq_handler ADC1_2_IRQHandler
def_irq_handler USB_HP_CAN1_TX_IRQHandler
def_irq_handler USB_LP_CAN1_RX0_IRQHandler
def_irq_handler CAN1_RX1_IRQHandler
def_irq_handler CAN1_SCE_IRQHandler
def_irq_handler EXTI9_5_IRQHandler
def_irq_handler TIMER1_BRK_IRQHandler
def_irq_handler TIMER1_UP_IRQHandler
def_irq_handler TIMER1_TRG_COM_IRQHandler
def_irq_handler TIMER1_CC_IRQHandler
def_irq_handler TIMER2_IRQHandler
def_irq_handler TIMER3_IRQHandler
def_irq_handler TIMER4_IRQHandler
def_irq_handler I2C1_EV_IRQHandler
def_irq_handler I2C1_ER_IRQHandler
def_irq_handler I2C2_EV_IRQHandler
def_irq_handler I2C2_ER_IRQHandler
def_irq_handler SPI1_IRQHandler
def_irq_handler SPI2_IRQHandler
def_irq_handler USART1_IRQHandler
def_irq_handler USART2_IRQHandler
def_irq_handler USART3_IRQHandler
def_irq_handler EXTI15_10_IRQHandler
def_irq_handler RTCAlarm_IRQHandler
def_irq_handler USBWakeUp_IRQHandler
def_irq_handler TIMER8_BRK_IRQHandler
def_irq_handler TIMER8_UP_IRQHandler
def_irq_handler TIMER8_TRG_COM_IRQHandler
def_irq_handler TIMER8_CC_IRQHandler
def_irq_handler ADC3_IRQHandler
def_irq_handler EXMC_IRQHandler
def_irq_handler SDIO_IRQHandler
def_irq_handler TIMER5_IRQHandler
def_irq_handler SPI3_IRQHandler
def_irq_handler UART4_IRQHandler
def_irq_handler UART5_IRQHandler
def_irq_handler TIMER6_IRQHandler
def_irq_handler TIMER7_IRQHandler
def_irq_handler DMA2_Channel1_IRQHandler
def_irq_handler DMA2_Channel2_IRQHandler
def_irq_handler DMA2_Channel3_IRQHandler
def_irq_handler DMA2_Channel4_5_IRQHandler
.end
3.2 编写链接文件gd32f10x.ld
gd32f10x.ld 为链接文件,用于确定设备堆栈起始地址和FLASH大小配置等。
gd32f10x.ld 为参考keil安装目录下D:\develop\keil\ARM\Device\ARM\ARMCM3\Source\GCC\gcc_arm.ld 修改地址得到,用于确定设备堆栈起始地址和FLASH大小配置等。其中的地址,可以查看datasheet 了解,或者打开keil 的标准工程查看,如下图所示。 
图 3-1 工程 rom、ram 地址配置图
修改后的gd32f10x.ld 代码如下
/* Linker script to configure memory regions. */
MEMORY
{
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 0x8000 /* 32k */
RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x5000 /* 20k */
}
/* Library configurations */
GROUP(libgcc.a libc.a libm.a libnosys.a)
/* Linker script to place sections and symbol values. Should be used together * with other linker script that defines memory regions FLASH and RAM. * It references following symbols, which must be defined in code: * Reset_Handler : Entry of reset handler * * It defines following symbols, which code can use without definition: * __exidx_start * __exidx_end * __etext * __data_start__ * __preinit_array_start * __preinit_array_end * __init_array_start * __init_array_end * __fini_array_start * __fini_array_end * __data_end__ * __bss_start__ * __bss_end__ * __end__ * end * __HeapLimit * __StackLimit * __StackTop * __stack */
ENTRY(Reset_Handler)
SECTIONS
{
.text :
{
KEEP(*(.isr_vector))
*(.text*)
KEEP(*(.init))
KEEP(*(.fini))
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
KEEP(*(.eh_frame*))
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
__etext = .;
.data : AT (__etext)
{
__data_start__ = .;
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP(*(.preinit_array))
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
KEEP(*(SORT(.init_array.*)))
KEEP(*(.init_array))
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP(*(SORT(.fini_array.*)))
KEEP(*(.fini_array))
PROVIDE_HIDDEN (__fini_array_end = .);
. = ALIGN(4);
/* All data end */
__data_end__ = .;
} > RAM
.bss :
{
__bss_start__ = .;
*(.bss*)
*(COMMON)
__bss_end__ = .;
} > RAM
.heap :
{
__end__ = .;
end = __end__;
*(.heap*)
__HeapLimit = .;
} > RAM
/* .stack_dummy section doesn't contains any symbols. It is only * used for linker to calculate size of stack sections, and assign * values to stack symbols later */
.stack_dummy :
{
*(.stack)
} > RAM
/* Set stack top to end of RAM, and stack limit move down by * size of stack_dummy section */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}
3.3 编写makefile
makefile 中,根据自己的需要增加和修改内容。
INCDIR += -I $(ROOTDIR)/System_file/include该文件夹的内容,为keil 安装目录下的一些头文件拷贝过来,大家可根据需要,去自己的keil 安装目录下拷贝,如果缺少对应的代码,可能会编译报错。本人的keil 安装目录为D:\develop\keil\
故需要从如下几个目录拷贝源码至$(ROOTDIR)/System_file/include
D:\develop\keil\ARM\RV31\INC
D:\develop\keil\ARM\CMSIS\Include
D:\develop\keil\ARM\Inc\GD\GD32F10x makefile 的内容如下:
BIN = bin
OBJ = obj
OUTPUT = $(BIN)/$(TARGET)
ROOTDIR = .
# Compiler & Linker
CROSS_COMPILE=arm-none-eabi-
CC=$(CROSS_COMPILE)gcc
CXX=$(CROSS_COMPILE)g++
AS=$(CROSS_COMPILE)as
AR=$(CROSS_COMPILE)ar
LD=$(CROSS_COMPILE)ld
OBJDUMP=$(CROSS_COMPILE)objdump
OBJCOPY=$(CROSS_COMPILE)objcopy
STRIP=$(CROSS_COMPILE)strip
############# CFLAGS ##############
# Options for specific architecture
ARCH_FLAGS= -mthumb -mcpu=cortex-m3
DEFS += -DUSE_STDPERIPH_DRIVER
DEFS += -DUSE_GD32F103C_EVAL
DEFS += -DGD32F10X_HD
CFLAGS=$(ARCH_FLAGS) $(DEFS) $(INCDIR) -ffunction-sections -g -Os -std=gnu99 \
############# LFLAGS ##############
LFLAGS =
LFLAGS += -T gd32f10x.ld -Wl,-Map=$(OUTPUT).map -mthumb -mcpu=cortex-m3 -Wl,--gc-sections -lm
####################
LIBS =
##########
VPATH = $(wildcard $(ROOTDIR)/*) $(wildcard $(ROOTDIR)/*/*) $(wildcard $(ROOTDIR)/*/*/*) \
$(wildcard $(ROOTDIR)/*/*/*/*) $(wildcard $(ROOTDIR)/*/*/*/*/*) $(wildcard $(ROOTDIR)/*/*/*/*/*/*) \ $(wildcard $(ROOTDIR)/*/*/*/*/*/*/*) \
############# include ##############
INCDIR =
INCDIR += -I $(ROOTDIR)/Examples/USB_IAP/inc
INCDIR += -I $(ROOTDIR)/Firmware/CMSIS
INCDIR += -I $(ROOTDIR)/Firmware/GD32F10x_StdPeriph_Driver/inc
INCDIR += -I $(ROOTDIR)/Firmware/GD32_USB_Device_Driver/inc
INCDIR += -I $(ROOTDIR)/Firmware/GD32_USB_Device_Library/Class/IAP/inc
INCDIR += -I $(ROOTDIR)/Firmware/GD32_USB_Device_Library/Core/inc
INCDIR += -I $(ROOTDIR)/Utilities/GD32_EVAL/GD32103C_EVAL
INCDIR += -I $(ROOTDIR)/Utilities/GD32_EVAL/Common
INCDIR += -I $(ROOTDIR)/Examples/USB_IAP/Pax/pax_inc
INCDIR += -I $(ROOTDIR)/System_file/include
############# source ##############
ASM_OBJECTS = gd32f10x_init.o
C_OBJECTS = main.o \
system_gd32f10x.o
###############################
ASM_OBJECTS_DDR = $(addprefix $(OBJ)/, $(ASM_OBJECTS))
C_OBJECTS_DDR = $(addprefix $(OBJ)/, $(C_OBJECTS))
############# build ##############
all: $(OUTPUT).elf
$(OUTPUT).elf: $(ASM_OBJECTS_DDR) $(C_OBJECTS_DDR)
$(CC) -o $(OUTPUT).elf $^ $(LIBS) $(LFLAGS)
$(OBJDUMP) -D $(OUTPUT).elf > $(BIN)/asm.txt
$(OBJCOPY) -O binary $(OUTPUT).elf $(OUTPUT).bin
$(OBJCOPY) -O ihex $(OUTPUT).elf $(OUTPUT).hex
$(C_OBJECTS_DDR): $(OBJ)/%.o: %.c
echo CC $<
$(CC) $(CFLAGS) -c -o [email protected] $<
$(ASM_OBJECTS_DDR): $(OBJ)/%.o: %.S
echo CC $<
$(CC) $(CFLAGS) -c -o [email protected] $<
############# clean ##############
clean:
-rm -f $(OBJ)/*.* $(BIN)/*.*
注意,其中system_gd32f10x.o为工程的源码,其中有SystemInit 函数,用于初始化时钟,如果没有该system_gd32f10x.o,编译过程中,会提示SystemInit 函数没有定义,报错。
注意:有些项目的源码由于优化等级的问题,会导致无法运行正常,这时候需要修改优化等级,如-Os修改为-O1
CFLAGS=$(ARCH_FLAGS) $(DEFS) $(INCDIR) -ffunction-sections -g -O1 -std=gnu993.4 SystemInit 没有定义问题
如果没有system_gd32f10x.o,编译过程中,会提示SystemInit 函数没有定义,报错。解决方案3选1:
(1)找到对应的system_gd32f10x.c和system_gd32f10x.h 源码添加至makefile编译。其中system_gd32f10x.c 里面包含了SystemInit 函数。
(2)自己编写一个文件,文件中包含了SystemInit 函数申明,函数内容留空,这样也可以解决问题。
(3) 注释掉gd32f10x_init.S 中的SystemInit 部分代码。
/*
#ifndef __NO_SYSTEM_INIT
ldr r0, =SystemInit
blx r0
#endif
*/3.5 编写bat 编译脚本
由于gcc编译器为 windows端,则编写bat脚本,用于执行makefile,脚本名称为Build_Debug.bat
set PATH=../../tools/gcc-arm-none-eabi-4_7/bin;C:\make381;C:\cygwin\bin;
Set DATETIME=%date:~0,4%%date:~5,2%%date:~8,2%
set MON_VER=1.11
rm -f ./bin/*.elf ./bin/*.hex ./bin/*.map ./bin/*.bin ./bin/*.txt
set USE_AREA=C
set TARGET=GD32_Debug
make -B all
其中,set PATH=../../tools/gcc-arm-none-eabi-4_7/bin,用于设置gcc的工具链路径,跟进自己的路径进行修改。
3.6 增加编译文件夹
在目录下,新建 bin、obj 两个文件夹,用于保存编译的文件,不然编译过程中会提示找不到文件夹。
3.7 编译
1、在window 端进入dos命令行
2、进入到自己的代码目录
e:
cd E:\Project\gd32\test\3、准备好编译文件后,进行编译
其中,该目录下有 makefile、Build_Debug.bat、gd32f10x.ld、gd32f10x_init.S、obj文件夹、bin文件夹、需要编译的 .C 和 .H 源代码
运行编译脚本,进行编译
E:\Project\gd32\test>Build_Debug.bat边栏推荐
- Talk about the index of interview questions
- Use deconstruction to exchange the values of two variables
- 语音直播系统——提升云存储安全性的必要手段
- Is the array name the address of the first element?
- Summary of network device hard core technology insider router (Part 2)
- [sword finger offer] interview question 45: arrange the array into the smallest number
- Analysis of spark task scheduling exceptions
- DRF学习笔记(四):DRF视图
- DRF学习笔记(准备)
- 网络原理(1)——基础原理概述
猜你喜欢
![[sword finger offer] interview question 54: the k-largest node of the binary search tree](/img/13/7574af86926a228811503904464f3f.png)
[sword finger offer] interview question 54: the k-largest node of the binary search tree

leetcode234题-简单方法判断回文链表

Division of entity classes (VO, do, dto)

Static关键字的三种用法

Half find

Using Lombok results in the absence of parent class attributes in the printed toString

IP protocol of network layer

DRF学习笔记(二):数据反序列化

初识结构体

NPM install error unable to access
随机推荐
Fluent -- layout principle and constraints
synchronized和ReentrantLock的区别
Under the ban, the Countermeasures of security giants Haikang and Dahua!
Troubleshooting the slow startup of spark local programs
JS find the maximum and minimum values in the array (math.max() method)
初识MySQL数据库
Causes and solutions of deadlock in threads
Three uses of static keyword
On juicefs
Spark 3.0 testing and use
兆骑科创创业大赛策划承办机构,双创平台,项目落地对接
[regular expression] matching grouping
[sword finger offer] interview question 46: translating numbers into strings - dynamic programming
Spark RPC
[Yunxiang book club issue 13] common methods of viewing media information and processing audio and video files in ffmpeg
Mlx90640 infrared thermal imager temperature sensor module development notes (VII)
go语言慢速入门——包
[sword finger offer] interview question 54: the k-largest node of the binary search tree
C language: Sanzi game
DRF学习笔记(一):数据序列化