STM32的Code/RO/RW/ZI區、Flash/Ram的佔用情況、堆棧大小Stack_Size/Heap_Size的設置

以cortex-M3爲例,例如STM32F103

 

這篇文章要講2個問題:

1、編譯出的程序(指令)、變量的存放位置、大小?
2、在代碼和keil中,“堆、棧”兩者的大小如何設置?

 

keil編譯完成後,會有提示,形如:

Program Size: Code=1148 RO-data=424 RW-data=20 ZI-data=1636  

其中:
① Code爲代碼,本質上就是一大堆ARM指令;
② RO爲只讀的數據,例如,char *name = "TOM";//TOM三個字符就存放在ROM中作爲RO-DATA;又如,爲了減小sin的計算量,把sin的各個值直接製作成表,const float sinVal[]= {.....};
③ RW爲非初始化的全局和靜態變量佔用的RAM大小,同時還要佔用等量的ROM大小用於存放這些非0變量的初值;
④ ZI爲0初始化的內存區的大小(該區域3個用途:0初始化的全局和靜態變量+堆區+棧區)。

下面是keil自動生成的.map文件中的信息:

Flash的佔用量就是上圖中ROM Size的大小,它包含了①+②+③的大小【ARM指令代碼+只讀數據+非0初始化變量的初值】
RAM的佔用量包含上述③+④的大小,也即【非0初始化變量、0初始化RAM(又分爲0初始化靜態變量區+堆區+棧區)】

 

我們用jflash或者其他軟件打開hex文件,看一下前四個字節:

0x2000678-0x2000000=0x678=1656,而觀察一下前文編譯出的信息,正好1656 = RW-data(1636) +  ZI-data(20)的大小,這就證明了RAM的大小確實=RW+ZI的大小。

注:hex文件的前4個字節爲主堆棧指針MSP的初值。

 

 

在STM32的啓動文件(.s彙編文件)中,一開始我們會看到 Stack_Size、Heap_Size 這兩個彙編宏定義:

 

Stack指的是棧,棧是由堆棧指針MSP/PSP自動管理的,理論上初始化時給堆棧指針賦值爲RAM的最高地址即可,但是用keil編譯時,keil並不是按RAM的最高地址生成的HEX前4字節(也即MSP的初值),而是按照:全局和靜態變量的容量+Heap_Size+Stack_Size三者之和,作爲HEX文件的前4字節。

設置某塊芯片的RAM的總大小,是在keil的這個地方設的:

其實講道理,我覺得keil還是把這個值+RAM起始地址(0x2000000)作爲MSP的初值更好,只不過keil不是這麼做的,keil僅僅是把這個值用作編譯檢測:檢查全局和局部靜態變量(含0初始化和非0初始化兩部分)所佔的空間+堆區+棧區,它們所佔空間之和是否超過了上圖紅框裏的這個值,如果超了就編譯報錯。這就是上面紅框裏的值唯一的作用。

根據這段理論,我們也就知道了啓動文件中Stack_Size該設爲多少了,只要【全局變量+局部靜態變量+Heap_Size+Stack_Size】的大小不超過芯片的RAM容量即可。
keil編譯時,會把C庫函數支持的malloc、free所需的內存指向heap內存區,並且當我們不斷的malloc吃內存堆時,malloc函數會檢測程序已吃掉的內存堆是否超過了Heap_Size,超了的話就會返回NULL。
keil是這樣爲【全局變量 + 局部靜態變量 + Heap_Size + Stack_Size】分配內存的:

上面論述的是,使用C庫函數提供的mallloc時,內存堆heap的使用情形,如果我們不打算使用C庫提供的動態內存分配,而打算使用自己寫的內存堆管理程序,甚至乾脆不打算使用動態內配功能,這些情況下,請直接把Heap_Size設爲0。

 

最後總結一下Stack_Size的設置方法:①在keil中正確設置芯片的RAM大小, ②確定堆區Heap_Size的大小,這個值可以通過調試自己估計出來,如果不使用C庫的malloc的話,直接設爲0,③把Stack_Size設的越大越好,只要編譯不報錯,就把Stack_Size往儘可能大了配。over

 

PS:自己寫的動態內存管理程序,本質上就是申請一個大數組,自己管理這個數組而已,相當於自己寫一套malloc/free函數,很多操作系統中有這樣的例子,比如freeRtos、ucos等,這些操作系統都提供了好多種動態內存管理方法,最簡單的一種,跟切火腿似的,malloc出來之後就釋放不掉了,直到把這個大數組切完拉倒,看似很low的內存管理方法,實際上在很多小型項目上卻用起來很方便。更好的內存管理程序,那自然是支持動態切,還要支持把動態釋放的空間合併起來,以便把剛纔合併起來的空間再次malloc,這些更好的內存管理程序,用起來更方便,但是同時,這種功能強大的內存管理程序自身也會佔掉很多RAM / ROM / CPU資源,矛盾利弊共存。到底要使用簡單的內存管理還是高級的內存管理,要看項目需求,一般嵌入式操作系統會提供4種以上的內存管理程序供我們選用。

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章