基于GNU 对STM32工程

 说实话,现在很多人都用IAR跟kei等可视化IDE,真的很方便的。
 但是不管是IAR还是IDE,我想很多人都觉得要嘛编辑界面不好,要嘛就是编译器不好(这也是Iar与kei之间的对比)。
 不过他们共同点是占内存,老机子运行起来很慢……- -|||
 
 其实我一直用MDK编译环境的,不过后来在用一个嵌入式系统才转到GNU去。但是用了之后,发觉挺好用的。
 具体好用在哪里呢:
 1.我是用STM32的,STM32的库很大,编译的文件比我们自己的文件都多好多,如果你一个清除所有重新编译,时间是很久的,也不方便维护。但是用makefile单独生成一个stm32库的话,就不一样了,主程序的makefile是设置好后是不能删除库的,所以不用重新生成,编译要快多了。
 2.库添加方便,如果有几个独立库就独立添加,其他的就不用管了。
 3.利用notepad++或者slickedit进行编辑,搭配gcc环境,需要时候就一个make指令一步到位。也可以自己定制提醒字幕挺不错吧?
 
 不过本人菜鸟,对GNU一无所知,甚至你叫我自己写个makefile我都不会,也不会用gcc命令…………-  -|
 但是会改就行了嘛。所以本文章是在别人的基础上改的。
 
 原版的makefile如下:
 # setup

COMPILE_OPTS = -mcpu=cortex-m3 -mthumb -Wall -g -O0
INCLUDE_DIRS = -I . -I lib/inc
LIBRARY_DIRS = -L lib

CC = arm-eabi-gcc
CFLAGS = $(COMPILE_OPTS) $(INCLUDE_DIRS)

CXX = arm-eabi-g++
CXXFLAGS = $(COMPILE_OPTS) $(INCLUDE_DIRS)

AS = arm-eabi-gcc
ASFLAGS = $(COMPILE_OPTS) -c

LD = arm-eabi-gcc
LDFLAGS = -Wl,--gc-sections,[email protected],-cref,-u,Reset_Handler $(INCLUDE_DIRS) $(LIBRARY_DIRS) -T stm32.ld

OBJCP = arm-eabi-objcopy
OBJCPFLAGS = -O binary

AR = arm-eabi-ar
ARFLAGS = cr

MAIN_OUT = main
MAIN_OUT_ELF = $(MAIN_OUT).elf
MAIN_OUT_BIN = $(MAIN_OUT).bin

# all

all: $(MAIN_OUT_ELF) $(MAIN_OUT_BIN)

扫描二维码关注公众号,回复: 3773317 查看本文章

# main

$(MAIN_OUT_ELF): main.o stm32f10x_it.o lib/libstm32.a
 $(LD) $(LDFLAGS) main.o stm32f10x_it.o lib/libstm32.a --output $@

$(MAIN_OUT_BIN): $(MAIN_OUT_ELF)
 $(OBJCP) $(OBJCPFLAGS) $< $@


# flash

flash: $(MAIN_OUT)
 @cp $(MAIN_OUT_ELF) jtag/flash
 @cd jtag; openocd -f flash.cfg
 @rm jtag/flash


# libstm32.a

LIBSTM32_OUT = lib/libstm32.a

LIBSTM32_OBJS = /
 lib/src/stm32f10x_adc.o /
 lib/src/stm32f10x_bkp.o /
 lib/src/stm32f10x_can.o /
 lib/src/stm32f10x_dma.o /
 lib/src/stm32f10x_exti.o /
 lib/src/stm32f10x_flash.o /
 lib/src/stm32f10x_gpio.o /
 lib/src/stm32f10x_i2c.o /
 lib/src/stm32f10x_iwdg.o /
 lib/src/stm32f10x_lib.o /
 lib/src/stm32f10x_nvic.o /
 lib/src/stm32f10x_pwr.o /
 lib/src/stm32f10x_rcc.o /
 lib/src/stm32f10x_rtc.o /
 lib/src/stm32f10x_spi.o /
 lib/src/stm32f10x_systick.o /
 lib/src/stm32f10x_tim.o /
 lib/src/stm32f10x_tim1.o /
 lib/src/stm32f10x_usart.o /
 lib/src/stm32f10x_wwdg.o /
 lib/src/cortexm3_macro.o /
 lib/src/stm32f10x_vector.o

$(LIBSTM32_OUT): $(LIBSTM32_OBJS)
 $(AR) $(ARFLAGS) $@ $(LIBSTM32_OBJS)

$(LIBSTM32_OBJS): stm32f10x_conf.h


