用GCC开发STM32,正点原子开发板的一个库函数版本例程示例

简介: 用GCC开发STM32,正点原子开发板的一个库函数版本例程示例

GCC环境搭建.


首先下载交叉编译环境GCC,这个网上有很多,百度一下就能找到下载。比如 Sourcery G++ for ARM EABI


我的CSDN资源里,有相关下载。


熟悉下Makefile


强力推荐熟悉网络牛人李云的51cto博客,有一篇驾驭Makefile的文章,另外一份参考资料也尤为重要《GNUmake中文手册-v3.80.pdf》,这都是先辈们开凿好的前路,对于后辈的我们只要沿路走就可以了。


熟悉Makefile主要还是实践,按照李云博客介绍的方法,多使用echo,或者使用make的调试命令make –D > 1.txt,这样可以熟悉其中的依赖关系和建立顺序。说的直白点就是建立对应依赖关系。


在熟悉的时候,可以一边对照实际工程编写对应的Makefile。


以下是简要学习Makefile的笔记:


1. %.a: 匹配所有以.a结尾的所有文件名


  |--> 类似于通常意义的*.


2. $(addprefixsrc/,foo bar) -->


  返回值为"src/foosrc/bar"。


3. vpath %.h../headers


  Makefile中出现的.h文件:如果不能再当前目录中找到,则到目录"../headers"下寻找.


vpath与VPATH的区别在于后者指定全局的搜索路径


4. $(MAKE) -C$(STD_PERIPH_LIB)


  make的递归执行-->4.6GNUmake中文手册-v3.8


  当前目录下存在外设库文件,在编译的时候先对子目录进行编译.


  它等价于命令


  lib:


        cd $(STD_PERIPH_LIB) && $(MAKE)


5. $@:代表规则中的目标文件名:可以使用@-->at 代表目标的意思


  $%:规则的目标文件是一个静态库文件时,代表静态库的一个成员名.


  $<:规则的第一个依赖文件名.


  $^:规则的所有依赖文件列表.


  $(*D): 代表"茎"中的目录部分


  $(*F): 代表"茎"中的文件名部分


6. find ./ -name'*~' | xargs rm -f


  当你尝试用rm 删除太多的文件,你可能得到一个错误信息:


  /bin/rm Argument list too long. 用xargs 去避免这个问题


7. 将make调试信息保存到txt文档


  make -d > 1.txt


8. main.c 中#include"defs.h"


  命令 gcc -M main.c


  out: main.o:main.c defs.h


  若不需要依赖关系中不考虑标准头文件时


  使用gcc -MM main.c


9.  := 与 += 区别


  := --> 立即展开


  += --> 立即展开或延迟展开


  对于所有条件语句均采用立即展开


10. 将make输出的错误信息输出到文件1.txt


  make 2>1.txt


11. 从Shell获得当前文件夹位置


  ROOT=$(shell pwd)


12. 包含依赖文件时,不要放在所有目标的前面,如下所示



其中原因就是make依然会将dep文件作为目标,从而后面的目标无法得到运行。


熟悉gcc编译


Gcc编译学习是一个长期的过程,主要参考文档见安装目录下的Documation中的所有pdf和readme.txt。下面是简短的学习笔记。


1.      参数解释:


-g(level): 在本地操作系统产生指定格式的调试消息(stabs,COFF,XCOFF,DWARF 2)


-ggdb(level): 产生gdb格式的调试信息


-gstabs(level):产生stabs格式的调试信息,不包括GDB扩展.-->BSD.


 (level)-->默认级别为2


 0:不产生调试信息


 1:产生最少的调试信息


 3:包括额外的信息,包括在程序中出现的宏定义等.


 -gstabs+,-gcoff,-gxcoff,-gxcoff+,-gdwarf-version,-gvms


