0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

詳解STM32堆棧

GReq_mcu168 ? 來源:硬件攻城獅 ? 作者:硬件攻城獅 ? 2022-03-11 09:51 ? 次閱讀

學(xué)習(xí)STM32單片機(jī)的時候,總是能遇到“堆?!边@個概念。分享本文,希望對你理解堆棧有幫助。

對于了解一點匯編編程的人,就可以知道,堆棧是內(nèi)存中一段連續(xù)的存儲區(qū)域,用來保存一些臨時數(shù)據(jù)。堆棧操作由PUSH、POP兩條指令來完成。而程序內(nèi)存可以分為幾個區(qū):

棧區(qū)(stack)

堆區(qū)(Heap)

全局區(qū)(static

文字常亮區(qū)程序代碼區(qū)

程序編譯之后,全局變量,靜態(tài)變量已經(jīng)分配好內(nèi)存空間,在函數(shù)運行時,程序需要為局部變量分配??臻g,當(dāng)中斷來時,也需要將函數(shù)指針入棧,保護(hù)現(xiàn)場,以便于中斷處理完之后再回到之前執(zhí)行的函數(shù)。
棧是從高到低分配,堆是從低到高分配。
普通單片機(jī)與STM32單片機(jī)中堆棧的區(qū)別
普通單片機(jī)啟動時,不需要用bootloader將代碼從ROM搬移到RAM。

但是STM32單片機(jī)需要。

這里我們可以先看看單片機(jī)程序執(zhí)行的過程,單片機(jī)執(zhí)行分三個步驟:

取指令

分析指令

執(zhí)行指令

根據(jù)PC的值從程序存儲器讀出指令,送到指令寄存器。然后分析執(zhí)行執(zhí)行。這樣單片機(jī)就從內(nèi)部程序存儲器去代碼指令,從RAM存取相關(guān)數(shù)據(jù)。

RAM取數(shù)的速度是遠(yuǎn)高于ROM的,但是普通單片機(jī)因為本身運行頻率不高,所以從ROM取指令慢并不影響。

而STM32的CPU運行的頻率高,遠(yuǎn)大于從ROM讀寫的速度。所以需要用bootloader將代碼從ROM搬移到RAM。

使用棧就象我們?nèi)ワ堭^里吃飯,只管點菜(發(fā)出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等準(zhǔn)備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。使用堆就象是自己動手做喜歡吃的菜肴,比較麻煩,但是比較符合自己的口味,而且自由度大。

其實堆棧就是單片機(jī)中的一些存儲單元,這些存儲單元被指定保存一些特殊信息,比如地址(保護(hù)斷點)和數(shù)據(jù)(保護(hù)現(xiàn)場)。

如果非要給他加幾個特點的話那就是:

這些存儲單元中的內(nèi)容都是程序執(zhí)行過程中被中斷打斷時,事故現(xiàn)場的一些相關(guān)參數(shù)。如果不保存這些參數(shù),單片機(jī)執(zhí)行完中斷函數(shù)后就無法回到主程序繼續(xù)執(zhí)行了。

這些存儲單元的地址被記在了一個叫做堆棧指針(SP)的地方。

結(jié)合STM32的開發(fā)講述堆棧

從上面的描述可以看得出來,在代碼中是如何占用堆和棧的。可能很多人還是無法理解,這里再結(jié)合STM32的開發(fā)過程中與堆棧相關(guān)的內(nèi)容來進(jìn)行講述。

如何設(shè)置STM32的堆棧大???

在基于MDK的啟動文件開始,有一段匯編代碼是分配堆棧大小的。

d6e99b46-59c0-11ec-b2e9-dac502259ad0.png

這里重點知道堆棧數(shù)值大小就行。還有一段AREA(區(qū)域),表示分配一段堆棧數(shù)據(jù)段。數(shù)值大小可以自己修改,也可以使用STM32CubeMX數(shù)值大小配置,如下圖所示。

d710eb4c-59c0-11ec-b2e9-dac502259ad0.png

STM32F1默認(rèn)設(shè)置值0x400,也就是1K大小。

Stack_Size EQU 0x400

函數(shù)體內(nèi)局部變量:

void Fun(void){ char i; int Tmp[256]; //...}

局部變量總共占用了256*4 + 1字節(jié)的??臻g。所以,在函數(shù)內(nèi)有較多局部變量時,就需要注意是否超過我們配置的堆棧大小。

函數(shù)參數(shù):

voidHAL_GPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef *GPIO_Init)

這里要強(qiáng)調(diào)一點:傳遞指針只占4字節(jié),如果傳遞的是結(jié)構(gòu)體,就會占用結(jié)構(gòu)大小空間。提示:在函數(shù)嵌套,遞歸時,系統(tǒng)仍會占用??臻g。

堆(Heap)的默認(rèn)設(shè)置0x200(512)字節(jié)。

Heap_Size EQU 0x200

大部分人應(yīng)該很少使用malloc來分配堆空間。雖然堆上的數(shù)據(jù)只要程序員不釋放空間就可以一直訪問,但是,如果忘記了釋放堆內(nèi)存,那么將會造成內(nèi)存泄漏,甚至致命的潛在錯誤。

MDK中RAM占用大小分析

經(jīng)常在線調(diào)試的人,可能會分析一些底層的內(nèi)容。這里結(jié)合MDK-ARM來分析一下RAM占用大小的問題。在MDK編譯之后,會有一段RAM大小信息:

d736d352-59c0-11ec-b2e9-dac502259ad0.png

這里4+6=1640,轉(zhuǎn)換成16進(jìn)制就是0x668,在進(jìn)行在調(diào)試時,會出現(xiàn):

d74b3360-59c0-11ec-b2e9-dac502259ad0.png

這個MSP就是主堆棧指針,一般我們復(fù)位之后指向的位置,復(fù)位指向的其實是棧頂:

d75dbd46-59c0-11ec-b2e9-dac502259ad0.png

而MSP指向地址0x20000668是0x20000000偏移0x668而得來。具體哪些地方占用了RAM,可以參看map文件中【Image Symbol Table】處的內(nèi)容:

d76af862-59c0-11ec-b2e9-dac502259ad0.png

審核編輯 :李倩

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • STM32
    +關(guān)注

    關(guān)注

    2257

    文章

    10828

    瀏覽量

    352470
  • 堆棧
    +關(guān)注

    關(guān)注

    0

    文章

    176

    瀏覽量

    19668

原文標(biāo)題:詳解STM32堆棧

文章出處:【微信號:mcu168,微信公眾號:硬件攻城獅】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    STM32堆棧增長方向問題

    STM32堆棧增長方向是從高地址往低地址增長的,這樣的話底應(yīng)該是高地址咯。而下圖的底卻是低地址,查了很多資料,感覺都很矛盾。像INT8UOSTaskCreateExt 的第三個參
    發(fā)表于 04-20 04:36

    詳解STM32單片機(jī)的堆棧

    ,程序需要為局部變量分配空間,當(dāng)中斷來時,也需要將函數(shù)指針入,保護(hù)現(xiàn)場,以便于中斷處理完之后再回到之前執(zhí)行的函數(shù)。 是從高到低分配,是從低到高分配。普通單片機(jī)與
    發(fā)表于 01-12 11:30

    C語言單片機(jī)、堆棧的區(qū)別是什么?

    C語言單片機(jī)、堆棧的區(qū)別是什么?
    發(fā)表于 10-13 08:09

    怎樣去設(shè)置STM32堆棧空間的大小呢

    怎樣去設(shè)置STM32堆棧空間的大小呢?STM32有哪幾種調(diào)節(jié)堆棧空間大小的方式?
    發(fā)表于 10-21 07:33

    STM32堆棧的地址是怎么得出來的?

    STM32堆棧的地址是怎么得出來的?
    發(fā)表于 11-26 07:14

    什么是?什么是

    ,程序執(zhí)行過程中溢出,極大可能的影響程序、系統(tǒng)的穩(wěn)定,嚴(yán)重時會造成程序、系統(tǒng)的崩潰,所以堆棧溢出檢測十分重要且必要。什么是,什么是
    發(fā)表于 12-22 06:09

    STM32堆棧區(qū)劃分

    STM32堆棧區(qū)(一)一個由C/C++編譯的程序占用的內(nèi)存分為以下幾個部分:區(qū)(stack):編譯器自動分配釋放,存放函數(shù)的參數(shù)值,局部變量的值等。操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的
    發(fā)表于 01-20 08:32

    atmega128堆棧的特點是什么?

    atmega128堆棧的特點是什么?
    發(fā)表于 01-24 07:16

    STM32堆棧溢出檢測相關(guān)資料下載

    函數(shù)調(diào)用,局部變量等數(shù)據(jù)。heap用于動態(tài)內(nèi)存分配。堆棧可以在啟動文件或者鏈接腳本中指定大小,但在實際開發(fā)中,尤其工程量較大的項目中難以確定堆棧使用量,容易造成堆棧溢出,造成程序崩潰
    發(fā)表于 02-21 07:05

    怎樣去解決STM32堆棧空間不足的問題呢

    怎樣去設(shè)置STM32啟動文件堆棧空間的大小呢?怎樣去解決STM32堆棧空間不足的問題呢?
    發(fā)表于 02-21 06:39

    堆棧以及的區(qū)別

    堆棧堆棧是一個"后進(jìn)先出"的主存區(qū)域,位于堆棧段中,使用SS段寄存器記錄其段地址。它只有一個出入口,即當(dāng)前頂,頂是地址較小 的一端(低
    發(fā)表于 06-30 11:06 ?1820次閱讀
    <b class='flag-5'>堆棧</b>以及<b class='flag-5'>堆</b>和<b class='flag-5'>棧</b>的區(qū)別

    STM32及變量的存儲理解

    STM32及變量的存儲理解
    發(fā)表于 11-30 16:51 ?19次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>堆</b>和<b class='flag-5'>棧</b>及變量的存儲理解

    STM32堆棧空間大小設(shè)置

    1. 設(shè)置堆棧空間大小在使用STM32編程時,一般情況下我們不會關(guān)注堆棧空間的大小,因為在STM32的啟動文件中,已經(jīng)幫我們預(yù)先設(shè)置好了堆棧
    發(fā)表于 12-17 18:36 ?11次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>堆棧</b>空間大小設(shè)置

    STM8S的說明

    參考鏈接:對單片機(jī)堆棧的理解STM8數(shù)據(jù)手冊給出了堆棧的位置及大小。是從高到低分配,是從低到高分配。堆棧是內(nèi)存中一段連續(xù)的存儲區(qū)域,用來
    發(fā)表于 12-27 18:28 ?1次下載
    STM8S的<b class='flag-5'>堆</b>和<b class='flag-5'>棧</b>說明

    Office M5堆棧助手開源

    電子發(fā)燒友網(wǎng)站提供《Office M5堆棧助手開源.zip》資料免費下載
    發(fā)表于 06-19 10:12 ?0次下載
    Office M5<b class='flag-5'>堆棧</b>助手開源