使用Eclipse IDE for GNU ARM搭建STM32的開發環境


01:下載必要的文件

1.1 安裝java運行環境,這一步比較簡單,就不細說了。

1.2 需要下載四個文件gnumcueclipse、gcc-arm-none-eabi、xpack-windows-build-tools、jlink


gnumcueclipse:是在Eclipse + CDT的基礎上集成了Arm和RISC-V處理器開發的插件(GNU MCU Eclipse),對STM32F0、STM32F1、STM32F2等支持比較完善,official site在這里:https://eclipse-embed-cdt.github.io/

gcc-arm-none-eabi:這個沒啥好說的,gcc arm工具鏈。

xpack-windows-build-tools:windows下的make工具,如果需要使用linux下的make,需要安裝cygwin或者mysys2虛擬環境。

jlink:這個不是必須的,對於STM32如果你沒有jlink的話,也可以使用flymcu這類工具從串口1下載程序,或者使用DAP Link這類開源的調試器。

以上需要的文件已存至天翼雲盤(下載不限速),有需要的可直接下載:https://cloud.189.cn/t/RvaqQnrYBnaq (訪問碼:fu2a)。

02:軟件安裝

2.1 這一步比較簡單,這三個都是綠色軟件,直接解壓到想要存放的路徑即可,如果想要在任意地方使用make和arm-none-eabi-gcc還可以把他倆安裝目錄的bin文件夾添加到path。
!!! 添加環境變量不是必須的,因為即使配置了PATH,Eclipse里面還是需要再配置一遍。!!!


如果添加了環境變量,可以使用make和arm gcc的 --version輸出下版本信息,以判斷是否成功添加。


2.2 eclipse安裝完成后,還可以根據自己的電腦配置修改下啟動配置文件“eclipse.ini”(以下是8G內存的配置參數,僅供參考),如果對java虛擬機不了解的話也可以跳過這一步。

-Xms1024m
-Xmx2048m
-XX:PermSize=256m
-XX:MaxPermSize=256m
-Xverify:none

2.3 eclipse的基本配置,這一步是將步驟(2.1),安裝的編譯工具配置到eclipse,
選擇Window -> Preference打開eclipse的設置窗口。


切換到MCU列表,對帶有全局(Global)屬性的配置項目進行修改。
在ARM Toolchains Paths中,Default toolchain可以選擇任意的,前提是下回創建工程時需要選擇被配置的那個,
因此為了方便可以配置下拉列表的第一個,“GNU MCU Eclipse ARM Enbedded GCC”。
Toolchain name 無法修改,保持默認即可。
Toolchain folder 設置到arm-gcc安裝目錄的bin文件夾。


切換至Global Build Tools Path,此處填入make工具安裝路徑下的bin文件夾。


如果安裝了jlink,還可以配置下jlink gdb路徑,切換至 Global SEGGER J-Link Path,在Executable中填入JLinkGDBServerCL.exe,在Folder中填入你的jlink安裝路徑。

03:建立項目

3.1 打開eclipse,選擇File -> new -> C/C++ Project -> C Managed Build,如果想使用C++開發的話,也可以選擇下面一行的C++ Managed Build,
(但是需要考慮的是這個C++標准支持的不是很全,且生成的二進制文件較大),然后點擊Next即可進入工程建立界面。



3.2 這里是對工程的基本信息進行配置,例如工程名稱,保存路徑,模板代碼等。
Project name:可以按照需求填寫;
Location:可以選擇default location(即設置的工作區文件夾)或者自定義的路徑;
Project type:該列表下有很多ST系列MCU的模板代碼,可以按照自己的設備平台選擇,這里指定了平台后,會有對應的STD庫或者HAL庫被自動添加;
Toolchains:這里使用ARM Cross GCC交叉編譯器即可,然后點擊NEXT


