说实话,现在很多人都用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)
# 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锕……