-c


  只激活预处理,编译和汇编,生成obj文件.还需要通过ld链接器对所有


  .o文件进行链接才能生成执行文件.


  -S


  只激活预处理和编译把文件汇编到汇编代码,相当于将程序生成.s文件.


  -E


  只进行预处理


  -o


  定制目标名称,缺省情况下生成a.out文件. gcc -ohello.exe test.c


  -D(macro)


  相当于#define  macro    1比如DDEBUG相当于将DEBUG的宏定义为1


  -C


  在预处理的时候不删除注释信息.


  -M


  生成文件的关联信息,就可以知道源代码依赖了那些头文件.


  -MM


  同上,忽略#include造成的依赖关系


  -MD


  和-M相当,但是输出导入到.d文件中. gcc -MDtest.c 输出依赖关系


  放在test.d文件里


  -MF file


  生成指定的默认依赖文件.


  -MMD


  和-MM相当,忽略#include造成的依赖关系


  -l(library)


  用于指定编译的时候使用的库. gcc-lgtk test.c 则程序使用gtk库进


  行编译.不过需要注意的是gcc库一般以lib(name).a来命名库文件,使用


  -l参数导入库文件的时候,直接使用-lname来引入,lib被省略.


  -L(dir)


  指定库文件所在的文件夹


  -T script


  指定空间分配文件




下面是编译 正点原子 stm32f103开发板的一个库函数版本的流水灯的例程的makefile,需要注意几点得是:


要把startup_stm32f10x_hd.s替换为gcc_ride7里面的startup_stm32f10x_hd.s,keil里面的汇编文件不能用于gcc


链接脚本文件也特别重要。要找能用于gcc下面的链接脚本根据需要修改。CSDN资源里有完整的编译通过的例子。把libc.a和libgcc.a拷贝出来放到工程的Lib文件夹里


