說說STM32的堆棧與內存

1.概念
這裏所說的堆棧,是針對單片機所說的「堆」與「棧」,指的是內存中一片特殊用途的區域。而不是數據結構中的堆棧(雖然其實規則同樣)。程序員

這裏所說的內存,是指RAM,RAM包括SRAM,DRAM等。而不是什麼手機內存卡之類。數組

這裏所說的flash,指的是用做爲ROM的存儲器,保存代碼與常量數據。而不是動畫製做。。。數據結構

棧的生長方向:指的是入棧方向,從高地址向低地址生長叫作向下生長,或逆向生長;反過來就叫向上生長,或正向生長。STM32的棧是向下生長。函數

2.內存中的堆棧安排
確切地說,是keil mdk根據STM32的特性,對stm32的RAM甚至flash進行部署。動畫

編譯工程後,在生成的.map文件裏能夠看到具體的安排。雙擊工程界面的工程根目錄文件夾圖標,能夠打開.map文件。若是找不到文件,能夠在option->listing->linker listing 裏勾選 Memory map;spa

map文件內的兩部分Image Symbol Table與Memory Map of the image列出了RAM與ROM的內容,最後還有一些統計。blog

map文件跟下圖有很大關係:(這裏雖然我使用的是GD32,但跟STM32同樣)
內存

3.MAP文件與堆棧
網上你有可能會看到這些說法:字符串

(1)棧區(stack):由編譯器自動分配和釋放,存放函數的參數與返回值、局部變量等,其操做方式相似於數據結構中的棧。
(2)堆區(heap):由程序員分配管理。
(3)全局區與靜態區:存儲全局變量和靜態變量,其中初始化的全局變量和靜態變量在一塊區域,未初始化的全局變量和未初始化的靜態變量在相鄰的另外一塊區域。
(4)文字常量區:常量字符串存放。
(5)程序代碼區:存放程序代碼。部署

可能這樣仍是有點不明不白,那麼打開map文件你就會很具體地看到這些。

Execution Region RW_IRAM1:程序運行時的內存分佈

0X20000000是RAM開始地址。能夠看到各段的分佈。從低地址到高地址,分別爲:data段,bss段,heap段,stack段。包含對應上面所說的(1)(2)(3)。

0X08000000是ROM(flash)開始地址。能夠看到constdata(常量),和函數代碼,對應上面的(4)(5);

其中,data指的是初始化不爲0的全局或靜態(static)變量。bss指的是沒有初始化,或者初始化爲0的全局或靜態變量。一開始我也不理解什麼初始化之類,感受莫名其妙甚至自相矛盾。其實知道爲何這麼安排就很容易理解了。

由於全局與靜態變量的初始值,是須要保存下來,其基本能夠分爲三大類,一種是等於0的,一種是不等於0,還有一種是沒有初始值的。這些都是須要記錄下來保存在鏡像文件裏面,再燒錄到單片機的flash裏(固然非要寫到ram也能夠)。爲了節省空間,就把等於0的變量和沒有初始值的變量歸爲一類,都當作初始值等於0的變量處理。由於這些變量的初始值都爲0,因此記錄也方便,節省很多空間。好比定義一個500字節的全局數組,要是初始值已經定義,那麼鏡像文件也須要相應大小的空間記錄下來。可是若是所有爲0,或者沒有定義初始值。那麼,從原理上來講,只需記錄數組長度,賦予BSS「屬性」,就OK得。

程序在開始運行的時候,通常要作內存搬運的操做,好比將data段,bss段,heap段,stack段初始化爲對應的值。

由此也可知,在keil mdk中,沒有初始值的全局變量或者靜態變量,其實等於0。但局部普通變量並非,必定要初始化再使用。

上圖是符號表中Global Symbols的一部分,能夠看到內存開始地址0X20000000,放置的是SystemCoreClock這個變量,這個是系統時鐘頻率,初始時不爲0,後面記上(.data)。後面的Boot_buf變量,大小爲1024,標記爲(.bss)。

 

上圖是符號表中Local Symbols的一部分。能夠看到另一些變量符號,還能看到,constdata(常量)是保持着flash裏(地址爲0x08XX XXXX)。

相關文章
相關標籤/搜索