MAC OS X平臺搭建STM32開發環境

      本人主要用MAC作開發,其實MAC平臺只要不是用來開發Windows或者是嵌入式的話,作其餘任何開發都比較舒服,至少我認爲比在windows上要舒服的多。可是坑爹的事情也有,就是若是作嵌入式開發就比較蛋疼了。沒辦法,蛋疼歸蛋疼,該作的也仍是要作的。html

    本人手頭上有一塊STM32F103VET6的開發板,若是在windows下,那麼輕鬆愉快,裝個KeilMDK或者IAR for ARM就搞定了。可是在Mac OS X以及Linux下,就要用Makefile來管理開發了,這些平臺上可沒有很是方便的IDE供咱們來選擇。shell

    好了,廢話很少說,下面就進入正題。windows

1、準備工做bash

    至少要準備如下軟件,XCode,arm-none-eabi-gcc以及J-Link for MAC。我用的軟件版本以下:網絡

    XCode6.x  (AppStore 直接安裝就行了)app

    gcc-arm-none-eabi-4_8-2014q3-20140805-mac.tar (VeryARM上下載,各個平臺都有)electron

    JLink_MacOSX_V500k.pkg   (https://www.segger.com/jlink-software.html 這個地方能夠下載)ide

2、環境配置工具

    好了,安裝包都準備好了吧?先將gcc-arm-none-eabixxx這個包解壓到你自已方便的位置,並在.bash_profile中添加以下環境變量:ui

export PATH=$PATH:$(ARM-TOOLS-ROOT)/bin

其中$(ARM-TOOLS-ROOT)表明工具鏈解壓以後的根目錄,請用絕對路徑而且路徑名不要包含空格。完成以後在shell上執行以下指令使得以上設置的環境變量有效:

 

$ source .bash_profile

完成以後能夠在shell中執行以下命令查看時候安裝成功:

 

$ arm-none-eabi-gcc -v

若是安裝成功,此時會再shell中打印出一堆的gcc的版本信息,若是失敗,應該會打印此命令找不到之類的信息,那麼確定是環境變量設置出錯。

    此時編譯工具鏈已經安裝完成,那麼再將JLink驅動裝上就行了,這個與通常的其餘軟件安裝過程同樣。若是安裝成功,應該會在/usr/bin下面找到JLinkExe,JFlashSPI等等可執行文件的。

3、代碼示例

    本人使用代碼目錄結構以下圖:

       這裏主要貼一下Makefile,這些Makefile也是在網上參考了其餘人並通過加工而成。主要的Makefile有三個,

Makefile.common這個是公共配置文件,STM32目錄下得Makefile以及libs下得Makefile。

一、Makefile.common

 

# include Makefile  
  
#This file is included in the general Makefile, the libs Makefile and the src Makefile  
#Different optimize settings for library and source files can be realized by using arguments  
#Compiler optimize settings:  
# -O0 no optimize, reduce compilation time and make debugging produce the expected results (default).  
# -O1 optimize, reduce code size and execution time, without much increase of compilation time.  
# -O2 optimize, reduce code execution time compared to ‘O1’, increase of compilation time.  
# -O3 optimize, turns on all optimizations, further increase of compilation time.  
# -Os optimize for size, enables all ‘-O2’ optimizations that do not typically increase code size and other code size optimizations.  
#Recommended optimize settings for release version: -O3  
#Recommended optimize settings for debug version: -O0  
#Valid parameters :  
# OptLIB=0 --> optimize library files using the -O0 setting  
# OptLIB=1 --> optimize library files using the -O1 setting  
# OptLIB=2 --> optimize library files using the -O2 setting  
# OptLIB=3 --> optimize library files using the -O3 setting  
# OptLIB=s --> optimize library files using the -Os setting  
# OptSRC=0 --> optimize source files using the -O0 setting  
# OptSRC=1 --> optimize source files using the -O1 setting  
# OptSRC=2 --> optimize source files using the -O2 setting  
# OptSRC=3 --> optimize source files using the -O3 setting  
# OptSRC=s --> optimize source files using the -Os setting  
# all --> build all  
# libs --> build libs only  
# src --> build src only  
# clean --> clean project  
# tshow --> show optimize settings  
#Example:  
# make OptLIB=3 OptSRC=0 all tshow  
  
#TOP=$(shell readlink -f "$(dir $(lastword $(MAKEFILE_LIST)))")  
TOP			= /Users/zhj/Developer/STM32
PROGRAM		= stm32_project
LIBDIR		= $(TOP)/libs

#Adust the following line to the library in use   
STMLIB		= $(LIBDIR)/STM32F10x_StdPeriph_Lib_V3.5.0/Libraries

#Adjust TypeOfMCU in use, see CMSIS file "stm32f10x.h"
#STM32F103RBT (128KB FLASH, 20KB RAM) --> STM32F10X_MD
#STM32F103RET (512KB FLASH, 64KB RAM) --> STM32F10X_HD
#STM32F103ZET (512KB FLASH, 64KB RAM) --> STM32F10X_HD    
TypeOfMCU 	= STM32F10X_HD

# Tool chains settings.
TOOLCHAINS_PREFIX	=	arm-none-eabi
CC					=	$(TOOLCHAINS_PREFIX)-gcc
ld 					=	$(TOOLCHAINS_PREFIX)-ld -v
OBJCOPY 			=	$(TOOLCHAINS_PREFIX)-objcopy
AR 					=	$(TOOLCHAINS_PREFIX)-ar
GDB 				=	$(TOOLCHAINS_PREFIX)-gdb

INCLUDE	 =-I$(TOP)/inc  
INCLUDE	+=-I$(STMLIB)/CMSIS/CM3/CoreSupport
INCLUDE	+=-I$(STMLIB)/CMSIS/CM3/DeviceSupport/ST/STM32F10x
INCLUDE	+=-I$(STMLIB)/STM32F10x_StdPeriph_Driver/inc

COMMONFLAGS		= -g -mcpu=cortex-m3 -mthumb
COMMONFLAGSlib	= $(COMMONFLAGS)
#Commands for general Makefile and src Makefile  
ifeq ($(OptSRC),0)
	COMMONFLAGS	+=	-O0
	InfoTextSrc	 =	src (no optimize, -O0)
else ifeq ($(OptSRC),1)
	COMMONFLAGS +=	-O1
	InfoTextSrc  =	src (optimize time+ size+, -O1)
else ifeq ($(OptSRC),2)
	COMMONFLAGS +=	-O2
	InfoTextSrc  =	src (optimize time++ size+, -O2)
else ifeq ($(OptSRC),s)
	COMMONFLAGS +=	-Os
	InfoTextSrc  =	src (optimize size++, -Os)
else  
	COMMONFLAGS	+=	-Os
	InfoTextSrc  = 	src (full optimize, -O3)
endif
CFLAGS  +=  $(COMMONFLAGS) -Wall -Werror $(INCLUDE)
CFLAGS  +=  -D$(TypeOfMCU)
CFLAGS  +=  -DUSE_STDPERIPH_DRIVER
  
#Commands for libs Makefile  
ifeq ($(OptLIB),0)
	COMMONFLAGSlib	+=  -O0
	InfoTextLib		 =  libs (no optimize, -O0)
else ifeq ($(OptLIB),1)
	COMMONFLAGSlib	+=  -O1
	InfoTextLib		 =	libs (optimize time+ size+, -O1)
else ifeq ($(OptLIB),2)
	COMMONFLAGSlib  +=  -O2
	InfoTextLib		 =  libs (optimize time++ size+, -O2)
else ifeq ($(OptLIB),s)
	COMMONFLAGSlib	+=  -Os
	InfoTextLib		 =  libs (optimize size++, -Os)
else  
	COMMONFLAGSlib	+=	-O3
	InfoTextLib		 =	libs (full optimize, -O3)
endif  
CFLAGSlib += $(COMMONFLAGSlib) -Wall -Werror $(INCLUDE)
CFLAGSlib += -D$(TypeOfMCU)
CFLAGSlib += -DUSE_STDPERIPH_DRIVER

二、libs下的Makefile是用來編譯STM32標準驅動庫的,生成的中間文件在libs/out/tmp中,而最後成果在libs/out/lib中。請看具體內容:

 

# libs Makefile  
include ../Makefile.common 

INC       = -I$(TOP)/src
LIBS 	  = libstm32.a   
OBJOUTDIR = $(LIBDIR)/out/tmp
LIBOUTDIR = $(LIBDIR)/out/lib

MY_C_SOURCES := $(wildcard $(STMLIB)/CMSIS/CM3/CoreSupport/*.c)
MY_C_SOURCES += $(wildcard $(STMLIB)/CMSIS/CM3/DeviceSupport/ST/STM32F10x/*.c)
MY_C_SOURCES += $(wildcard $(STMLIB)/STM32F10x_StdPeriph_Driver/src/*.c)

SOURCES := $(patsubst %.c, %.c, $(MY_C_SOURCES))

MY_S_SOURCES := $(STMLIB)/CMSIS/CM3/DeviceSupport/ST/STM32F10x/startup/gcc_ride7/startup_stm32f10x_hd.s
S_OBJS 		 := $(patsubst %.s, %.o, $(MY_S_SOURCES))

OBJS				:= $(patsubst %.c, %.o, $(SOURCES))
OBJSWITHOUTDIR 		:= $(patsubst %.c, $(OBJOUTDIR)/%.o, $(notdir $(SOURCES)))
OBJSWITHOUTDIR		+= $(OBJOUTDIR)/$(notdir $(S_OBJS))

all: $(LIBS) 

$(LIBS):$(OBJS) $(S_OBJS)
	$(AR) cr $(LIBOUTDIR)/$@ $(OBJSWITHOUTDIR)

.PHONY: clean tshow
  
clean:
	rm -f $(LIBOUTDIR)/*.a
	rm -f $(OBJOUTDIR)/*.o

show:
	@echo $(MY_C_SOURCES)
	@echo 
	@echo $(SOURCES)
	@echo 
	@echo $(OBJS)
	@echo 

tshow:  
	@echo "#####################################################################################"  
	@echo "################# optimize settings: $(InfoTextLib), $(InfoTextSrc)"  
	@echo "#####################################################################################"  

$(S_OBJS): $(MY_S_SOURCES)
	$(CC) $(CFLAGSlib) -c $< -o $(OBJOUTDIR)/$(notdir $@)

%.o:%.c
	$(CC) $(CFLAGSlib) $(INC) -c $< -o $(OBJOUTDIR)/$(notdir $@)

三、編譯二進制可執行文件的Makefile,就在與Makefile.common同級的目錄中。它編譯的結果包括中間文件都在src/out目錄中,這裏的編譯會用到libs下生成的libstm32.a文件。

 

# general Makefile  
  
include Makefile.common  

PROGRAM	  = stm32_project
LIBS 	  = libstm32.a   
OBJOUTDIR = $(TOP)/src/out/tmp
BINOUTDIR = $(TOP)/src/out/bin
LIBOUTDIR = $(LIBDIR)/out/lib
INC 	  = -I$(TOP)/src

LDFLAGS=$(COMMONFLAGS) -fno-exceptions -ffunction-sections -fdata-sections \
	-L$(LIBOUTDIR) -Wl,--no-whole-archive -lstm32 \
	-nostartfiles -Wl,--gc-sections,-T$(TOP)/src/stm32_flash.ld  

MY_C_SOURCES 		:= $(wildcard $(TOP)/src/*.c)
SOURCES 			:= $(patsubst %.c, %.c, $(MY_C_SOURCES))
OBJS				:= $(patsubst %.c, %.o, $(SOURCES))
OBJSWITHOUTDIR 		:= $(patsubst %.c, $(OBJOUTDIR)/%.o, $(notdir $(SOURCES)))

.PHONY: libs clean tshow  show
all: libs src  
  
libs:
	$(MAKE) -C $@
	
src: $(OBJS)
	$(CC) -o $(BINOUTDIR)/$(PROGRAM).elf $(OBJSWITHOUTDIR) $(LDFLAGS)
	$(OBJCOPY) -O ihex $(BINOUTDIR)/$(PROGRAM).elf $(BINOUTDIR)/$(PROGRAM).hex
	$(OBJCOPY) -O binary $(BINOUTDIR)/$(PROGRAM).elf $(BINOUTDIR)/$(PROGRAM).bin
	arm-none-eabi-readelf -a $(BINOUTDIR)/$(PROGRAM).elf > $(BINOUTDIR)/$(PROGRAM).info_elf
	arm-none-eabi-size -d -B -t $(BINOUTDIR)/$(PROGRAM).elf > $(BINOUTDIR)/$(PROGRAM).info_size
	arm-none-eabi-objdump -S $(BINOUTDIR)/$(PROGRAM).elf > $(BINOUTDIR)/$(PROGRAM).info_code
	arm-none-eabi-nm -t d -S --size-sort -s $(BINOUTDIR)/$(PROGRAM).elf > $(BINOUTDIR)/$(PROGRAM).info_symbol

%.o:%.c
	$(CC) $(CFLAGS) $(INC) -c $< -o $(OBJOUTDIR)/$(notdir $@)

clean:
	$(MAKE) -C libs $@
	-rm -r $(OBJOUTDIR)/*.o
	@cd $(BINOUTDIR)
	-rm -f $(PROGRAM).elf $(PROGRAM).hex $(PROGRAM).bin $(PROGRAM).info_elf $(PROGRAM).info_size
	-rm -f $(PROGRAM).info_code
	-rm -f $(PROGRAM).info_symbol
	@cd ..

show:
	@echo $(MY_C_SOURCES)
	@echo 
	@echo $(SOURCES)
	@echo 
	@echo $(OBJS)
	@echo 
	@echo $(OBJSWITHOUTDIR)

tshow:  
	@echo "######################################################################################################"  
	@echo "################# optimize settings: $(InfoTextLib), $(InfoTextSrc)"  
	@echo "######################################################################################################"

四、當文件都配置穩當,那麼就能夠在STM32這一級目錄中執行make指令,若是一塊兒正常就會在src/out/bin下生成一個stm32_project.bin的文件,這個文件就是最終要燒錄到開發板的二進制文件。

五、還要注意的是,注意程序在連接的時候須要一個連接腳本,這個腳本定義了連接過程當中全部代碼的定位問題。因此必定要注意其配置。這個文件在STM32標準驅動庫中的Project/STM32F10x_StdPerihp_Template/TrueSTUDIO中每一EVAL目錄中有示例,主要區別就是目標MCU的RAM/FLASH的大小。必定注意,我使用的STM32F103VET6是512KB flash/64KB RAM,其連接腳本(stm32_flash.ld)以下:

 

/*
*****************************************************************************
**
**  File        : stm32_flash.ld
**
**  Abstract    : Linker script for STM32F103ZE Device with
**                512KByte FLASH, 64KByte RAM
**
**                Set heap size, stack size and stack location according
**                to application requirements.
**
**                Set memory bank area and size if external memory is used.
**
**  Target      : STMicroelectronics STM32
**
**  Environment : Atollic TrueSTUDIO(R)
**
**  Distribution: The file is distributed 「as is,」 without any warranty
**                of any kind.
**
**  (c)Copyright Atollic AB.
**  You may use this file as-is or modify it according to the needs of your
**  project. Distribution of this file (unmodified or modified) is not
**  permitted. Atollic AB permit registered Atollic TrueSTUDIO(R) users the
**  rights to distribute the assembled, compiled & linked contents of this
**  file as part of an application binary file, provided that it is built
**  using the Atollic TrueSTUDIO(R) toolchain.
**
*****************************************************************************
*/

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = 0x20010000;    /* end of 64K RAM */

/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0;      /* required amount of heap  */
_Min_Stack_Size = 0x200; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 512K
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 64K
  MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}

/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

  /* The program code and other data goes into FLASH */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */

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

    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH


   .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
    .ARM : {
    __exidx_start = .;
      *(.ARM.exidx*)
      __exidx_end = .;
    } >FLASH

  .ARM.attributes : { *(.ARM.attributes) } > FLASH

  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(.fini_array*))
    KEEP (*(SORT(.fini_array.*)))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH

  /* used by the startup to initialize data */
  _sidata = .;

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .data : AT ( _sidata )
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */

    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
  } >RAM

  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)

    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM

  PROVIDE ( end = _ebss );
  PROVIDE ( _end = _ebss );

  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(4);
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(4);
  } >RAM

  /* MEMORY_bank1 section, code must be located here explicitly            */
  /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */
  .memory_b1_text :
  {
    *(.mb1text)        /* .mb1text sections (code) */
    *(.mb1text*)       /* .mb1text* sections (code)  */
    *(.mb1rodata)      /* read-only data (constants) */
    *(.mb1rodata*)
  } >MEMORY_B1

  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
}