#****************************************************************************
# Cross complie path
#****************************************************************************
PRJ := ${PWD}
GCC_PATH=c:\tools\arm2013.05
CROSS_COMPILE=$(GCC_PATH)\bin\arm-none-eabi-
CC     := $(CROSS_COMPILE)gcc
CXX    := $(CROSS_COMPILE)g++
AS   := $(CROSS_COMPILE)as
AR     := $(CROSS_COMPILE)ar rc
LD     := $(CROSS_COMPILE)ld
RANLIB := $(CROSS_COMPILE)ranlib
OBJDUMP:= $(CROSS_COMPILE)objdump
OBJCOPY:= $(CROSS_COMPILE)objcopy
STRIP  := $(CROSS_COMPILE)strip
BINARY = main
CFLAGS= -O0  -g -mcpu=cortex-m3 -mthumb -nostartfiles  -D STM32F10X_HD -D USE_STDPERIPH_DRIVER 
ASFLAG= -g -mcpu=cortex-m3 -mthumb 
LDSCRIPT = stm32f103VET6.ld
LDFLAGS =   -Llib -T $(LDSCRIPT) 
#****************************************************************************
# Targets of the build
#****************************************************************************
TARGET   := .\Output\A303_GJXF
all: prebuild $(TARGET).elf
SRC_C=$(shell gfind . -name "*.c")
SRC_S=$(shell gfind . -name "*.s")
OBJ_C=$(patsubst %.c, %.o, $(SRC_C))
OBJ_S=$(patsubst %.s, %.o, $(SRC_S))
OBJS := $(OBJ_C) $(OBJ_S)
#****************************************************************************
# Libs
#****************************************************************************
LIB_C         := $(GCC_PATH)\arm-none-eabi\lib\libc.a
LIB_GCC       := $(GCC_PATH)\lib\gcc\arm-none-eabi\4.7.3\libgcc.a
LIBS = $(LIB_C) $(LIB_GCC)
INCS = -I HARDWARE\LED -I SYSTEM\delay -I SYSTEM\sys -I SYSTEM\usart -I USER -I STM32F10x_FWLib\inc -I CORE  
# OBJS = stm32f10x_gpio.o stm32f10x_rcc.o isr.o
# OBJS += $(BINARY).o 
# OBJS += core_cm3.o
# OBJS += system_stm32f10x.o
#****************************************************************************
# TARGET
#****************************************************************************
prebuild:
@echo Building app...
$(TARGET).elf : $(OBJS) $(LIBS)
@echo (LD) $@: $^
-${LD}  -o $@ $^ ${LDFLAGS} 
@echo Generating bin...
@$(OBJCOPY) -O binary $(TARGET).elf $(TARGET).bin
@echo Generating hex...
@$(OBJCOPY) -O ihex $@ $(TARGET).hex
@echo Generating asm...
@$(OBJDUMP) -D -S $@ > $(TARGET).asm
@echo OK!
%.o : %.c
${CC} -c ${CFLAGS} ${INCS} -o $@ $<
%.o : %.s
$(AS) $(ASFLAG) -o $@ $<
clean:
@echo The following files:
rm  -f  $(TARGET) *.o
gfind . -name "*.[od]" |xargs rm
@echo Removed!
#====================end
/*
Default linker script for STM32F10x_1024K_1024K
Copyright RAISONANCE S.A.S. 2008
*/
/* include the common STM32F10x sub-script */
/* Common part of the linker scripts for STM32 devices*/
/* default stack sizes. 
These are used by the startup in order to allocate stacks for the different modes.
*/
__Stack_Size = 512 ;
PROVIDE ( _Stack_Size = __Stack_Size ) ;
__Stack_Init = _estack  - __Stack_Size ;
/*"PROVIDE" allows to easily override these values from an object file or the commmand line.*/
PROVIDE ( _Stack_Init = __Stack_Init ) ;
/*
There will be a link error if there is not this amount of RAM free at the end.
*/
_Minimum_Stack_Size = 0x100 ;
/* include the memory spaces definitions sub-script */
/*
Linker subscript for STM32F10x definitions with 1024K Flash and 1024K External SRAM */
/* Memory Spaces Definitions */
MEMORY
{
  RAM (xrw) : ORIGIN = 0x60000000, LENGTH = 512K
  FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 512K
  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
}
/* higher address of the user mode stack */
_estack = 0x60080000;
/* include the sections management sub-script for FLASH mode */
/* Sections Definitions */
SECTIONS
{
    /* for Cortex devices, the beginning of the startup code is stored in the .isr_vector section, which goes to FLASH */
    .isr_vector :
    {
        . = ALIGN(4);
        KEEP(*(.isr_vector))            /* Startup code */
        . = ALIGN(4);
    } >FLASH
    /* for some STRx devices, the beginning of the startup code is stored in the .flashtext section, which goes to FLASH */
    .flashtext :
    {
        . = ALIGN(4);
        *(.flashtext)            /* Startup code */
        . = ALIGN(4);
    } >FLASH
    /* the program code is stored in the .text section, which goes to Flash */
    .text :
    {
        . = ALIGN(4);
        *(.text)                   /* remaining code */
        *(.text.*)                   /* remaining code */
        *(.rodata)                 /* read-only data (constants) */
        *(.rodata*)
        *(.glue_7)
        *(.glue_7t)
        . = ALIGN(4);
         _etext = .;
        /* This is used by the startup in order to initialize the .data secion */
        _sidata = _etext;
    } >FLASH
    /* This is the initialized data section
    The program executes knowing that the data is in the RAM
    but the loader puts the initial values in the FLASH (inidata).
    It is one task of the startup to copy the initial values from FLASH to RAM. */
    .data  : AT ( _sidata )
    {
        . = ALIGN(4);
        /* This is used by the startup in order to initialize the .data secion */
        _sdata = . ;
        *(.data)
        *(.data.*)
        . = ALIGN(4);
        /* This is used by the startup in order to initialize the .data secion */
        _edata = . ;
    } >RAM
    /* This is the uninitialized data section */
    .bss :
    {
        . = ALIGN(4);
        /* This is used by the startup in order to initialize the .bss secion */
        _sbss = .;
        *(.bss)
        *(COMMON)
        . = ALIGN(4);
        /* This is used by the startup in order to initialize the .bss secion */
        _ebss = . ;
    } >RAM
    PROVIDE ( end = _ebss );
    PROVIDE ( _end = _ebss );
    /* This is the user stack section 
    This is just to check that there is enough RAM left for the User mode stack
    It should generate an error if it's full.
     */
    ._usrstack :
    {
        . = ALIGN(4);
        _susrstack = . ;
        . = . + _Minimum_Stack_Size ;
        . = ALIGN(4);
        _eusrstack = . ;
    } >RAM
    /* this is the FLASH Bank1 */
    /* the C or assembly source must explicitly place the code or data there
    using the "section" attribute */
    .b1text :
    {
        *(.b1text)                   /* remaining code */
        *(.b1rodata)                 /* read-only data (constants) */
        *(.b1rodata*)
    } >FLASHB1
    /* this is the EXTMEM */
    /* the C or assembly source must explicitly place the code or data there
    using the "section" attribute */
    /* EXTMEM Bank0 */
    .eb0text :
    {
        *(.eb0text)                   /* remaining code */
        *(.eb0rodata)                 /* read-only data (constants) */
        *(.eb0rodata*)
    } >EXTMEMB0
    /* EXTMEM Bank1 */
    .eb1text :
    {
        *(.eb1text)                   /* remaining code */
        *(.eb1rodata)                 /* read-only data (constants) */
        *(.eb1rodata*)
    } >EXTMEMB1
    /* EXTMEM Bank2 */
    .eb2text :
    {
        *(.eb2text)                   /* remaining code */
        *(.eb2rodata)                 /* read-only data (constants) */
        *(.eb2rodata*)
    } >EXTMEMB2
    /* EXTMEM Bank0 */
    .eb3text :
    {
        *(.eb3text)                   /* remaining code */
        *(.eb3rodata)                 /* read-only data (constants) */
        *(.eb3rodata*)
    } >EXTMEMB3
    /* after that it's only debugging information. */
    /* remove the debugging information from the standard libraries */
    DISCARD :
    {
     libc.a ( * )
     libm.a ( * )
     libgcc.a ( * )
     }
    /* Stabs debugging sections.  */
    .stab          0 : { *(.stab) }
    .stabstr       0 : { *(.stabstr) }
    .stab.excl     0 : { *(.stab.excl) }
    .stab.exclstr  0 : { *(.stab.exclstr) }
    .stab.index    0 : { *(.stab.index) }
    .stab.indexstr 0 : { *(.stab.indexstr) }
    .comment       0 : { *(.comment) }
    /* DWARF debug sections.
       Symbols in the DWARF debugging sections are relative to the beginning
       of the section so we begin them at 0.  */
    /* DWARF 1 */
    .debug          0 : { *(.debug) }
    .line           0 : { *(.line) }
    /* GNU DWARF 1 extensions */
    .debug_srcinfo  0 : { *(.debug_srcinfo) }
    .debug_sfnames  0 : { *(.debug_sfnames) }
    /* DWARF 1.1 and DWARF 2 */
    .debug_aranges  0 : { *(.debug_aranges) }
    .debug_pubnames 0 : { *(.debug_pubnames) }
    /* DWARF 2 */
    .debug_info     0 : { *(.debug_info .gnu.linkonce.wi.*) }
    .debug_abbrev   0 : { *(.debug_abbrev) }
    .debug_line     0 : { *(.debug_line) }
    .debug_frame    0 : { *(.debug_frame) }
    .debug_str      0 : { *(.debug_str) }
    .debug_loc      0 : { *(.debug_loc) }
    .debug_macinfo  0 : { *(.debug_macinfo) }
    /* SGI/MIPS DWARF 2 extensions */
    .debug_weaknames 0 : { *(.debug_weaknames) }
    .debug_funcnames 0 : { *(.debug_funcnames) }
    .debug_typenames 0 : { *(.debug_typenames) }
    .debug_varnames  0 : { *(.debug_varnames) }
}


