Linux
    
    
    
    
         | 
        
        2020-05-02
    
    
    
         | 
        
        782
    
    
    
  
                
                資料夾結構
第一步,建立三個資料夾 “System”、“OS” 及 “User”
. |-- System | |-- OS | `-- User
   | 
 
- System 放驅動程式
 
- OS 就是作業系統(也可不用)
 
- User 放的是我們的專案
 
接著,在每個資料夾底下新增一個 makefile。
. |-- System |   `-- makefile | |-- OS |   `-- makefile | |-- User |   `-- makefile | `-- makefile
   | 
 
準備步驟的最後,將所有程式碼正確的擺放。如範例:
. |-- System |   |-- STM32 |   |   |-- src |   |   `-- inc |   | |   |-- STM32F429 |   |   |-- src |   |   `-- inc |   | |   |-- CMSIS |   |   |-- src |   |   `-- inc |   | |   `-- makefile | |-- OS |   |-- src |   |-- inc |   `-- makefile | |-- User |   |-- src |   |-- inc |   `-- makefile | `-- makefile
   | 
 
在這個例子,我們在 System 底下放了三個驅動,所以需要將程式碼分成三個資料夾。
當然你也可以直接全部放在一起是沒問題的。
 
最後的最後,別忘了在驅動的底下也加一個 makefile。
. |-- System |   |-- STM32 |   |   |-- src |   |   |-- inc |   |   `-- makefile |   | |   |-- STM32F429 |   |   |-- src |   |   |-- inc |   |   `-- makefile |   | |   |-- CMSIS |   |   |-- src |   |   |-- inc |   |   `-- makefile |   | |   `-- makefile | |-- OS |   |-- src |   |-- inc |   `-- makefile | |-- User |   |-- src |   |-- inc |   `-- makefile | `-- makefile
   | 
 
下一步,來寫 makefile!
GCC
在所有的 makefile(除了最上層)寫上以下程式碼:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
   | TCPREFIX = arm-none-eabi- CC       = $(TCPREFIX)gcc
  CFLAGS 	= -c -Wall -fno-common -O0 -g -mthumb -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16 --specs=nosys.specs
  INCFLAG =\ -I. \ -Iinc
  CFLAGS  += $(INCFLAG)
  OBJDIR 	= obj
  OBJS =\ $(OBJDIR)/src.o 
  all: $(OBJS)
  $(OBJDIR)/%.o: src/%.c | $(OBJDIR) 	@echo "bulid file: $<" 	$(CC) $(CFLAGS) -MMD -MF$(@:%.o=%.d) -o $@ $<
  $(OBJDIR): 	@echo $(NOW) INFO Make new folder User/$(OBJDIR). 	mkdir -p $(OBJDIR)
  clean: 	-rm -rf $(OBJDIR)/*.o  	-rm -rf $(OBJDIR)/*.d
   | 
 
- 使用 
arm-none-eabi-gcc 來進行編譯 
- 為 
gcc 加入一些設定,如浮點數處理器。 
- 接著設定所有需要連結的 object file
 
- 將所有 
.c 編譯成 .o 
- Target 
all 將會完成編譯所有檔案 
- Target 
clean 可以清理所有 object file 
接著告訴主要的 makefile 要去底下的 makefile 執行編譯
1 2 3 4
   | obj: 	$(MAKE) all -C System 	$(MAKE) all -C OS 	$(MAKE) all -C User
   | 
 
-C 意味著要去下層資料夾執行目標,所以第二行等同於:
Startup.o
Startup.o 是必須的,把它放在 User 理,但不要放進 src;編譯他的道理是類似的
OBJS +=\ startup.o
  Startup/startup.o: ./startup.s | $(OBJDIR) 	@echo "bulid file: $<" 	$(CC) $(CFLAGS) -MMD -MF$(@:%.o=%.d) -o $@ $<
   | 
 
以上建置完成後,能快速的編譯所有程式。接著我們將所有 object file 連結成一個二進位檔。
G++ (Linker)
連結的動作放在主要的 makefile 中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | TCPREFIX = arm-none-eabi- LD       = $(TCPREFIX)g++
  LFLAGS  = -mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 -Os -T$(LDFILE) --specs=nosys.specs LDFILE  = ./STM32F429ZI_FLASH.ld
  OBJS =\ $(wildcard ./User/obj/*.o) \ $(wildcard ./System/*/obj/*.o) \ $(wildcard ./OS/obj/*.o) \ ./User/startup.o
  main.elf: $(OBJS) $(LDFILE) 	@echo "link file: $@" 	$(LD) $(LFLAGS) -o $@ $(OBJS)
   | 
 
- 使用 wildcard 掃描所有 object file
 
- 連結成一個 
.elf 
Objdump and Objcopy
再將 .elf 轉成 .bin 燒錄。
1 2 3 4 5 6 7 8
   | TCPREFIX = arm-none-eabi- CP       = $(TCPREFIX)objcopy OD       = $(TCPREFIX)objdump
  main.bin: obj main.elf 	@echo "copy file main.elf" 	$(CP) $(CPFLAGS) main.elf $@ 	$(OD) $(ODFLAGS) main.elf > main.lst
   | 
 
Openocd
最後一件事,燒錄;這裡使用 openocd。
1 2 3 4 5 6 7 8 9 10 11 12
   | run: main.bin 	@echo $(YELLOW)"Flash $< into board..."$(RST) 	openocd -f $(OCDCFG)  				\ 			-c "init"                   \             -c "reset init"             \             -c "stm32f2x unlock 0"      \             -c "flash probe 0"          \             -c "flash info 0"           \             -c "flash write_image erase $< 0x8000000" \             -c "reset run" -c shutdown 	@echo $(GREEN)"Finish flash $< into board."$(RST) 	@echo ""
   | 
 
總結
在主 makefile 寫下以下片段,將所有東西整合吧。
如此以來,只要下指令 make all 就會將所有該編譯的程式碼編譯完成,連結成一個二進位檔,最後燒盡板子。
這是我的一個專案建置的範例,可以參考。