在KEIL下查看單片機編程內存使用情況


原文鏈接:https://blog.csdn.net/D_azzle/article/details/83410141

 

轉載並整理:

---------------------------------------------

截至到目前為止,本人接觸單片機也有將近一年的時間。這一年以來也接觸過了很具代表性的單片機,比如51、HT32、STM32等等。但是呢對於單片機的內存一直不了解,一直到現在,在一次單片機編程時我用到了malloc函數為指針分配內存空間。不知道為什么內存一直分配不成功。

所以這才去了解單片機的內存。下圖是KELI編譯成功后的輸出信息。

 

在這里,我們先只關心Program Size這一行:

Code:代碼指令占用的空間;

RO-data:Read Only Data的縮寫。它的意義是只讀常量占用的空間,比如const型常量、字符串常量等等;

           RW-data:Read Write Data的縮寫。它的意義是可讀可寫並且已初始化了的遍歷所占用的空間,比如全局變量,靜 態變量等等;

           ZI-data:Zero Initialize Data的縮寫。它的意義是以0初始化的變量,比如未初始化賦值的全局變量、靜態變量等等;

而對單片機燒寫程序時,FLASH被占用的空間大小為:Code + RO Data + RW Data,但是程序運行時使用到的RAM空間大小為:RW Data + ZI Data。

 

Why?

FALSH中被占用的空間 == 代碼指令  + 只讀數據值 + 已初始化變量的值。那么為什么程序運行時占用RAM空間大小 == RW Data + ZI Data呢?

我們都知道,在代碼運行機制上單片機不同於PC,單片機的程序通常是在FALSH中直接取指執行,而PC是先把程序拷貝到RAM中再取指執行。因此單片機的RAM中不會存在Code拷貝(除非使用特殊方法強行使程序拷貝到了RAM中執行)。另外單片機RAM中也不會存在RO-data拷貝,因為RO-data是只讀數據,為了節省RAM空間,這種數據在執行時直接從FLASH中取出使用,無需再復制到RAM。又由於RW Data和ZI Data是可讀可寫數據,為了供程序運行時正常讀寫,於是就會被放在單片機的RAM中(單片機的FLASH區不能被程序改寫)

那么對於局部變量來說(RW Data和ZI data都是指的是全局變量或者靜態變量),在C語言中全局變量和靜態變量在RAM中都有一個特定的地址(存於靜態區),而局部變量沒有特定的地址。因此局部變量會被存放於堆棧中,當函數入棧時系統就會在棧頂開辟一段內存供局部變量使用,函數出棧時該內存就會被釋放掉(靜態局部變量除外)。

 

那么單片機程序在運行時RAM的使用量就等於RW Data + ZI Data了嗎?還有沒有其他因素會導致RAM占用變化?

玩過PC的都知道,一個程序在運行時它在內存中的占用情況是會隨時改變的,這其中可能有壓棧入棧和堆塊的申請與釋放等事件發生,那么在單片機里難道就沒有這樣的過程了嗎?

其實單片機的RAM中也有堆棧區,因此程序運行時RAM的使用量就不會再等於RW Data + ZI Data了。(STM32的堆棧是存放於SRAM中的)而是等於 RW Data + ZI Data + Stack_Size + Heap_Size;

另外編譯器並不會給變量一個內存,而是在內存中為變量指定一個地址,然后讓其他變量不會重復指向該地址。在編譯時編譯器會把變量名用地址替換掉,這樣也就達到了“編譯器給變量分配了內存”的效果。那么,因為編譯器為每個變量分配地址且不會讓該地址被占用,由此可知RW Data 和 ZI Data這兩塊數據在被分配好內存之后一直會處於無法被回收的狀態。因此如果沒有新的程序燒錄至單片機,RW Data + ZI Data區占用的空間是不會變的。

而對於堆棧區,堆棧區的大小是由啟動文件確定的。函數入棧、出棧的過程變化的只是區內的數據而不是堆棧區的大小(入棧數量超過了棧區的大小限制則為爆棧)。因此沒有新的程序燒錄至單片機,堆棧區的大小也不會改變。

 

結論:ARM單片機中的FLASH占有量 == Code + RO Data + RW Data,程序運行時RAM的占有量 == RW Data + ZI Data + Stack_Size + Heap_Size

 

 

 


免責聲明!

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



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