3.3 對芯片配置進行修改。
Chip family 選擇所使用的芯片系列即可。
Flash size(KB) 芯片的Flash容量,這后期在里根據芯片設置,如果不清楚可以任意寫,ldscript中還是可以修改的。
RAM size(KB) 芯片的RAM大小,同上。
Clock(Hz): 有晶振的填HSE時鍾,沒晶振的填HSI時鍾,該配置實際上沒啥卵用,在STM32的初始化文件system_stm32f0xx.c中可以修改,即使在此處配置了,也不會同步更新到模板代碼中。
Content:提供了Blinky 和Empty兩個demo,一個是閃燈程序,另一個則是空項目,第一次開始可以選擇Blinky熟悉下工程結構。
Use system calls: 這里是標准庫的系統調用,主要為stdin stdout標准輸入/輸出流服務,如果需要在eclipse console中打印log,可以選擇Semihosting;如果習慣使用Jlink RTT也可以選擇POSIX或者Freestanding。
Trace output:如果在Use system calls中沒有選擇Semihosting,這一部分的修改是不生效的,前一步選擇了Semihosting后這里可以選擇STDOUT和DEBUG通道,功能上二者沒有區別(一個是RUN的輸出,另一個是DEBUG的輸出)。
下面的勾選框中,可以把Enable -Werror去除,因為ST的標准庫有些編碼不規范的地方,去除Werror避免編譯報錯。


點擊NEXT后可以對項目的文件夾名稱進行修改,這里也可以使用默認的。


再次點擊NEXT后可以選擇創建的版本,一般而言會有debug和release兩個版本,同時勾選Debug和release會創建一條宏定義,用以切換代碼版本,這里只選個release即可。


接下來選擇arm工具鏈,使用之前配置好的,最后點擊Finish即可創建工程。

04:修改項目

4.1 打開main.c,屏蔽掉trace_puts、puts、fprintf、trace_printf打印函數。



4.2 修改連接腳本,打開ldscripts/mem.ld,在MEMORY中僅保留RAM和FLASH(根據你的芯片決定)

4.3 打開sections.ld,刪除SECTIONS中之前在MEMORY中移除的段,堆棧大小也可以在此修改。

__stack = ORIGIN(RAM) + LENGTH(RAM);

_estack = __stack; 	

__Main_Stack_Size = 1024 ;

PROVIDE ( _Main_Stack_Size = __Main_Stack_Size ) ;

__Main_Stack_Limit = __stack  - __Main_Stack_Size ;

PROVIDE ( _Main_Stack_Limit = __Main_Stack_Limit ) ;

_Minimum_Stack_Size = 256 ;

PROVIDE ( _Heap_Begin = _end_noinit ) ;
PROVIDE ( _Heap_Limit = __stack - __Main_Stack_Size ) ;

ENTRY(_start)

