最近,看到群里的小伙伴在討論【我的代碼不按照流程執行】相關的話題。這類問題,有經驗的工程師肯定能想到是什么原因導致的,那就是編譯器把你代碼優化了。
本文將圍繞Keil MDK優化選項,以及相關拓展知識(微庫、實際應用、調試)進行講述,希望能對你的項目開發有所幫助。
一、概 述
我們所指的優化,主要包括兩個方面:
代碼大小(Size)
代碼性能(運行時間)
在MDK-ARM中,優化相關的配置選項:
當然,如果選擇編譯器(AC5、AC6)不同,優化選項也有差異(下面講述)。
舉個例子:
某些項目MCU容量有限時,你除了修改代碼(優化開支),同時你有必要使用優化選項。
某些項目(比如某算法)需要高效(最短時間)運行,此時有必要使用優化選項。
二、優化選項說明
本節詳細講述了優化相關選項,同時,編譯器選擇AC5和AC6時有差異,下面也會針對AC5和6分別講述。
1、Use Cross-Module Optimization:使用跨模塊優化
使用跨模塊優化可以啟用鏈接器反饋文件(進行兩次編譯),從而允許進一步的代碼優化。
提示:
不針對庫目標執行跨模塊優化;
跨模塊優化將增加構建項目所需的時間,因為會自動執行多個編譯和鏈接步驟。
2、Use MicroLIB:使用微庫
它是ISO標準C運行時庫的子集(其中一部分),提供了性能和代碼大小之間的權衡。
微庫并不完全兼容ANSI,但對于大多數小型嵌入式應用程序來說,它已經足夠了。
3、Use Link-Time Code Generation:使用鏈接時代碼生成(優化)
在V5版本之前有這個優化選項,多文件編譯,鏈接時進行優化:
函數跨模塊內聯
刪除未引用的變量和函數
通過重新排列變量優化內存訪問
在可能的情況下重用內存
4、Execute-only Code:生成只執行的代碼
不包含未使用(函數、變量等)代碼段。
僅限于:
C、Thumb代碼
基于Cortex-M3、M4的處理器
編譯器5.04以上
5、Optimize for Time:優化時間
以更大的代碼大小為代價,減少執行時間,比如使用內聯函數。
編譯器為AC6時,此選項為【Link-Time Optimization】,在鏈接狀態下執行模塊間優化。
6、Split Load and Store Multiple:分割加載和多存儲
指示編譯器將LDM和STM指令拆分為兩個或多個LDM或STM指令,以減少延遲,此選項可以提高系統的總體性能。
7、The One ELF Section per Function:每個函數一個ELF段
ELF代碼段通常包含許多函數的代碼,此選項告訴編譯器將所有函數放入它們自己的ELF段,這允許鏈接器刪除未使用的ELF段(而不是未使用的函數)。
8、AC5時:Optimization優化選項
Level 0 (-O0):關閉大部分優化,除了一些簡單的轉換,生成的代碼具有最佳的調試視圖。
Level 1 (-O1):應用受限優化。
比如:刪除未使用的內聯函數和靜態函數,刪除冗余代碼和重新排序指令等。生成的代碼經過合理優化,具有良好的調試視圖。
Level 2 (-O2):高度優化,目標代碼到源代碼的映射并不一定對應,因此,不利于調試。
Level 3 (-O3):最大級別優化,級別3與時間優化相結合可能生成比級別2更多的代碼。
9、AC6時:Optimization優化選項
當編譯器選擇AC6時,優化選項有差異(有更多優化選項):
AC6優化選型中前面5項(default、-O0 ~ 3)和AC5的作用基本一樣,但AC6多了三個選項。
-Ofast:啟用-O3的所有優化,以及其他可能違反語言標準(嚴格遵守)的優化。
-Os balanced:平衡代碼大小與代碼速度。默認情況下,編譯器執行優化以提高性能,但可能會增加image文件大小。
-Oz image size:優化代碼大小。
三、如何優化?
本節講述三種編譯優化,使其達到最優(代碼最小、性能最好):
代碼大小
代碼性能(速度)
代碼平衡(大小和速度)
1、優化代碼大小
針對AC5編譯器:
Use MicroLIB
Use Cross-module optimization
Optimization:level 2 (-O2)
針對AC6編譯器:
Use MicroLIB
Optimization:-Oz image size
說明:
代碼量大(ELF代碼段通常包含許多函數的代碼),可考慮使用The One ELF Section per Function選項減小代碼。
AC6編譯器改進了優化功能(可以理解為增加的3個選項集成了優化功能)。
代碼優化大小(對比):
2、優化代碼性能
針對AC5編譯器:
Use Cross-module optimization
Optimization:level 3 (-O3)
Optimize for Time
針對AC6編譯器:
Optimization:-Ofast
Link-Time Optimization
代碼優化性能(對比):
3、代碼平衡
這種情況下,在滿足代碼大小的同時,我們應盡量滿足性能。
這里其實就是一個相關平衡的關系,結合上面兩種優化方式根據自己實際情況出發,一般優化考慮如下配置。
針對AC5編譯器:
Use Cross-module optimization
Optimization:level 3 (-O3)
Optimize for Time
針對AC6編譯器:
Optimization:-Os balanced
Link-Time Optimization
當然,AC6中-Os balanced優化選項更智能。
四、拓 展
Keil MDK的優化功能需要結合項目實際情況進行優化。對一些項目能起到很大幫助作用,但優化之后也可能帶來一些影響。
比如,使用高度優化(-O1以上),可能會影響Debug調試(因為優化之后,編譯輸出和實際代碼不匹配)。
還有,指定源文件/文件組優化。有些代碼不需要優化,我們優化指定的源文件/文件組就行。
本文轉載自嵌入式專欄
審核編輯:湯梓紅
-
單片機
+關注
關注
6032文章
44525瀏覽量
633260 -
程序
+關注
關注
116文章
3778瀏覽量
80860 -
keil
+關注
關注
68文章
1212瀏覽量
166701 -
代碼
+關注
關注
30文章
4753瀏覽量
68368 -
編譯器
+關注
關注
1文章
1618瀏覽量
49057
原文標題:寫個單片機程序,居然被優化了!
文章出處:【微信號:玩點嵌入式,微信公眾號:玩點嵌入式】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論