4、使用J-Link下載代碼到MCU

    好了,如今咱們擁有一個能夠燒錄的stm32_project.bin文件。如今請將J-LINK鏈接到你的MAC而且爲開發板供電。

若是J-LINK鏈接正常,那麼系統信息中會顯示J-Link設備。個人設備以下:

   

    如今可使用安裝好的J-LINK驅動將bin文件下載到MCU得內置flash中。請先在shell中進入的工程根目錄,並在shell執行以下命令:

$ JLinkExe
J-Link>

    如今您能夠在此命令行中執行相關命令來下載bin文件。首先要執行device這條指令用來指定您的目標MCU,個人是STM32F103VET6,因此以下:

 

J-Link > exec device=STM32F103VE

    是否成功會有消息提示,請仔細閱讀。

    在使用以上命令選擇了目標MCU以後,就能夠下載bin文件了,以下:

 

J-Link > loadbin src/out/bin/stm32_project.bin 0x08000000

    其中loadbin爲命令,緊接着爲文件名,再接着爲目標MCU內置Flash的起始地址。這個地址依賴具體的MCU,請查閱相關Datasheet,但應該與stm32_flash.ld中memory section中Flash描述的起始地址同樣,及以下:

 

/* Specify the memory areas */
MEMORY
{
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 512K
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 64K
  MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}

    其中的 FLASH(rx) 中的ORIGIN就表示Flash的起始地址,上述命令中的地址應該與其保持一致。若是這條命令執行成功就會打印出OK等字樣,而且會打印相關打印的時間信息等。

    大功告成,如此一來,只要將MCU復位,就能夠看到代碼的執行效果了。

5、總結

    本文主要介紹了Mac OS X下如何搭建STM32的開發環境。其實本文中的Makefile仍是不太完善,由於每次執行make全部的文件都會從新編譯,可是不影響功能,相關完善就再也不發文,請知悉。文中內容均爲原創,只有Makefile.common的部份內容摘錄自網絡,轉載請註明出處,謝謝。

相關文章
相關標籤/搜索