SECTIONS
{
    .isr_vector : ALIGN(4)
    {
        FILL(0xFF)

        __vectors_start = ABSOLUTE(.) ;
        __vectors_start__ = ABSOLUTE(.) ; /* STM specific definition */
        KEEP(*(.isr_vector))     	/* Interrupt vectors */
          
        *(.after_vectors .after_vectors.*)	/* Startup code and ISR */
    } >FLASH

    .inits : ALIGN(4)
    {
        __data_regions_array_start = .;
        
        LONG(LOADADDR(.data));
        LONG(ADDR(.data));
        LONG(ADDR(.data)+SIZEOF(.data));

        __data_regions_array_end = .;
        
        __bss_regions_array_start = .;
        
        LONG(ADDR(.bss));
        LONG(ADDR(.bss)+SIZEOF(.bss));
        
        
        __bss_regions_array_end = .;

		KEEP(*(.init))
		KEEP(*(.fini))

		. = ALIGN(4);


		PROVIDE_HIDDEN (__preinit_array_start = .);
        
		KEEP(*(.preinit_array_sysinit .preinit_array_sysinit.*))

		KEEP(*(.preinit_array_platform .preinit_array_platform.*))
        
		KEEP(*(.preinit_array .preinit_array.*))

		PROVIDE_HIDDEN (__preinit_array_end = .);

		. = ALIGN(4);

		PROVIDE_HIDDEN (__init_array_start = .);
		KEEP(*(SORT(.init_array.*)))
		KEEP(*(.init_array))
		PROVIDE_HIDDEN (__init_array_end = .);

		. = ALIGN(4);

		PROVIDE_HIDDEN (__fini_array_start = .);
		KEEP(*(SORT(.fini_array.*)))
		KEEP(*(.fini_array))
		PROVIDE_HIDDEN (__fini_array_end = .);

    } >FLASH

    .text : ALIGN(4)
    {
        *(.text .text.*)			
 
        *(.rodata .rodata.* .constdata .constdata.*) 		

        *(vtable)					/* C++ virtual tables */

            KEEP(*(.eh_frame*))


        *(.glue_7)
        *(.glue_7t)

    } >FLASH


	.ARM.extab : ALIGN(4)
   	{
       *(.ARM.extab* .gnu.linkonce.armextab.*)
   	} > FLASH
   	
    . = ALIGN(4);
   	__exidx_start = .;   	
   	.ARM.exidx : ALIGN(4)
   	{
       *(.ARM.exidx* .gnu.linkonce.armexidx.*)
   	} > FLASH
   	__exidx_end = .;
   	
    . = ALIGN(4);
    _etext = .;
    __etext = .;
    
    _sidata = LOADADDR(.data);

    .data : ALIGN(4)
    {
    	FILL(0xFF)

        _sdata = . ;        	/* STM specific definition */
        __data_start__ = . ;
		*(.data_begin .data_begin.*)

		*(.data .data.*)
		
		*(.data_end .data_end.*)
	    . = ALIGN(4);

        _edata = . ;        	/* STM specific definition */
        __data_end__ = . ;

    } >RAM AT>FLASH

    .bss (NOLOAD) : ALIGN(4)
    {
        __bss_start__ = .;     	/* standard newlib definition */
        _sbss = .;              /* STM specific definition */
        *(.bss_begin .bss_begin.*)

        *(.bss .bss.*)
        *(COMMON)
        
        *(.bss_end .bss_end.*)
	    . = ALIGN(4);
        __bss_end__ = .;        /* standard newlib definition */
        _ebss = . ;             /* STM specific definition */
    } >RAM
    
    .noinit (NOLOAD) : ALIGN(4)
    {
        _noinit = .;
        
        *(.noinit .noinit.*) 
        
         . = ALIGN(4) ;
        _end_noinit = .;   
    } > RAM
    
    PROVIDE ( end = _end_noinit ); /* was _ebss */
    PROVIDE ( _end = _end_noinit );
    PROVIDE ( __end = _end_noinit );
    PROVIDE ( __end__ = _end_noinit );
    
    ._check_stack : ALIGN(4)
    {
        . = . + _Minimum_Stack_Size ;
    } >RAM

    /* 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) }
} 

4.4 編譯前的相關配置,點擊下Project Explorer中的項目名稱,在Project -> Properties -> C/C++ Build Settings中做出如下配置:


在Create Flash Image中可以選擇輸出Hex或者bin文件。


在C/C++ Build -> Behavior 中將並行編譯打開(鏈接還是單線程的),這樣可以提高編譯速度,一般項目配合8線程處理器,4~5秒即可完成。


以上配置完成后,基本可以進行編譯了(makefile由eclipse根據配置自動生成),編譯完成后有可執行文件各個段的占用空間信息。

05:程序下載





06:基於標准庫(StdPeriph_Lib)(HAL庫也同樣適用)建立工程

6.1 一些准備工作。
基於標准庫在eclipse下建立項目需要STM32F0xx_StdPeriph_Lib_V1.5.0 1.zip,
沒有的話可以在這里下載,鏈接:https://cloud.189.cn/t/RvaqQnrYBnaq (訪問碼:fu2a)。


解壓后的目錄應該與下圖一致


6.2 eclipse創建項目
打開eclipse,選擇File -> new -> Project...


這里以c語言工程為例,選擇C Project,然后點擊Next。


第一步:在“Project name”中輸入項目的名稱;第二步:在“Toolchains”選擇合適的編譯工具,這里選擇ARM Cross GCC
第三步:在“Project type”中選擇Hello World ARM C Project;第四步:點擊Next進入下一步驟。(這里需要注意的是一定要先選擇Toolchains,再選擇Project type,否則下面的Finish按鈕到后面的最后一步時還是不可用的灰色)


基本設置,把“Linker semi-hosting options”清空(這里不使用semihosting提供的stdin stdout重定向(且hello world工程也缺少相關文件),如需打印log可以使用RTT或者串口),其他的默認即可,點擊Next進入下一步驟。


項目分支設置,可配置debug和release,二者在編譯/生成bin文件無明顯差別(在makefile中通過if DEBUG指定優化等級),這里我僅勾選Release,實際中可根據需要決定。


最后看下編譯工具鏈路徑是否正確,如果OK,那么下面的Finish按鈕就變成可點擊狀態,點擊Finish即可。


主界面左側出現項目樹,並且main.c如下所示,那么基本的項目框架就有了,下面就是一些簡單的參數配置。


新建startup文件夾,復制STM32F0xx_StdPeriph_Lib_V1.5.01庫中的啟動文件進去,具體的路徑如下(以STM32F072系列的MCU為例),同時將startup_stm32f072.s的后綴名改成大寫的S,變成startup_stm32f072.S:
\Libraries\CMSIS\Device\ST\STM32F0xx\Source\Templates\gcc_ride7\startup_stm32f072.s

需要改成大寫.S的原因在這里window -> preference -> c/c++ ->file types,eclipse默認的file types只有大寫的.S文件作為匯編文件類型,但你也可以點擊“new”,新建一個小寫.s的匯編文件類型。


新建ldscript文件夾,復制STM32F0xx_StdPeriph_Lib_V1.5.01庫中的鏈接腳本進去,具體的路徑如下(以STM32F072系列的MCU為例):
\Projects\STM32F0xx_StdPeriph_Templates\TrueSTUDIO\STM32F072\STM32F072VB_FLASH.ld


在項目下新建include文件夾。

添加初始化代碼和必要的外設支持庫,在src目錄新建cmsis文件夾,復制system_stm32f0xx.c進入,該文件在std庫中的路徑:\Projects\STM32F0xx_StdPeriph_Templates\system_stm32f0xx.c。
在include目錄下新建cmsis文件夾,復制以下文件進入:
core_cm0.h 源路徑\Libraries\CMSIS\Include\core_cm0.h
stm32f0xx.h 源路徑\Libraries\CMSIS\Device\ST\STM32F0xx\Include\stm32f0xx.h
system_stm32f0xx.h 源路徑\Libraries\CMSIS\Device\ST\STM32F0xx\Include\stm32f0xx.h\system_stm32f0xx.h
stm32f0xx_conf.h 源路徑\Projects\STM32F0xx_StdPeriph_Templates\stm32f0xx_conf.h 這個文件也可以不加,自己在項目中按需include也很好。
以下兩個文件有部分修改,以網盤鏈接形式提供,鏈接:https://cloud.189.cn/t/RvaqQnrYBnaq (訪問碼:fu2a)。
arm_asm.h
cmsis_gcc.h

在src目錄創建stm32f0-stdperiph文件夾,復制標准庫中\Libraries\STM32F0xx_StdPeriph_Driver\src下所有.c文件進入。
在include目錄創建stm32f0-stdperiph文件夾,復制標准庫中\Libraries\STM32F0xx_StdPeriph_Driver\inc下所有.h文件進入。
添加一些日志輸出的組件,以便打印“Hello World”,這里我使用了SEGGER RTT,最終的項目結構如下圖所示。


從上一步的項目樹可以看到一些打紅色叉的警告信息,這就需要修改include path等配置項以消除這些錯誤。
點擊左側項目樹的項目名稱,保證選中當前項目,選擇Project -> Properties


在Resource中,將Text file encoding改成Other:UTF-8,點擊右下角Apply,如果之前配置過全局編碼,這一步可以省略。(每一步驟完成或頁面切換時,建議點擊右下角的Apply保存配置項)


在C/C++ Build -> Behavior -> Build settings中,勾選Enable parallel build 選擇Use paralleljobs,使用並行編譯。


同時也需要留意Configuration選擇為需要被配置的項目,由於先前僅創建了Release,因此這里只有一個選項。

Logging -> Enable build logging 可以關掉,沒啥用處。


接下來是關於MCU ARM核基本信息設置,這里比較重要,不能選擇“Toolchain default”;如果不清楚需要查詢自己所用芯片的手冊,這里以stm32f072為例,cortex m0的arm核心,架構armv6-m,只支持thumb/2指令集,不支持非對其訪問;那么
C/C++ Build -> Settings Tool Settings -> Target Processor 需要按如下參數配置。


如果跳出需要重新編譯工程的對話框,選擇“NO”即可,因為沒配置完成,編譯也會有很多Error或Warning。


C/C++ Build -> Settings Tool Settings -> Optimization 為一些優化選項,可以按照需求配置,


C/C++ Build -> Settings Tool Settings -> Warnings 為一些編譯警告,推薦設置如下圖:


C/C++ Build -> Settings Tool Settings -> Debuging 是一些調試信息,只會存在於elf文件中,objcpy后的bin文件是沒有這些信息的,使用jlink的話,Debug format選擇gdb即可,Debug level選項下的區別可以自行網絡查找,我這里就不使用debug信息了。


C/C++ Build -> Settings Tool Settings -> GNU ARM Cross Assember 匯編選項全部保持默認即可。


C/C++ Build -> Settings Tool Settings ->GNU ARM Cross C Compiler -> Preprocessor 添加必要的宏定義

STM32F072
USE_STDPERIPH_DRIVER
HSE_VALUE=16000000

這三個宏定義都在stm32f0xx.h是被使用,其中'STM32F072'是必須的,另外兩個可選。


C/C++ Build -> Settings Tool Settings ->GNU ARM Cross C Compiler -> Includes 添加include path


這里也可以使用相對路徑。


C/C++ Build -> Settings Tool Settings ->GNU ARM Cross C Compiler -> Optimization 語言標准選擇c99或者c11都可以,在gnu編譯器里,選擇gnu99或gnu11


C/C++ Build -> Settings Tool Settings ->GNU ARM Cross C Compiler -> warnings 這三個建議打開,編譯時的warning可能會在運行時變成error,有必要提前處理。


C/C++ Build -> Settings Tool Settings ->GNU ARM Cross C Linker -> General
Script files 添加先前復制進項目的STM32F072VB_FLASH.ld文件,只需輸入文件名即可。
鏈接選項 -nostartfiles -Xlinker --gc-sections也需要勾選下。


C/C++ Build -> Settings Tool Settings ->GNU ARM Cross C Linker -> Libraries
只需要修改 Library search path,設置之前新建的ldscript文件夾,使用相對路徑"../ldscript"或者eclispe定義的宏${workspace_loc:/${ProjName}/ldscript}都可,Libraries欄下其他項目保持默認。


C/C++ Build -> Settings Tool Settings ->GNU ARM Cross C Compiler -> Miscellaneous
勾選newlib-nano


C/C++ Build -> Settings Tool Settings ->GNU ARM Cross Create Flash Image -> General
這里可以選擇生成bin文件orhex文件,我這里使用bin文件。(jlink下載時使用的是elf文件,因此這里選擇bin文件或hex文件取決於其他燒寫工具的要求), C/C++ Build欄的修改就此完成了,其他的保持默認即可。


C/C++ General -> Paths and Symbols -> Source Location
點擊Add Folder,把我們的啟動文件所在的文件夾也添加進來。

可以添加.c文件編譯的過濾器,可以屏蔽掉當前用不到的c文件,增加編譯速度。

按照如下步驟點擊鼠標

選擇需要屏蔽的文件,對於Hello World工程來說,用不到外設庫,可以全部屏蔽(以后用到需要到這里解除過濾)。

最后保存即可,可以看到Includes增加了我們自定義的路徑,src目錄下紅色的叉也消失了(如果未消失,可按F5刷新)。


最后點擊Project -> Build Project

可以看出,開啟並行編譯后速度飛快。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM