keil 采用 makefile 实现编译

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 $@ $< 

$(ASM_OBJECTS_DDR): $(OBJ)/%.o:  %.S   
    echo CC $< 
    $(CC) $(CFLAGS) -c -o $@ $<    

#############   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=gnu99

3.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

猜你喜欢

转载自blog.csdn.net/xhoufei2010/article/details/79161988