stm32F103(HAL庫)+keil5.20+gcc(gcc-arm-none-eabi-9-2019-q4-major-win32)編譯器編譯工程(詳細步驟)


序:

偶然的因素看到網上有keil設置arm gcc的編譯器,於是想自己嘗試一下。mdk5.15之后就可以按照此文的方案去設置,也可以參考keil官網文檔,

這個文章過了好多年,圈中大佬,真正的大佬(GorgonMeducer 傻孩子 裸機思維),在他的公眾號中,寫了一個手把手的教程——《【教程】如何用GCC“零匯編”白嫖MDK》,溫故知新,好記性不如爛筆頭~~~

1、安裝

gcc-arm-none-eabi-9-2019-q4-major-win32.exe,這個在arm公司官網下載,是免費的,不同於armcc,armcc是要注冊的。

(之前的老版本下載網址:https://launchpad.net/gcc-arm-embedded/)基本上不使用了。

2、安裝使用默認路徑。

3、keil使用我原來的hal工程,工程下設置如下。這個和keil的文檔上面是一樣的。

 PS:選擇了第3步,會把之前的設置全部清空,因此最好是保留一份工程。

4、工程設置

4.1、把時鍾設置正確,有木有和以前的armcc完全不一樣。

4.2、out設置,沒有了broswer information了。還可以該大小端,當然stm32f103默認是小端,我們不去改動大端。

4.3、c語言設置,划線的都要根據實際來設置。

Misc Controls : -mcpu=cortex-m3 -mthumb -fdata-sections -ffunction-sections
注:
1.這里我用的cortex-m3,如果你是m4內核就改成4)
2.-mthumb的意義是:使用這個編譯選項生成的目標文件是Thumb的
3.-fdata-sections和-ffunction-sections和下文連接規則一起說

4.5、匯編設置

  • Misc Controls : -mcpu=cortex-m3 -mthumb

 4.6、鏈接設置,注意划線部分

Misc Controls : -Wl,–gc-sections
注:
1.注意這個gc前面是兩個短小的“–”,由於博客的問題直接復制會出錯
2.-wl, 表示后面的參數 –gc-sections 傳遞給鏈接器
3.-fdata-sections和-ffunction-sections和–gc-sections的說明如下

-ffunction-sections和-fdata-sections會使編譯器為每個function和data item分配獨立的section。 –gc-sections會使連接器刪除沒有被使用的section。
連接操作以section作為最小的處理單元,只要一個section中有某個符號被引用,該section就會被放入output中。這些選項一起使用會從最終的輸出文件中刪除所有未被使用的function和data, 只包含用到的unction和data。

有點類似armcc的elf設置

具體細節可以參考另一位博主的文章http://blog.csdn.net/pengfei240/article/details/55228228

 4.6、debug設置,和armcc一樣,不細講。

5、stm32_flash.ld文件,我是從標准外設庫里拷貝的,如下搜索:

 具體的作用如下:

 6、啟動代碼,使用GCC專用的.S文件,這個要從cubef1的庫中去拷貝。

 7、編譯

編譯后很多錯誤,首先是標准庫的錯誤。類似於:

d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text._sbrk_r+0xc): undefined reference to `_sbrk'
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-writer.o): In function `_write_r':
writer.c:(.text._write_r+0x10): undefined reference to `_write'
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-closer.o): In function `_close_r':
closer.c:(.text._close_r+0xc): undefined reference to `_close'
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-fstatr.o): In function `_fstat_r':
fstatr.c:(.text._fstat_r+0xe): undefined reference to `_fstat'
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-isattyr.o): In function `_isatty_r':
isattyr.c:(.text._isatty_r+0xc): undefined reference to `_isatty'
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-lseekr.o): In function `_lseek_r':
lseekr.c:(.text._lseek_r+0x10): undefined reference to `_lseek'
d:/gcc-arm-none-eabi-4_9/bin/../lib/gcc/arm-none-eabi/4.9.3/../../../../arm-none-eabi/lib/armv7-m\libc_nano.a(lib_a-readr.o): In function `_read_r':

 如上圖所示出現兩個錯誤,根據原文所述如果有使用標准的C 函數,如sprintf,則要包含syscall.c 這個文件。於是我查找了標准庫文件發現沒有提供,后來又查找了HAL庫的文件,找到了syscall.c如下圖,找到一個文件拷貝到工程目錄中。

 其次是undefined reference to `_init'錯誤,網上參考了文章如下:

今天利用CDT 的eclipse調試程序,遇到下面的問題:

d:/plugin/bin/../lib/gcc/arm-none-eabi/4.8.4/../../../../arm-none-eabi/lib/armv7-m\libg_s.a(lib_a-init.o): In function `__libc_init_array':
init.c:(.text.__libc_init_array+0x1c): undefined reference to `_init'
collect2.exe: error: ld returned 1 exit status
make: *** [gg.elf] Error 1

圖片格式如下:

查詢良久,在與非網上(http://www.infineonic.org/module/forum/thread-601371-1-1.html)發現問題所在:

在工程->property->C/C++ builder->settings->Cross ARM C++ linker->general中的設置是這樣的:

將第一個√去掉就可以了

這個在linker設置之前是會出錯的,因此在上一步的linker設置中,按照我的配置即可編譯通過。意思是我們這個工程是需要標准的啟動文件的。如下兩點,其中我們也使用標准庫的文件的。

 最后,重定義標准庫的函數,當我們需要重定向到usart 到pc com調試打印時候,需要重新實現_write() 和 _read() 。

我的實現_write() 如下:

int _write(int fd, char *pBuffer, int size)
{
    for (int i = 0; i < size; i++)
    {
		HAL_UART_Transmit(&huart1, (uint8_t*)pBuffer++, 1, 0xFFFF);
		//HAL_UART_Transmit(&huart1, pBuffer++, 1, 0xFFFF);
    }
    return size;
}
HAL_UART_Transmit(&huart1, pBuffer++, 1, 0xFFFF);這個語句是編譯不能通過的:

 最后編譯結果如下:

說明gcc的編譯語法等級比較高。

注:采用GCC編譯器后無法使用“Go To Definition Of ”跳轉到相應的函數這個功能。

8、仿真:仿真設置好以前的armcc一樣的。仿真結果:

 9、總結,使用arm gcc編譯器來編譯,應該可以避免keil編譯器盜版的情況。可以學習到更多的gcc方面的知識,以后linux下更多的也是arm gcc編譯器。

網上資源很多,需要自己根據實際情況來判斷是否是有用的。

附件:

-mcpu=cortex-m3 -mthumb -fdata-sections -ffunction-sections
-mcpu=cortex-m3 -mthumb 
-Wl,--gc-sections

注意點:

--gc是兩個--

參考網站:
https://blog.csdn.net/weixin_42559298/article/details/98769671 ——主要講述預定義
https://blog.csdn.net/weixin_39871788/article/details/78858791 ——這個文章很好,基本參考這個
https://blog.csdn.net/lan120576664/article/details/46806991——STM32F4的工程
https://blog.csdn.net/daxiebao/article/details/52653657——解決串口重映射
https://www.cnblogs.com/quray/p/4724506.html——解決undefined reference to `_init'的編譯問題

http://www.keil.com/arm/gnu.asp——keil使用gcc編譯器

 https://blog.csdn.net/weixin_39871788/article/details/78858791——Keil5配置GCC編譯器編譯STM32工程

https://blog.csdn.net/Cui_Hongwei/article/details/104108044——STM32 GCC編譯器 .ld & .s文件詳細解析


免責聲明!

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



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