STM32 Development For Linux

独白:使用STM32也快三年了,最近正在从windows转移到linux下,系统装好后大致的环境和软件都调的差不多,接下来就是开发一类的工具转移,今天要吸血的是STM32,准备使用GCC编译、eclipse编写,依然使用官方的库。测试型号是STM32F103RC,我并不打算捣鼓一个最简洁的工程做测试一了了之,在这里我将我的平时整理的整个STM32的工程移过来。

1.1 安装GCC

1stm32 属于arm cortex-m系列thumb指令集,所以给arm用的arm-none-eabi就可以了,下载地址:

https://launchpad.net/gcc-arm-embedded/+download

下载其中的gcc-arm-none-eabi-version-linux.tar.bz2

解压到你知道的目录会产生 gcc-arm-none-eabi的文件夹

2、设置环境变量

把该编译器添加到你的环境中:

# sudo gedit  ~/.bashrc  最后一行添加

export PATH=$PATH:/your_stm_gcc_dir/gcc-arm-none-eabi-4_8-2013q4/bin  

3、测试

# arm-none-eabi-gcc -v  

 

1.2 建立工程

1、下载官方的库

2、将文件分类放在文件下,然后写makefile进行编译

 

1.3 Makefile解析

 makefile是所有的重点,由于我对makefile并不是很熟料,我在这里参考过很多github相关的makefile,在这里整理出一份我比较喜欢,简洁明了、通用性移植性强的:

注意使用官方库的时候,选择的启动文件不一样,keil的是arm编译,我们使用的gcc编译。

