1.為什么不是gcc
之前我們花了三篇文章介紹Linux下如何進(jìn)行C語言編程:
這是為了給接下來的Linux下嵌入式開發(fā)打好基礎(chǔ),盡快熟悉Linux下c編程,但是在開發(fā)stm32的時(shí)候,編譯工具鏈要使用gcc-arm-none-eabi,為什么不是gcc呢?這就要說到linux下的交叉編譯了,因?yàn)槲覀円赑C機(jī)上編譯出可以運(yùn)行在ARM上的程序,使用gcc編譯出的是在PC上運(yùn)行的程序,所以我們要使用gcc-arm-none-eabi進(jìn)行交叉編譯~
2.gcc-arm-none-eabi toolchain 介紹及安裝
gcc-arm-none-eabi是一個(gè)開源的ARM開發(fā)工具鏈,適用于Arm Cortex-M和Coretex-A系列處理器,包括GNU編譯器(GCC),以及GDB,可用于Windows,Linux,MacOS上的交叉編譯。
gcc-arm-none-eabi在ubuntu軟件源倉庫中就有,但是版本比較陳舊:

在此我們從[ARM官方下載鏈接](https://developer./open-source/gnu-toolchain/gnu-rm/downloads)選擇合適的版本下載(這里我選擇Linux64):

解壓下來是tar.ba2格式包,使用命令tar -jxf <要解壓的文件>解壓到我們要安裝的目錄:

為了以后使用方便,將文件夾重命名:

它下面的bin目錄就是我們要使用的編譯工具鏈:

share目錄的doc下包含了大量的使用幫助文檔,可以先略讀一二,特別是readme.txt:

接下來我們要將bin目錄添加到環(huán)境變量,這樣可以直接在命令行輸入要使用的工具名,然后系統(tǒng)就可以找到該工具,在此我們僅為當(dāng)前用戶添加環(huán)境變量,使用vim ~/.bashrc編輯當(dāng)前用戶配置文件,在最后添加export PATH=$PATH:/home/mculover666/gcc-arm-none-eabi/bin:

然后使用命令source ~/.bashrc更新系統(tǒng)路徑,使添加的環(huán)境變量立即生效:

然后輸入命令arm-none,然后按三下Tab(一定不要輸入全部),檢查系統(tǒng)是否可以自動補(bǔ)全:

如果系統(tǒng)可以提示,說明環(huán)境變量配置成功,可以開心的使用arm-none-eabi工具鏈啦~
3.從裸機(jī)工程開始
3.1.硬件說明
這里我使用的是野火霸道開發(fā)板,板載芯片為STM32F103ZET6,下載器使用e-link,這個(gè)下載器使用CMSIS-DAP下載程序,同時(shí)并帶有一個(gè)串口,非常好用~

板載RGB-LED的原理圖如圖所示:

3.2.新建空的裸機(jī)工程
首先新建一個(gè)文件夾mkdir 00-template-reg用來存放整個(gè)工程,然后整個(gè)工程包含三個(gè)文件:
#include 'stm32f10x.h'
int main()
{
/* 開啟GPIOB時(shí)鐘 */
*(unsigned int*)(0x40021000+0x18) |= 1<<3;
/* 配置PB0為推挽輸出 */
*(unsigned int*)(0x40010c00+0x00) |= 1<<(4*0);
/* PB0輸出低電平,點(diǎn)亮綠色LED */
*(unsigned int*)(0x40010c00+0x0c) &= ~(1<<0);
while(1);
}
void SystemInit(void)
{
}
4.編譯
接下來就是激動人心的編譯步驟了~編譯的時(shí)候有兩種文件,一種是匯編啟動文件,一種是c源文件,接下來分別編譯:
首先需要說明一些編譯任何一個(gè)文件都需要帶上的參數(shù):
| 參數(shù) | 說明 |
|---|
| -mthumb | 表明使用的指令集(必需) |
| -mcpu=cortex-m3 | 表明芯片內(nèi)核(必需) |
| -g | 產(chǎn)生調(diào)試信息 |
4.1.啟動文件編譯
啟動文件一般是由匯編寫成,此處需要注意的是,匯編文件的格式有.S和.s之分:
之前我們添加的啟動文件是小寫.s,所以直接進(jìn)行編譯,另外說一下,如果使用的是.S文件,那么需要帶上-x assembler-with-cpp參數(shù)。
接下來說明一些匯編文件gcc編譯器使用的參數(shù):
| 參數(shù) | 說明 |
|---|
| -x assembler-with-cpp | 先對文件進(jìn)行預(yù)處理 |
| -Wa,option | 向匯編器Assembler傳遞參數(shù) |
注:可以向匯編器傳遞的參數(shù):
| 參數(shù) | 說明 |
|---|
| -W或--no-warn | 關(guān)閉所有告警 |
| --fatal-warnings | 將所有的警告提示為錯(cuò)誤 |
| --warn | 正常提示告警信息 |
所以,接下來我們可以使用如下的參數(shù)組合來編譯啟動文件(不進(jìn)行預(yù)處理,并且正常提示告警信息):
arm-none-eabi-gcc -c -mthumb -mcpu=cortex-m3 -g -Wa,--warn -o startup_stm32f10x_hd.o startup_stm32f10x_hd.s

4.2.C文件編譯
因?yàn)閙ain.c中沒有特殊的東西,只是兩個(gè)函數(shù),所以簡單的編譯一下就可以了:
arm-none-eabi-gcc -c -mthumb -mcpu=cortex-m3 -g -Wall -o main.o main.c
5.鏈接
鏈接重要的部分有兩點(diǎn):鏈接文件和傳遞給鏈接器的參數(shù)。
鏈接文件在固件庫中給的示例工程中有,在下面這個(gè)目錄:

