對于使用RTOS進行項目開發的朋友可能會有這樣的疑惑,我創建的任務到底需要多大的堆棧空間才夠呢?
其實,除了使用RTOS開發,就是使用裸機進行開發的朋友同樣也會遇到類似的問題,有些地方需要很大的堆棧,對系統堆棧的分配就有必要知道其大小,如果分配不充分,很有可能導致內存溢出。
之前就有小伙伴問:我的代碼經常運行到“HardFault_Handler”、 “MemManage_Handler”異常中斷里面去了,是什么原因導致的呢?
當我們遇到內存溢出現象時,查看map文件,很快就能找到那些代碼占用了多少空間。
還有很多小伙伴問:我代碼、內存占用的資源如何查看呢?當你們了解了map文件里面的內容,以上問題就一目了然了。
輸出map配置
在工程中,默認是輸出了map文件,如果沒有輸出,需要如下配置:
當按照上面配置勾選了“生產map”文件,就可以看到如下情況:
下面才是重點,就讓我給大家詳細講述一下IAR中map文件的重要內容。map文件主要分為六大塊,詳情見下面章節。
Ⅰ、MAIN INIF
Ⅲ、PLACEMENT SUMMARY
Ⅳ、INIT TABLE
Ⅴ、MODULE SUMMARY
Ⅵ、ENTRY LIST
Ⅰ
MAIN INIF主要信息
這段信息比較簡單,關于map文件的主要信息。包含:IAR版本、日期、輸出文件路徑、map文件路徑等。
Ⅱ
RUNTIME MODEL ATTRIBUTES
RUNTIME MODEL ATTRIBUTES:運行時MODEL屬性。這部分顯示相關屬性等信息,可以不用深入理解。
Ⅲ
PLACEMENT SUMMARY
PLACEMENT SUMMARY:概述位置,即各Section(段)存儲的位置。
1.總體概述
"A0": place at 0x08000000 { ro section .intvec };
"P1": place in [from 0x08000000 to 0x0801ffff] { ro };
"P2": place in [from 0x20000000 to 0x20004fff] { rw, block CSTACK, block HEAP };
意思是:
"A0"段位于0x08000000,類型為intvec(初始化向量);
"P1"段位于0x08000000 至 0x0801ffff區域,類型為ro;
"P2"段位于0x20000000 至0x20004fff區域,類型包含:rw, block CSTACK, block HEAP;
2.詳細說明
Section Kind Address Size Object
段 類型 地址 大小 目標位置
"A0": 0xec
.intvec ro code 0x08000000 0xec startup_stm32f10x_md.o [1]
- 0x080000ec 0xec
意思是:
"A0"段總共大小為0xec;
其中“.intvec”段類型為ro,地址0x08000000,大小0xec,位于
startup_stm32f10x_md文件;
"A0"段結束地址為0x080000ec,總共大小0xec。
提示:
段與類型一般有對應關系
Section Kind
"A1":
.intvec ro code(ro代碼)
"P1":
.text ro code(ro代碼)
.rodata const (常量)
CODE ro code(ro代碼)
.iar.init_table const(常量)
Initializer bytes ro data(ro數據)
"P2":
.data inited(已初始化數據)
.bss zero(未初始化數據 零)
Ⅳ
INIT TABLE
INIT TABLE:初始化表,類似于上面第三部分內容,這里是針對RAM存儲地址。
Ⅴ
MODULE SUMMARY
MODULE SUMMARY:概述模塊,主要概述文件于庫(模塊)所占ro代碼大小、rw數據大小。
Ⅵ
ENTRY LIST
ENTRY LIST:入口列表,包含函數、變量等入口地址。
其中Entry(入口)主要包含兩大類:函數和變量。
函數:全局函數、靜態函數
變量:全局變量、(文件內)靜態變量、(函數內)靜態變量
入口 地址 大小 類型 目標
Entry Address Size Type Object
main 0x08000317 0x5e Code Gb main.o [1]
SetSysClock 0x08000141 0x8 Code Lc system_stm32f10x.o
gVar 0x20000000 0x4 Data Gb main.o [1]
sVar_E 0x20000004 0x4 Data Lc main.o [1]
main::sVar_I 0x20000008 0x4 Data Lc main.o [1]
從上面列表的差異可以看到出來主要包含五類:
1.“全局”函數
入口:main,為全局函數接口;
地址:0x08000317,代表存儲在FLASH;
大小:0x5e,該入口函數大小為0x5e;
類型:Code Gb,其中code說明為代碼,Gb說明為“全局的”函數(Global);
目標:main.o,該入口函數位于main.c文件下面。
2.“靜態”函數
靜態函數也就是在函數前加“static”.
SetSysClock位于system_stm32f10x.c文件下,可以看到前面加了“static”。
類型為Code Lc,即靜態(局部Local)函數;
3.全局變量
全局變量也叫“全局數據”,因為它的類型為“Data Gb”。
從地址0x20000000可以看得出,它是位于RAM區域,也就是內存中。
(提示:只有全局和靜態的變量才會在編譯之后決定在RAM中的地址,定義在函數體里面的局部變量只有在程序運行時才會分配地址,也就是說局部變量位于堆棧中)。
4.(文件內)靜態變量
使用static關鍵字定義的變量,只有在當前文件內使用,所以它屬于靜態(“局部”Local)變量。
5.(函數內)靜態變量
它和“(文件內)靜態變量”類似,屬于靜態變量,只是它定義在函數體內的。
從入口“main::sVar_I”可以看得出,變量sVar_I定義在main函數體內。
map文件的最后有如下一段信息:
[1] = C:\Users\Administer\Desktop\Demo\Debug\Obj
[2] = command line
[3] = dl7M_tln.a
[4] = m7M_tls.a
[5] = rt7M_tl.a
[6] = shb_l.a
130 157 bytes of readonly code memory
18 736 bytes of readonly data memory
121 508 bytes of readwrite data memory
Errors: none
Warnings: none
相信大家都會明白,信息就是所有代碼、內存塊匯總的。而這條信息也會在編譯窗口中顯示出來。
-
內存
+關注
關注
8文章
3019瀏覽量
74005 -
IAR
+關注
關注
5文章
350瀏覽量
36665 -
RTOS
+關注
關注
22文章
811瀏覽量
119595 -
MAP
+關注
關注
0文章
49瀏覽量
15137
發布評論請先 登錄
相關推薦
評論