STM32的map文件學習筆記

前言

前幾個月針對公司自己的芯片寫了個程序,這個程序有個硬性要求,就是能用的FLASH空間只有4KB,之前已經寫得差不多了,最終佔用空間3.6KB。這不,最近又得加需求,還剩一點點FLASH空間可以使用,這該如何是好。需求已經加過來了,不行也得行啊。所以就得去優化之前的代碼了,這就得研究比較底層的東西了。

我們的芯片與其它的MCU芯片用起來都差不多一樣。我們在用ST的時候,編譯完成,會生成很多文件,其中有一個.map文件,裡面包含的信息就是工程 ROM/FLASH 和 RAM 的佔用情況 。之前只是關心.map文件的最後幾行的 ROM/FLASH佔用信息,如:

STM32的map文件學習筆記


這次就得認真的學習一下這個文件了,只有清楚的知道這些信息才可以很好的進行代碼優化 。下面我們來一起學習一下STM32的.map文件。(以下內容來自於野火及安富萊教程文檔)

map文件

要生成 map 文件,MDK 中如下選項要選上:

STM32的map文件學習筆記


將工程全編譯,且沒有錯誤後,雙擊這裡就可以看到生成的 map 文件了:

STM32的map文件學習筆記


map文件的內容可分為如下幾部分:

<code>1、節區的跨文件引用(Section Cross References)2、刪除無用節區(Removing Unused input sections from the image)3、符號映像表(Image Symbol Table (Local Symbols Global Symbols)4、存儲器映像索引(Memory Map of the image)5、映像組件大小(Image component sizes)/<code> 

1、節區的跨文件引用

STM32的map文件學習筆記


這部分主要是不同文件中函數的調用關係。 在這部分中,詳細列出了各個.o 文件之間的符號引用。由於.o 文件是由 asm 或 c/c++源文件編譯後生成的,各個文件及文件內的節區間互相獨立,鏈接器根據它們之間的互相引用鏈接起來,鏈接的詳細信息在這個Section Cross References一一列出。

例如,開頭部分說明的是 startup_stm32f429_439xx.o 文件中的“RESET”節區分為它使用的__initial_sp符號引用了同文件“STACK”節區。也許我們對啟動文件不熟悉,不清楚這究竟是什麼,那我們繼續瀏覽,可看到 main.o文件的引用說明,如說明 main.o 文件的 i.main 節區為它使用的 LED_GPIO_Config 符號引用了 bsp_led.o 文件的 i.LED_GPIO_Config 節區。

有時在構建工程的時候,編譯器會輸出 “Undefined symbol xxx (referred from xxx.o)” 這樣的提示,該提示的原因就是在鏈接過程中,某個文件無法在外部找到它引用的標號,因而產生鏈接錯誤。


2、刪除無用節區

map 文件的第二部分是刪除無用節區的說明,見代碼清單 51-11。

STM32的map文件學習筆記


這部分列出了在鏈接過程它發現工程中未被引用的節區,這些未被引用的節區將會被刪除(指不加入到.axf 文件,不是指在.o 文件刪除),這樣可以防止這些無用數據佔用程序空間。

例如,上面的信息中說明 startup_stm32f429_439xx.o 中的 HEAP(在啟動文件中定義的用於動態分配的“堆”區)以及 stm32f4xx_adc.o 的各個節區都被刪除了,因為在我們這個工程中沒有使用動態內存分配,也沒有引用任何 stm32f4xx_adc.c 中的內容。由此也可以知道,雖然我們把 STM32 標準庫的各個外設對應的 c 庫文件都添加到了工程,但不必擔心這會使工程變得臃腫,因為未被引用的節區內容不會被加入到最終的機器碼文件中。

對於這個部分功能,用戶最好將 MDK 中這個選項勾上,然後全編譯工程,效果會比較好:

STM32的map文件學習筆記


3、符號映像表

map 文件的第三部分是符號映像表(Image Symbol Table), 見代碼清單 51-12。

STM32的map文件學習筆記


這個表列出了被引用的各個符號在存儲器中的具體地址、佔據的空間大小等信息。如我們可以查到LED_GPIO_Config 符號存儲在 0x080002a5 地址,它屬於 Thumb Code 類型,大小為 106 字節,它所在的節區為 bsp_led.o 文件的 i.LED_GPIO_Config 節區。


4、存儲器映像索引

map 文件的第四部分是存儲器映像索引(Memory Map of the image), 見代碼清單:

STM32的map文件學習筆記


映像文件可以分為加載域(Load Region)和運行域(Execution Region) 。簡單的說,加載域就是程序在 Flash 中的實際存儲,而運行域是芯片上電後的運行狀態,通過下面的框圖可以有一個感性的認識:

STM32的map文件學習筆記


通過上面的框圖可以看出,RW 區也是要存儲到 ROM/Flash 裡面的,在執行映像之前,必須將已初始化的 RW 數據從 ROM 中複製到 RAM 中的執行地址並創建 ZI Section(初始化為 0 的變量區)。

本工程的存儲器映像索引分為 ER_IROM1 及 RW_IRAM1 部分,它們分別對應 STM32內部 FLASH 及 SRAM 的空間。相對於符號映像表,這個索引表描述的單位是節區,而且它描述的主要信息中包含了節區的類型及屬性,由此可以區分 Code、 RO-data、 RW-data及 ZI-data。

例如,從上面的表中我們可以看到 i.LED_GPIO_Config 節區存儲在內部 FLASH 的0x080002a4 地址,大小為 0x00000074,類型為 Code,屬性為 RO。而程序的 STACK 節區(棧空間)存儲在 SRAM 的 0x20000000 地址,大小為 0x00000400,類型為 Zero,屬性為RW(即 RW-data) 。


5、映像組件大小

map 文件的最後一部分是包含映像組件大小的信息(Image component sizes),這也是最常查詢的內容,見代碼清單 :

STM32的map文件學習筆記


這部分包含了各個使用到的*.o 文件的空間彙總信息、整個工程的空間彙總信息以及佔用不同類型存儲器的空間彙總信息,它們分類描述了具體佔據的 Code、 RO-data、 RW-data及 ZI-data 的大小,並根據這些大小統計出佔據的 ROM 總空間。

綜合整個 map 文件的信息,可以分析出,當程序下載到 STM32 的內部 FLASH 時,需要使用的內部 FLASH 是從 0x0800 0000 地址開始的大小為 1456 字節的空間;當程序運行時,需要使用的內部 SRAM 是從 0x20000000 地址開始的大小為 1024 字節的空間。


總結

對照著這個map文件再看看我的程序,就可以知道哪裡佔的flash空間多了。硬件相關的部分已經用寄存器來操作,協議處理部分佔用的flash空間最多。

最後,對於.map文件,我們一般只需要瞭解最後幾行即可。如果想要深入學習,可以參照野火及安富萊的教程文檔進行學習。


分享到:


相關文章: