stm32的儲存器結構

2021-08-11 11:05:34 字數 4382 閱讀 9391

首先,先看一下

stm32

的儲存器結構。

flash

,sram

暫存器和輸入輸出埠被組織在同乙個

4gb的線性位址空間內。可訪問的儲存器空間被分成

8個主要塊,每個塊為

512mb

。flash

sram

是儲存執行程式中的資料,sram是ram的一種。

所以,只要你不外擴儲存器,寫完的程式中的所有東西也就會出現在這兩個儲存器中。 1.

stm32中的堆疊

。首先要說明的是微控制器是一種積體電路晶元,整合

cpu、

ram、

rom、多種

i/o口和中斷系統、定時器

/計數器等功能。

cpu中包括了各種匯流排電路,計算電路,邏輯電路,還有各種暫存器。

stm32

有通用暫存器r0‐

r15 

以及一些特殊功能暫存器

,其中包括了堆疊指標暫存器。當

stm32

正常執行程式的時候,來了乙個中斷,

cpu就需要將暫存器中的值壓棧到

ram裡,然後將資料所在的位址存放在堆疊暫存器中。等中斷處理完成退出時,再將資料出棧到之前的暫存器中,這個在

c語言裡是自動完成的。

2.stm32的堆疊大小

定義大小在startup_stm32f2xx.s

stack_size      equ     0x00000400

area    stack, noinit, readwrite, align=3

stack_mem       space   stack_size

__initial_sp

; heap configuration

;   heap size (in bytes) <0x0-0xffffffff:8>;

heap_size       equ     0x00000200

area    heap, noinit, readwrite, align=3

__heap_base

3.stm32的堆疊位置

通過map檔案可知(在目標工程欄-->>雙擊工程名,就會在keil檔案顯示框出現map檔案)

heap                                     0x200106f8   section      512  startup_stm32f2xx.o(heap)

stack                                   0x200108f8   section     1024  startup_stm32f2xx.o(stack)

__heap_base                         0x200106f8   data           0  startup_stm32f2xx.o(heap)

__heap_limit                           0x200108f8   data           0  startup_stm32f2xx.o(heap)

__initial_sp                             0x20010cf8   data           0  startup_stm32f2xx.o(stack)

顯然 cortex-m3資料可知:__initial_sp是堆疊指標,它就是flash的0x8000000位址前面4個位元組(它根據堆疊大小,由編譯器自動生成)

顯然堆和棧是相鄰的。

4.stm32的堆和棧的空間分配

棧:向低位址擴充套件

堆:向高位址擴充套件

顯然如果依次定義變數

先定義的棧變數的記憶體位址比後定義的棧變數的記憶體位址要大

先定義的堆變數的記憶體位址比後定義的堆變數的記憶體位址要小 

5.程式設計中的堆疊。

在程式設計中很多時候會提到堆疊這個東西,準確的說這個就是

ram中的乙個區域。我們先來了解幾個說明

:

(1)

程式中的所有內容最終只會出現在

flash

,ram

裡(不外擴)。

(2)段的劃分,是將類似資料種類儲存在乙個區域裡,方便管理,但正如上面所說,不管什麼段的資料,都是最終在

flash

和ram

裡面。重點分析一下

stm32

以及在mdk

裡面段的劃分。

mdk下

code,ro-data,rw-data,zi-data

這幾個段:

code

是儲存程式**的。 ​

ro-data

是儲存const

常量和指令。 ​

rw-data

是儲存初始化值不為

0的全域性變數。 ​

zi-data

是儲存未初始化的全域性變數或初始化值為

0的全域性變數。

flash=code + ro-data + rw-data;

ram= rw-data+zi-data;

這個是mdk編譯之後能夠得到的每個段的大小,也就能得到占用相應的

flash

和ram

的大小,但是還有兩個資料段也會占用

ram,但是是在程式執行的時候,才會占用,那就是堆和棧。在

stm32

的啟動檔案