clean:
 -rm *.o lib/src/*.o $(LIBSTM32_OUT) $(MAIN_OUT_ELF) $(MAIN_OUT_BIN)
 
 对于上面这个有很多的不足,有下过stm32的gnu例程的人应该看过这个例程,地址是代码和Makefile是基于http://www.siwawi.arubi.uni-kl.de/avr_projects/arm_projects/index_cortex.html#stm32_blink
 这下懂了吧。
 从上面的makefile我们看到的是,首先,它结构不好,其次,它编译需要很多时间,此外,它的一个make clean会吧库都删掉,这样重新编译就很费时间了……当然某种程度上多,对于想清除库的,这样很方便。另外,明显它没有用到makefile的优势,有些地方改一个地方也要改另外的地方,比如添加编译文件,它就需要改两个地方。所以针对这个我们进行修改。
 
 修改过程很简单,添加一些路径,吧要编译的文件跟连接库统一放到同类编译变量去,修改后的makefile如下:
 # setup

#包含文件路径

LIBALLDIRS = lib
STM32LIBSRC = lib/STM32F10x_StdPeriph_Driver
STM32LIBSRC_DIR = $(STM32LIBSRC)/src
STM32LIBINC_DIR = $(STM32LIBSRC)/inc

STM32DSPLIBSRC = lib/STM32F10x_DSP_Lib
STM32DSPLIBSRC_DIR = $(STM32DSPLIBSRC)/src
STM32DSPLIBINC_DIR = $(STM32DSPLIBSRC)/inc

COMPILE_OPTS = -mcpu=cortex-m3 -mthumb -Wall -g -O0
INCLUDE_DIRS = -I . -I$(STM32LIBINC_DIR) -I $(LIBALLDIRS) -I $(STM32DSPLIBINC_DIR)
LIBRARY_DIRS = -L $(STM32LIBSRC) -L $(LIBALLDIRS) -L $(STM32DSPLIBSRC)

CC = arm-eabi-gcc
CFLAGS = $(COMPILE_OPTS) $(INCLUDE_DIRS)

CXX = arm-eabi-g++
CXXFLAGS = $(COMPILE_OPTS) $(INCLUDE_DIRS)

AS = arm-eabi-gcc
ASFLAGS = $(COMPILE_OPTS) -c

LD = arm-eabi-gcc
LDFLAGS = -Wl,--gc-sections,[email protected],-cref,-u,Reset_Handler $(INCLUDE_DIRS) $(LIBRARY_DIRS) -T stm32.ld

OBJCP = arm-eabi-objcopy
OBJCPFLAGS = -O binary

AR = arm-eabi-ar
ARFLAGS = cr

MAIN_OUT = main
MAIN_OUT_ELF = $(MAIN_OUT).elf
MAIN_OUT_BIN = $(MAIN_OUT).bin

#这么改之后,添加编译文件与库就在这部分,其他地方不用改了,这里的库我是为了好看点菜这么编,实际上可以跟编译.o一样的方式编写
APP_OBJ = $(MAIN_OUT).o RCC.o hal.o GPIO.o TIM.o stm32f10x_it.o NVIC.o

STM32_LIB = lib/STM32F10x_StdPeriph_Driver/libstm32.a
STM32DSP_LIB = $(STM32DSPLIBSRC)/stm32dsp.a
ALL_LIB = $(STM32_LIB) $(STM32DSP_LIB)
# all

all: $(MAIN_OUT_ELF) $(MAIN_OUT_BIN)

# main

$(MAIN_OUT_ELF):$(APP_OBJ)
 @$(LD) $(LDFLAGS) $(APP_OBJ) $(ALL_LIB) --output $@
 @echo "生成ELF文件!"
$(MAIN_OUT_BIN): $(MAIN_OUT_ELF)
 @$(OBJCP) $(OBJCPFLAGS) $< $@
 @echo "生成BIN文件!"

# flash

flash: $(MAIN_OUT)
 @cp $(MAIN_OUT_ELF) jtag/flash
 @cd jtag; openocd -f flash.cfg
 @rm jtag/flash


# libstm32.a

clean:

#加入-f指令屏蔽警报- -反正移除文件也不需要这个。
 @-rm -f *.o $(MAIN_OUT_ELF) $(MAIN_OUT_BIN)
 @echo "删除所有编译生成的文件!"
当然这只是一部分,我们还得让修改另外一个makefile来生成一个库文件:
# setup

STM32LIBSRC_DIR = src
STM32LIBINC_DIR = inc


COMPILE_OPTS = -mcpu=cortex-m3 -mthumb -Wall -g -O0
INCLUDE_DIRS = -I . -I$(STM32LIBINC_DIR)
LIBRARY_DIRS = -L lib

CC = arm-eabi-gcc
CFLAGS = $(COMPILE_OPTS) $(INCLUDE_DIRS)

CXX = arm-eabi-g++
CXXFLAGS = $(COMPILE_OPTS) $(INCLUDE_DIRS)

AS = arm-eabi-gcc
ASFLAGS = $(COMPILE_OPTS) -c

LD = arm-eabi-gcc
LDFLAGS = -Wl,--gc-sections,[email protected],-cref,-u,Reset_Handler $(INCLUDE_DIRS) $(LIBRARY_DIRS) -T stm32.ld

OBJCP = arm-eabi-objcopy
OBJCPFLAGS = -O binary

AR = arm-eabi-ar
ARFLAGS = cr


MAIN_OUT = main
MAIN_OUT_ELF = $(MAIN_OUT).elf
MAIN_OUT_BIN = $(MAIN_OUT).bin


LIBSTM32_OBJS = /
 $(STM32LIBSRC_DIR)/misc.o /
 $(STM32LIBSRC_DIR)/stm32f10x_adc.o /
 $(STM32LIBSRC_DIR)/stm32f10x_bkp.o /
 $(STM32LIBSRC_DIR)/stm32f10x_can.o /
 $(STM32LIBSRC_DIR)/stm32f10x_cec.o /
 $(STM32LIBSRC_DIR)/stm32f10x_crc.o /
 $(STM32LIBSRC_DIR)/stm32f10x_dac.o /
 $(STM32LIBSRC_DIR)/stm32f10x_dbgmcu.o /
 $(STM32LIBSRC_DIR)/stm32f10x_dma.o /
 $(STM32LIBSRC_DIR)/stm32f10x_exti.o /
 $(STM32LIBSRC_DIR)/stm32f10x_flash.o /
 $(STM32LIBSRC_DIR)/stm32f10x_fsmc.o /
 $(STM32LIBSRC_DIR)/stm32f10x_gpio.o /
 $(STM32LIBSRC_DIR)/stm32f10x_i2c.o /
 $(STM32LIBSRC_DIR)/stm32f10x_iwdg.o /
 $(STM32LIBSRC_DIR)/stm32f10x_pwr.o /
 $(STM32LIBSRC_DIR)/stm32f10x_rcc.o /
 $(STM32LIBSRC_DIR)/stm32f10x_rtc.o /
 $(STM32LIBSRC_DIR)/stm32f10x_sdio.o /
 $(STM32LIBSRC_DIR)/stm32f10x_spi.o /
 $(STM32LIBSRC_DIR)/stm32f10x_tim.o /
 $(STM32LIBSRC_DIR)/stm32f10x_usart.o /
 $(STM32LIBSRC_DIR)/stm32f10x_wwdg.o /
 $(STM32LIBSRC_DIR)/core_cm3.o /
 $(STM32LIBSRC_DIR)/startup_stm32f10x_md.o /
 $(STM32LIBSRC_DIR)/system_stm32f10x.o

# all
LIBSTM32_OUT = libstm32.a

all: $(LIBSTM32_OUT)
# @echo "creating stm32 lib..."
$(LIBSTM32_OUT): $(LIBSTM32_OBJS)
 @rm -f stm32lib.a
 $(AR) $(ARFLAGS) $@ $(LIBSTM32_OBJS)
 @echo "生成GNC集成库libstm32.a!"
#$(LIBSTM32_OBJS): stm32f10x_conf.h

clean:
 @-rm -f src/*.o $(LIBSTM32_OUT)
 @echo "删除所有生成的文件!"

一样的复制粘贴,只是改了些小地方而已,事实上是把上一个makefile的库生成指令放到这了。
这样就可以改好了。
另外想该处理器的话,需要在库文件找到stm32f10x.h里面根据你的stm32类型更改,(方法就是注释嘛),并且需要在stm32ld修改你的处理器flash与内存:
/*
Linker script for STM32F10x
Copyright RAISONANCE 2007 (modified by Lanchon 1-Feb-2008)
You can use, copy and distribute this file freely, but without any waranty.
Configure memory sizes, end of stack and boot mode for your project here.
*/