其中stm32_flash.ld是針對于STM32F103ZE的鏈接文件,如果是別的芯片,需要進(jìn)行修改,將它復(fù)制到我們的工程中去:

然后就要讓鏈接器開始根據(jù)stm32_flash.ld這個(gè)文件對startup_stm32f10x_hd.o和main.o這兩個(gè)文件開始鏈接,生成包含了調(diào)試信息的elf文件,同時(shí),我們還需要給鏈接器傳遞一些參數(shù):arm-none-eabi-gcc -o test.elf main.o startup_stm32f10x_hd.o -mthumb -mcpu=cortex-m3 -T stm32_flash.ld -specs=nosys.specs -static -Wl,-cref,-u,Reset_Handler -Wl,-Map=test.map -Wl,--gc-sections -Wl,--defsym=malloc_getpagesize_P=0x80 -Wl,--start-group -lc -lm -Wl,--end-group
6.生成bin文件和hex文件
利用arm-none-eabi-objcopy工具可以將elf文件轉(zhuǎn)化為適合于單片機(jī)的bin文件和hex文件,其中參數(shù)-O(大寫o)用于指定輸出文件的格式(默認(rèn)是bin格式)
arm-none-eabi-objcopy test.elf test.bin
arm-none-eabi-objcopy test.elf -Oihex test.hex
7.編寫一個(gè)makefile雛形
TARGET=test
CC=arm-none-eabi-gcc
OBJCOPY=arm-none-eabi-objcopy
RM=rm -f
CORE=3
CPUFLAGS=-mthumb -mcpu=cortex-m$(CORE)
LDFLAGS = -T stm32_flash.ld -Wl,-cref,-u,Reset_Handler -Wl,-Map=$(TARGET).map -Wl,--gc-sections -Wl,--defsym=malloc_getpagesize_P=0x80 -Wl,--start-group -lc -lm -Wl,--end-group
CFLAGS=-g -o
$(TARGET):startup_stm32f10x_hd.o main.o
$(CC) $^ $(CPUFLAGS) $(LDFLAGS) $(CFLAGS) $(TARGET).elf
startup_stm32f10x_hd.o:startup_stm32f10x_hd.s
$(CC) -c $^ $(CPUFLAGS) $(CFLAGS) $@
main.o:main.c
$(CC) -c $^ $(CPUFLAGS) $(CFLAGS) $@
bin:
$(OBJCOPY) $(TARGET).elf $(TARGET).bin
hex:
$(OBJCOPY) $(TARGET).elf -Oihex $(TARGET).hex
clean:
$(RM) *.o $(TARGET).*
使用命令make編譯生成elf文件;
使用命令make bin將elf文件轉(zhuǎn)化生成bin文件;
使用命令make hex將elf文件轉(zhuǎn)化生成hex文件;
使用命令make clean即可清除掉所有編譯產(chǎn)生的文件。
==下一篇==:Linux下開發(fā)stm32(二) | 使用openocd下載與調(diào)試
(https://blog.csdn.net/Mculover666/article/details/84900665)