.s檔案裡面,就有堆疊的設定,其實這個堆疊的記憶體占用就是在上面

ram分配給

rw-data+zi-data

之後的位址開始分配的。

這裡為什麼在

flash

中加了rw-data

還要在ram

中加上呢,原因是在初始化時rw-data從flash拷貝到ram中,掉電後資料依然是在flash中的。

:是編譯器呼叫動態記憶體分配的記憶體區域。棧:

是程式執行的時候區域性變數的地方,所以區域性變數用陣列太大了都有可能造成棧溢位。

堆疊的大小在編譯器編譯之後是不知道的,只有執行的時候才知道,所以需要注意一點,就是別造成堆疊溢位了。。。不然就等著

hardfault

找你吧。

舉例:

flash=

4164+336+56=0x11cc

ram=

56+1832=0x760

那麼:堆疊指標指向的位置就是0x20000760

os中的堆疊及其記憶體管理。

嵌入式系統的堆疊,不管是用什麼方法來得到記憶體,感覺他的方式都和程式設計中的堆差不多。目前我知道兩種獲得記憶體情況:

(1)用龐大的全域性變數陣列來圈住一塊記憶體,然後將這個記憶體拿來進行記憶體管理和分配。這種情況下,堆疊占用的記憶體就是上面說的:如果沒有初始化陣列,或者陣列的初始化值為0,堆疊就是占用的ram的

zi-data部分;如果陣列初始化值不為0,堆疊就占用的ram的

rw-data部分。這種方式的好處是容易從邏輯上知道資料的來由和去向。

(2)​

就是把編譯器沒有用掉的

ram部分拿來做記憶體分配,也就是除掉

rw-data+zi-data+

編譯器堆

+編譯器棧後剩下的

ram記憶體中的一部分或者全部進行記憶體管理和分配。這樣的情況下就只需要知道記憶體剩下部分的首位址和記憶體的尾位址,然後要用多少記憶體,就用首位址開始挖,做乙個鍊錶,把記憶體獲取和釋放相關資訊鏈結起來,就能及時的對記憶體進行管理了。記憶體管理的演算法多種多樣,不詳說,這樣的情況下:

os的記憶體分配和自身區域性變數或者全域性變數不衝突,之前我就在這上面糾結了很久,以為函式裡面的變數也是從系統的動態記憶體中得來的。這種方式感覺更加能夠明白自己位址的開始和結束。

這兩種方法我感覺沒有誰更高明,因為只是乙個記憶體的獲取方式,高明的在於記憶體的管理和分配。

7.stm32的堆疊生長方向和儲存模式。

大端格式(big-endian)

小端格式(little-endian)

資料0x12345678儲存格式

大端格式

低位址高位址

小端格式

低位址高位址

stm32是向下生長,採用的是小端儲存。

stm32儲存結構 儲存器對映

問題 1 什麼是儲存器對映?是怎麼乙個運作過程?2 stm32總體架構 3 cm3核心結構 1 stm32系統結構 要想深刻理解stm32的儲存器,需要首先知道stm32的系統結構。如figure 1,是stm32系統結構框圖。根據stm32 reference manual rm0008 中的描述...

STM32儲存器結構 儲存器對映

問題 1 什麼是儲存器對映?是怎麼乙個運作過程?2 stm32總體架構 3 cm3核心結構 以下 1 stm32系統結構 要想深刻理解stm32的儲存器,需要首先知道stm32的系統結構。如figure 1,是stm32系統結構框圖。根據stm32 reference manual rm0008 中...

STM32儲存結構(2)

當我們在完成某乙個實驗,當我們正慶幸的時候,我們不由得產生一種不安的想法 我們是否已經少許明白其中的種種細節?尤其,當我們所有的事情都依賴於編譯環境或firmware,抑或他人的程式,而自己僅僅是copy和modify,以致using。當你還是乙個初學者的時候,或許不會太過於關注於此,但是要想提高自...