[cpp]  view plain  copy
  1. BUILDDIR = build  
  2. BINNAME = STM32F103forLinux  
  3. STM32FlashDIR =/home/jimy/work/sources/stm32flash/stm32flash  
  4. TTYUSB = /dev/ttyUSB0  
  5.   
  6. ELF = $(BUILDDIR)/$(BINNAME).elf  
  7. HEX = $(BUILDDIR)/$(BINNAME).hex  
  8. BIN = $(BUILDDIR)/$(BINNAME).bin  
  9.   
  10. TC = arm-none-eabi-  
  11. CC = $(TC)gcc  
  12. LD = $(TC)gcc  
  13. AR = $(TC)ar  
  14. OBJCOPY = $(TC)objcopy  
  15.   
  16. #----------Object dir----------#  
  17. STM32LIBS_DIR = stm32lib/STM32_USB-FS-Device_Lib_V4.0.0  
  18. USER_DIR = user  
  19. BSP_DIR = bsp  
  20. TEMP_DIR = temp  
  21. MYLIB_DIR = mylib  
  22. MODULE_DIR1 = module  
  23. MODULE_DIR2 = module/mpu_core_lib  
  24. MODULE_DIR3 = module/mpu_core_lib/include  
  25. MODULE_DIR4 = module/mpu_core_lib/mllite  
  26.   
  27. #----------Object .C file----------#  
  28. #wildcard:扩展通配符  
  29. SOURCES += $(STM32LIBS_DIR)/Libraries/CMSIS/Device/ST/STM32F10x/Source/Templates/system_stm32f10x.c  
  30. SOURCES += $(STM32LIBS_DIR)/Libraries/CMSIS/Device/ST/STM32F10x/Source/Templates/gcc_ride7/startup_stm32f10x_hd.s  
  31. SOURCES += $(wildcard $(STM32LIBS_DIR)/Libraries/STM32F10x_StdPeriph_Driver/src/*.c)  
  32. SOURCES += $(wildcard $(USER_DIR)/*.c)  
  33. SOURCES += $(wildcard $(BSP_DIR)/*.c)  
  34. SOURCES += $(wildcard $(TEMP_DIR)/*.c)  
  35. SOURCES += $(wildcard $(MYLIB_DIR)/*.c)  
  36. SOURCES += $(wildcard $(MODULE_DIR1)/*.c)  
  37. SOURCES += $(wildcard $(MODULE_DIR2)/*.c)  
  38. SOURCES += $(wildcard $(MODULE_DIR3)/*.c)  
  39. SOURCES += $(wildcard $(MODULE_DIR4)/*.c)  
  40.   
  41. #----------Object .O file----------#  
  42. #basename:去掉每个单词的前缀、后缀  
  43. #addsuffix:添加后缀,addprefix:添加前缀  
  44. OBJECTS = $(addprefix $(BUILDDIR)/, $(addsuffix .o, $(basename $(SOURCES))))  
  45.   
  46.   
  47. #----------Object .h file---------#  
  48. INCLUDES += -I$(STM32LIBS_DIR)/Libraries/CMSIS/Include \  
  49.         -I$(STM32LIBS_DIR)/Libraries/CMSIS/Device/ST/STM32F10x/Include \  
  50.         -I$(STM32LIBS_DIR)/Libraries/STM32F10x_StdPeriph_Driver/inc \  
  51.         -I$(USER_DIR) \  
  52.         -I$(BSP_DIR) \  
  53.         -I$(MYLIB_DIR) \  
  54.         -I$(TEMP_DIR) \  
  55.         -I$(MODULE_DIR1) \  
  56.         -I$(MODULE_DIR2) \  
  57.         -I$(MODULE_DIR3) \  
  58.         -I$(MODULE_DIR4) \  
  59.         -I$(MODULE_DIR2)/mpl  
  60.   
  61. #----------Object LD extern static lib file and dir----------#  
  62. LDLIBS += -lc -lgcc -lm  
  63. LDLIBS += -L $(MODULE_DIR2)/mpl  
  64. LDLIBS += -llibmplmpu  
  65.   
  66. #----------build Object .c to .O file----------#   
  67. CFLAGS  = -O0 -g -c -Wall -s -I. -mcpu=cortex-m3 -mthumb \  
  68.    $(INCLUDES) -DUSE_STDPERIPH_DRIVER -DSTM32F10X_HD   
  69.   
  70. #----------LD Objecd .O to elf file----------#  
  71. LDSCRIPT = link.lds  
  72. LDFLAGS += -T$(LDSCRIPT) -s -mthumb -mcpu=cortex-m3 -specs=nosys.specs $(LDLIBS)  
  73.   
  74.   
  75. #----------make start----------#  
  76. all : $(BIN) $(HEX)  
  77.   
  78. $(BIN): $(ELF)   
  79.     $(OBJCOPY) -O binary $< $@  
  80.   
  81. $(HEX): $(ELF)  
  82.     $(OBJCOPY) -O ihex $< $@  
  83.   
  84. $(ELF): $(OBJECTS)  
  85.     @echo "**********Linking...**********"  
  86.     $(LD) $(OBJECTS) $(LDFLAGS) -o $@  
  87.     @echo "*******Linking Finished!*******"  
  88.   
  89. $(BUILDDIR)/%.o: %.c  
  90.     mkdir -p $(dir $@)  
  91.     $(CC) -c $(CFLAGS) $< -o $@  
  92.   
  93. $(BUILDDIR)/%.o: %.s  
  94.     mkdir -p $(dir $@)  
  95.     $(CC) -c $(CFLAGS) $< -o $@  
  96.   
  97.   
  98. flash: $(HEX)  
  99.     sudo chmod +666 $(TTYUSB)  
  100.     $(STM32FlashDIR) -b 115200 -v -w ./$(HEX) $(TTYUSB)  
  101.   
  102. clean:  
  103.     rm -rf build  

1.4 gcc参数解析

编译过程:预处理-编译-汇编-链接

注:当静态库和动态库同名时, gcc命令将优先使用动态库。

注:链接库的参数不能放到-o参数后面,否则可能会报错。

下载列部分常用的gcc参数,makefile看不太懂的可以参考下面的参数列表

选项

含义

--help 
--target-help

显示 gcc 帮助说明。‘target-help’是显示目标机器特定的命令行选项。

--version

显示 gcc 版本号和版权信息 。

-o outfile

输出到指定的文件。

-xlanguage

指明使用的编程语言。允许的语言包括:c c++ assembler none 。 ‘none’意味着恢复默认行为,即根据文件的扩展名猜测源文件的语言。

-v

打印较多信息,显示编译器调用的程序。

-###

与 -v 类似,但选项被引号括住,并且不执行命令。

-E

仅作预处理,不进行编译、汇编和链接。如上图所示。

-S

仅编译到汇编语言,不进行汇编和链接。如上图所示。

-c

编译、汇编到目标代码,不进行链接。

-pipe

使用管道代替临时文件。

-combine

将多个源文件一次性传递给汇编器。


-l library(小写L)
-llibrary

进行链接时搜索名为library的库。
例子: $ gcc test.c -lm -o test

-Idir(大写i)

dir加入到搜索头文件的路径列表中。
例子: $ gcc test.c -I../inc -o test

-Ldir

dir加入到搜索库文件的路径列表中。
例子: $ gcc -I/home/foo -L/home/foo -ltest test.c -o test

-Dname

预定义一个名为name的宏,值为1
例子: $ gcc -DTEST_CONFIG test.c -o test

-Dname=definition

预定义名为name,值为definition的宏。

-ggdb 
-ggdblevel

为调试器 gdb 生成调试信息。level可以为123,默认值为2

-g 
-glevel

生成操作系统本地格式的调试信息。-g 和 -ggdb 并不太相同, -g 会生成 gdb 之外的信息。level取值同上。

-s

去除可执行文件中的符号表和重定位信息。用于减小可执行文件的大小。

-M

告诉预处理器输出一个适合make的规则,用于描述各目标文件的依赖关系。对于每个源文件,预处理器输出 一个make规则,该规则的目标项(target)是源文件对应的目标文件名,依赖项(dependency)是源文件中 `#include引用的所有文件。生成的规则可以是单行,但如果太长,就用`/'-换行符续成多行。规则 显示在标准输出,不产生预处理过的C程序。

-C

告诉预处理器不要丢弃注释。配合`-E'选项使用。

-P

告诉预处理器不要产生`#line'命令。配合`-E'选项使用。

-static

在支持动态链接的系统上,阻止连接共享库。该选项在其它系统上无效。

-nostdlib

不连接系统标准启动文件和标准库文件,只把指定的文件传递给连接器。

 

Warnings

 

-Wall

会打开一些很有用的警告选项,建议编译时加此选项。

-W 
-Wextra

打印一些额外的警告信息。

-w

禁止显示所有警告信息。

-Wshadow

当一个局部变量遮盖住了另一个局部变量,或者全局变量时,给出警告。很有用的选项,建议打开。 -Wall 并不会打开此项。

-Wpointer-arith

对函数指针或者void *类型的指针进行算术操作时给出警告。也很有用。 -Wall 并不会打开此项。

-Wcast-qual

当强制转化丢掉了类型修饰符时给出警告。 -Wall 并不会打开此项。

-Waggregate-return

如果定义或调用了返回结构体或联合体的函数,编译器就发出警告。

-Winline

无论是声明为 inline 或者是指定了-finline-functions 选项,如果某函数不能内联,编译器都将发出警告。如果你的代码含有很多 inline 函数的话,这是很有用的选项。

-Werror

把警告当作错误。出现任何警告就放弃编译。

-Wunreachable-code

如果编译器探测到永远不会执行到的代码,就给出警告。也是比较有用的选项。

-Wcast-align

一旦某个指针类型强制转换导致目标所需的地址对齐增加时,编译器就发出警告。

-Wundef

当一个没有定义的符号出现在 #if 中时,给出警告。

-Wredundant-decls

如果在同一个可见域内某定义多次声明,编译器就发出警告,即使这些重复声明有效并且毫无差别。

 

Optimization

 

-O0

禁止编译器进行优化。默认为此项。

-O 
-O1

尝试优化编译时间和可执行文件大小。

-O2

更多的优化,会尝试几乎全部的优化功能,但不会进行“空间换时间”的优化方法。

-O3

在 -O2 的基础上再打开一些优化选项:-finline-functions, -funswitch-loops 和 -fgcse-after-reload 

-Os

对生成文件大小进行优化。它会打开 -O2 开的全部选项,除了会那些增加文件大小的。

-finline-functions

把所有简单的函数内联进调用者。编译器会探索式地决定哪些函数足够简单,值得做这种内联。

-fstrict-aliasing

施加最强的别名规则(aliasing rules)。

 

ARM

 

-mthumb

指令集

-mcpu=cortex-m3

 

-T

指定链接文件

  
  


1.5 ld链接文件解析

主要设置系统flash/arm的起始地址和大小,还有堆栈的结束地址

这个也是跟keil有所不一样的,keil使用的是链接文件和启动文件时一起的,但是在makefile使用gcc编译时,启动文件时是定义向量并初始化,并没有定义堆栈的大小和地址等,而是在链接文件中定义,这里主要声明了堆栈的地址、flash和ram的大小,其他的相对并不太需要修改。

[cpp]  view plain  copy
  1. /* 
  2. ***************************************************************************** 
  3. ** 
  4. ** File : stm32_flash.ld 
  5. ** 
  6. ** Abstract : Linker script for STM32F103ZE Device with 
  7. ** 512KByte FLASH, 64KByte RAM 
  8. ***************************************************************************** 
  9. */  
  10.   
  11. /* Entry Point */  
  12. ENTRY(Reset_Handler)  
  13.   
  14. /* Highest address of the user mode stack */  
  15. _estack = 0x20010000; /* end of 64K RAM */  
  16.   
  17. /* Generate a link error if heap and stack don't fit into RAM */  
  18. _Min_Heap_Size = 0; /* required amount of heap */  
  19. _Min_Stack_Size = 0x200; /* required amount of stack */  
  20.   
  21. /* Specify the memory areas */  
  22. MEMORY  
  23. {  
  24.   FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 512K  
  25.   RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K  
  26.   MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K  
  27. }  
  28.   
  29. /* Define output sections */  
  30. SECTIONS  
  31. {  
  32.   /* The startup code goes first into FLASH */  
  33.   .isr_vector :  
  34.   {  
  35.     . = ALIGN(4);  
  36.     KEEP(*(.isr_vector)) /* Startup code */  
  37.     . = ALIGN(4);  
  38.   } >FLASH  
  39.   
  40.   /* The program code and other data goes into FLASH */  
  41.   .text :  
  42.   {  
  43.     . = ALIGN(4);  
  44.     *(.text) /* .text sections (code) */  
  45.     *(.text*) /* .text* sections (code) */  
  46.     *(.rodata) /* .rodata sections (constants, strings, etc.) */  
  47.     *(.rodata*) /* .rodata* sections (constants, strings, etc.) */  
  48.     *(.glue_7) /* glue arm to thumb code */  
  49.     *(.glue_7t) /* glue thumb to arm code */  
  50.   
  51.     KEEP (*(.init))  
  52.     KEEP (*(.fini))  
  53.   
  54.     . = ALIGN(4);  
  55.     _etext = .; /* define a global symbols at end of code */  
  56.   } >FLASH  
  57.   
  58.   
  59.    .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH  
  60.     .ARM : {  
  61.     __exidx_start = .;  
  62.       *(.ARM.exidx*)  
  63.       __exidx_end = .;  
  64.     } >FLASH  
  65.   
  66.   .ARM.attributes : { *(.ARM.attributes) } > FLASH  
  67.   
  68.   .preinit_array :  
  69.   {  
  70.     PROVIDE_HIDDEN (__preinit_array_start = .);  
  71.     KEEP (*(.preinit_array*))  
  72.     PROVIDE_HIDDEN (__preinit_array_end = .);  
  73.   } >FLASH  
  74.   .init_array :  
  75.   {  
  76.     PROVIDE_HIDDEN (__init_array_start = .);  
  77.     KEEP (*(SORT(.init_array.*)))  
  78.     KEEP (*(.init_array*))  
  79.     PROVIDE_HIDDEN (__init_array_end = .);  
  80.   } >FLASH  
  81.   .fini_array :  
  82.   {  
  83.     PROVIDE_HIDDEN (__fini_array_start = .);  
  84.     KEEP (*(.fini_array*))  
  85.     KEEP (*(SORT(.fini_array.*)))  
  86.     PROVIDE_HIDDEN (__fini_array_end = .);  
  87.   } >FLASH  
  88.   
  89.   /* used by the startup to initialize data */  
  90.   _sidata = .;  
  91.   
  92.   /* Initialized data sections goes into RAM, load LMA copy after code */  
  93.   .data : AT ( _sidata )  
  94.   {  
  95.     . = ALIGN(4);  
  96.     _sdata = .; /* create a global symbol at data start */  
  97.     *(.data) /* .data sections */  
  98.     *(.data*) /* .data* sections */  
  99.   
  100.     . = ALIGN(4);  
  101.     _edata = .; /* define a global symbol at data end */  
  102.   } >RAM  
  103.   
  104.   /* Uninitialized data section */  
  105.   . = ALIGN(4);  
  106.   .bss :  
  107.   {  
  108.     /* This is used by the startup in order to initialize the .bss secion */  
  109.     _sbss = .; /* define a global symbol at bss start */  
  110.     __bss_start__ = _sbss;  
  111.     *(.bss)  
  112.     *(.bss*)  
  113.     *(COMMON)  
  114.   
  115.     . = ALIGN(4);  
  116.     _ebss = .; /* define a global symbol at bss end */  
  117.     __bss_end__ = _ebss;  
  118.   } >RAM  
  119.   
  120.   PROVIDE ( end = _ebss );  
  121.   PROVIDE ( _end = _ebss );  
  122.   
  123.   /* User_heap_stack section, used to check that there is enough RAM left */  
  124.   ._user_heap_stack :  
  125.   {  
  126.     . = ALIGN(4);  
  127.     . = . + _Min_Heap_Size;  
  128.     . = . + _Min_Stack_Size;  
  129.     . = ALIGN(4);  
  130.   } >RAM  
  131.   
  132.   /* MEMORY_bank1 section, code must be located here explicitly */  
  133.   /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */  
  134.   .memory_b1_text :  
  135.   {  
  136.     *(.mb1text) /* .mb1text sections (code) */  
  137.     *(.mb1text*) /* .mb1text* sections (code) */  
  138.     *(.mb1rodata) /* read-only data (constants) */  
  139.     *(.mb1rodata*)  
  140.   } >MEMORY_B1  
  141.   
  142.   /* Remove information from the standard libraries */  
  143.   /DISCARD/ :  
  144.   {  
  145.     libc.a ( * )  
  146.     libm.a ( * )  
  147.     libgcc.a ( * )  
  148.   }  
  149. }  

1.6 串口下载程序

1、stm32flash

https://sourceforge.net/p/stm32flash/wiki/Home/

https://github.com/ARMinARM/stm32flash

下载之后make编译,插上串口,设置一下usb的权限为666,即可使用串口下载程序。

下载是github的简单使用说明:

[cpp]  view plain  copy
  1. Usage: ./stm32flash [-bvngfhc] [-[rw] filename] /dev/ttyS0  
  2.         -b rate         Baud rate (default 57600)  
  3.         -r filename     Read flash to file  
  4.         -w filename     Write flash to file  
  5.         -u              Disable the flash write-protection  
  6.         -e n            Only erase n pages before writing the flash  
  7.         -v              Verify writes  
  8.         -n count        Retry failed writes up to count times (default 10)  
  9.         -g address      Start execution at specified address (0 = flash start)  
  10.         -s start_page   Flash at specified page (0 = flash start)  
  11.         -f              Force binary parser  
  12.         -h              Show this help  
  13.         -c              Resume the connection (don't send initial INIT)  
  14.                         *Baud rate must be kept the same as the first init*  
  15.                         This is useful if the reset fails  


好了,eclipse的安装比较单一,在这里就不详述了,到此搞定。但是发现有一些问题:

1、gcc编译出来的目标文件在同等优化等级的情况下会大%30左右,这个很让然头痛。

2、在使用优化的时候发现以前在keil下写的一些代码出现了bug,特别是关于Volatile的疏忽,才发现keil是会自动完善这些代码bug,这里是小弟写的代码风格不严谨,惭愧惭愧。

3、flash下载的速度实在跟stlink等工具没法比,下载得据需搞搞stlink的下载才行。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值