/* include the common STM32F10x sub-script */
INCLUDE "STM32_COMMON.ld"

/* Memory Spaces Definitions */
MEMORY
{
  RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 48K  /* also change _estack below */
  FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 256K
  FLASHB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB0 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB1 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB2 (rx) : ORIGIN = 0x00000000, LENGTH = 0
  EXTMEMB3 (rx) : ORIGIN = 0x00000000, LENGTH = 0
}

/* highest address of the user mode stack */
_estack = 0x2000C000;

/* include the section management sub-script */
/* (either "STM32_SEC_FLASH.ld" or "STM32_SEC_RAM.ld") */
INCLUDE "STM32_SEC_FLASH.ld"


这样一个GNU开发的STM32例程就编辑好了……
修改好的实例我放在CSDN,自己去下载,集成STM固件库3.4与电机库2.0。

http://download.csdn.net/source/2799887

此外需要编译STM32的启动文件.s要不生成的bin文件大小可是0k的- -我是已经加进去md的,如果你们的芯片不是md的,到lib/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/gcc_ride7目录下找个对应拷到stm32的库src里面去,然后要在库生成makefile里面吧名字$(STM32LIBSRC_DIR)/startup_stm32f10x_md.o修改成你copy的那文件.o再编译。

如果你觉得麻烦的话,请自觉忽视。

最后提醒下,用gcc编译生成的bin二进制文件代码密度是远远大于keil4的hex文件的哦,个人实测的,用这个makefile生成的大小是70多k,但是用mdk4就只有40k左右。自己权衡把,除非会makefile跟gcc选项的把编译命令优化下- -要不还是比不上mdk锕……

猜你喜欢

转载自blog.csdn.net/xuzhenglim/article/details/5979313