参考文档:GCC参数详解

相关文章
|
2月前
|
C++ 芯片 编译器
STM32F103标准外设库—— 新建工程与库函数(四)
STM32F103标准外设库—— 新建工程与库函数(四)
44 0
STM32F103标准外设库—— 新建工程与库函数(四)
|
2月前
|
传感器 芯片 内存技术
STM32F103标准外设库——认识STM32(一)
STM32F103标准外设库——认识STM32(一)
109 0
STM32F103标准外设库——认识STM32(一)
|
2月前
|
芯片 存储 C语言
STM32F103标准外设库——固件库 (三)
STM32F103标准外设库——固件库 (三)
63 0
STM32F103标准外设库——固件库 (三)
|
7月前
|
存储 编译器 C语言
STM32开发 -- Keil基本使用
STM32开发 -- Keil基本使用
308 0
STM32CubeIDE移植ARM DSP库
STM32CubeIDE移植ARM DSP库
|
3月前
|
缓存 编译器 程序员
嵌入式开发环境Vscode开发STM32单片机程序
嵌入式开发环境Vscode开发STM32单片机程序
55 0
|
7月前
|
存储 芯片 内存技术
STM32F0单片机快速入门十 用 SPI HAL 库读写W25Q128
STM32F0单片机快速入门十 用 SPI HAL 库读写W25Q128
|
7月前
|
存储 内存技术
STM32F0单片机快速入门九 用 I2C HAL 库读写24C02
STM32F0单片机快速入门九 用 I2C HAL 库读写24C02
|
7月前
|
芯片
STM32F0单片机快速入门六 用库操作串口(UART)原来如此简单
STM32F0单片机快速入门六 用库操作串口(UART)原来如此简单
|
7月前
|
API 芯片
STM32 使用HAL库调试内部RTC经验总结
STM32 使用HAL库调试内部RTC经验总结
285 1