RM新时代网站-首页

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

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

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

學(xué)習(xí)STM32單片機(jī),要理解它的堆棧

lcdz66 ? 來源:雨飛工作室 ? 2023-10-29 17:12 ? 次閱讀

學(xué)習(xí)STM32單片機(jī)的時(shí)候,總是能遇到 “堆?!?這個(gè)概念。對于了解一點(diǎn)匯編編程的人,就可以知道,堆棧是內(nèi)存中一段連續(xù)的存儲(chǔ)區(qū)域,用來保存一些臨時(shí)數(shù)據(jù)。堆棧操作由 PUSH、POP 兩條指令來完成。而程序內(nèi)存可以分為幾個(gè)區(qū):棧區(qū)(stack)、堆區(qū)(Heap)、全局區(qū)(static)、字符常量區(qū)、程序代碼區(qū)。

棧,用于存放局部變量,局部數(shù)組等; 堆,用于malloc申請內(nèi)存空間; 全局靜態(tài)區(qū),用于保存全局變量和靜態(tài)變量; 字符常量區(qū),用于保存字符串等; 代碼區(qū),用于保存程序的二進(jìn)制代碼。

程序編譯之后,全局變量,靜態(tài)變量已經(jīng)分配好內(nèi)存空間。在函數(shù)運(yùn)行時(shí),程序需要為局部變量分配棧空間,當(dāng)中斷來時(shí),也需要將函數(shù)指針入棧,保護(hù)現(xiàn)場,以便于中斷處理完之后再回到之前執(zhí)行的函數(shù)。棧是從高到低分配,堆是從低到高分配。

普通單片機(jī)與STM32單片機(jī)中堆棧的區(qū)別

普通單片機(jī)啟動(dòng)時(shí),不需要用bootloader 將代碼從ROM搬移到RAM;但是STM32單片機(jī)需要。這里我們可以先看看單片機(jī)程序執(zhí)行的過程,單片機(jī)執(zhí)行分三個(gè)步驟:取指令、分析指令、執(zhí)行指令。根據(jù)PC的值從程序存儲(chǔ)器讀出指令,送到指令寄存器。然后分析、執(zhí)行。這樣單片機(jī)就從內(nèi)部程序存儲(chǔ)器取代碼指令,從RAM 存取相關(guān)數(shù)據(jù)。RAM 取數(shù)據(jù)的速度是遠(yuǎn)高于 ROM 的,但是普通單片機(jī)因?yàn)楸旧磉\(yùn)行頻率不高,所以從 ROM 取指令慢并不影響。

而STM32的CPU運(yùn)行的頻率高,遠(yuǎn)大于從ROM讀寫的速度。所以需要用 bootloader 將代碼從ROM搬移到 RAM(請注意,這部分表述不準(zhǔn)確)。使用棧就象我們?nèi)ワ堭^里吃飯,只管點(diǎn)菜(發(fā)出申請)、付錢、和吃(使用),吃飽了就走,不必理會(huì)切菜、洗菜等準(zhǔn)備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。使用堆就象是自己動(dòng)手做喜歡吃的菜肴,比較麻煩,但是比較符合自己的口味,而且自由度大。 其實(shí)堆棧就是單片機(jī)中的一些存儲(chǔ)單元,這些存儲(chǔ)單元被指定保存一些特殊信息,比如地址(保護(hù)斷點(diǎn))和數(shù)據(jù)(保護(hù)現(xiàn)場)。如果非要給堆棧加幾個(gè)特點(diǎn)的話,那就是:

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

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

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

從上面的描述可以看得出來,在代碼中是如何占用堆和棧的??赡芎芏嗳诉€是無法理解,這里再結(jié)合STM32的開發(fā)過程中與堆棧相關(guān)的內(nèi)容來進(jìn)行講述。 如何設(shè)置STM32的堆棧大???在基于MDK的啟動(dòng)文件開始,有一段匯編代碼是分配堆棧大小的。

ee413696-7633-11ee-939d-92fbcf53809c.png

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

ee4eaec0-7633-11ee-939d-92fbcf53809c.png

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

Stack_Size EQU 0x400函數(shù)體內(nèi)局部變量:void Fun(void) { chari; intTmp[256];//... }局部變量總共占用了256*4+1字節(jié)的棧空間。所以,在函數(shù)內(nèi)有較多局部變量時(shí),就需要注意是否超過我們配置的堆棧大小。 函數(shù)參數(shù):voidHAL_GPIO_Init(GPIO_TypeDef*GPIOx,GPIO_InitTypeDef *GPIO_Init)要強(qiáng)調(diào)一點(diǎn):傳遞指針只占4字節(jié),如果傳遞的是結(jié)構(gòu)體,就會(huì)占用結(jié)構(gòu)大小空間。提示:在函數(shù)嵌套,遞歸時(shí),系統(tǒng)仍會(huì)占用??臻g。 堆(Heap)的默認(rèn)設(shè)置 0x200(512)字節(jié)。Heap_Size EQU 0x200大部分人應(yīng)該很少使用malloc來分配堆空間。雖然堆上的數(shù)據(jù)只要程序員不釋放空間就可以一直訪問,但是,如果忘記了釋放堆內(nèi)存,那么將會(huì)造成內(nèi)存泄漏,甚至致命的潛在錯(cuò)誤。

MDK中RAM占用大小分析

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

ee6a522e-7633-11ee-939d-92fbcf53809c.png

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

ee6dccba-7633-11ee-939d-92fbcf53809c.png

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

ee7bce8c-7633-11ee-939d-92fbcf53809c.png

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

ee8cb198-7633-11ee-939d-92fbcf53809c.png

STM32棧空間溢出的處理方法

在寫STM32程序時(shí)會(huì)用到一些局部變量,函數(shù)中的局部變量是存在??臻g當(dāng)中,在

STM32的啟動(dòng)文件當(dāng)中可以設(shè)置??臻g大小。如果在函數(shù)當(dāng)中定義的局部變量超過棧空間大小編譯時(shí)不會(huì)報(bào)錯(cuò),但運(yùn)行時(shí)極有可能出現(xiàn)錯(cuò)誤,甚至?xí)?dǎo)致程序卡死,那么該如何處理呢?

方法一:修改棧空間大小1、找到啟動(dòng)文件hd.s (例如:是stm32f103 則是 startup_stm32f10x_hd.s) 2、找到啟動(dòng)文件當(dāng)中的??臻g大小定義:

//系統(tǒng)默認(rèn)棧空間大小為 1K Stack_SizeEQU0x000004003、修改棧空間大小//我們修改為4K Stack_SizeEQU0x00001000方法二:將局部變量改為全局變量。

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

    關(guān)注

    6035

    文章

    44554

    瀏覽量

    634614
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5336

    瀏覽量

    120228
  • STM32
    +關(guān)注

    關(guān)注

    2270

    文章

    10895

    瀏覽量

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

    關(guān)注

    0

    文章

    182

    瀏覽量

    19753

原文標(biāo)題:學(xué)習(xí)STM32單片機(jī),要理解它的堆棧

文章出處:【微信號(hào):雨飛工作室,微信公眾號(hào):雨飛工作室】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    STM32單片機(jī)學(xué)習(xí)筆記(5):ADC模數(shù)轉(zhuǎn)換器

    利用CubMX生成基于32單片機(jī)的HAl庫工程,然后編寫程序在proteus上仿真驗(yàn)證。本項(xiàng)目最適合沒有開發(fā)板的同學(xué)學(xué)習(xí),零成本利用仿真軟件率先入門STM32單片機(jī)。這是第五部分針對
    發(fā)表于 07-19 15:34 ?844次閱讀
    <b class='flag-5'>STM32</b><b class='flag-5'>單片機(jī)</b><b class='flag-5'>學(xué)習(xí)</b>筆記(5):ADC模數(shù)轉(zhuǎn)換器

    STM32單片機(jī)學(xué)習(xí)筆記(6):PWM波形產(chǎn)生

    利用CubMX生成基于32單片機(jī)的HAl庫工程,然后編寫程序在proteus上仿真驗(yàn)證。本項(xiàng)目最適合沒有開發(fā)板的同學(xué)學(xué)習(xí),零成本利用仿真軟件率先入門STM32單片機(jī)。這是第六部分針對
    發(fā)表于 07-19 15:34 ?2236次閱讀
    <b class='flag-5'>STM32</b><b class='flag-5'>單片機(jī)</b><b class='flag-5'>學(xué)習(xí)</b>筆記(6):PWM波形產(chǎn)生

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

    學(xué)習(xí)STM32單片機(jī)的時(shí)候,總是能遇到“堆棧”這個(gè)概念。分享本文,希望對你理解堆棧有幫助。 對于
    發(fā)表于 01-12 11:30

    單片機(jī)堆棧理解

    參考鏈接:對單片機(jī)堆棧理解STM8數(shù)據(jù)手冊給出了堆棧的位置及大小。棧是從高到低分配,堆是從低到高分配。堆棧是內(nèi)存中一段連續(xù)的存儲(chǔ)區(qū)域,用來
    發(fā)表于 02-21 07:29

    詳細(xì)的STM32單片機(jī)學(xué)習(xí)筆記

    STM32單片機(jī)學(xué)習(xí)筆記給大家參考
    發(fā)表于 11-23 17:55 ?1.5w次閱讀

    單片機(jī)堆棧的小故事讓你更容易理解堆棧的概念

    因?yàn)?b class='flag-5'>單片機(jī)有CPU、存儲(chǔ)器、IO等等,使他(人性化一點(diǎn)以配合下文)看起來就像一個(gè)比較小的計(jì)算機(jī),所以在理解單片機(jī)的時(shí)候如果能把你之前有的那些也許僅僅是直覺上的對計(jì)算機(jī)的理解融入進(jìn)來的話
    的頭像 發(fā)表于 09-23 15:58 ?4478次閱讀

    51單片機(jī)STM32單片機(jī)有哪些區(qū)別

    大部分朋友可能都知道51單片機(jī)stm32單片機(jī)也知道一般入門會(huì)先學(xué)習(xí)51單片機(jī)學(xué)習(xí)
    發(fā)表于 08-13 17:32 ?17次下載
    51<b class='flag-5'>單片機(jī)</b>和<b class='flag-5'>STM32</b><b class='flag-5'>單片機(jī)</b>有哪些區(qū)別

    什么是單片機(jī)堆棧單片機(jī)堆棧有什么作用和原理說明

    什么是單片機(jī)堆棧?在片內(nèi)RAM中,常常指定一個(gè)專門的區(qū)域來存放某些特別的數(shù)據(jù),遵循順序存取和后進(jìn)先出(LIFO/FILO)的原則,這個(gè)RAM區(qū)叫
    的頭像 發(fā)表于 08-03 09:29 ?2w次閱讀

    STM32單片機(jī)堆棧深入解析

    學(xué)習(xí)STM32單片機(jī)的時(shí)候,總是能遇到堆棧這個(gè)概念。分享本文,希望對你理解堆棧有幫助。 對于了解
    的頭像 發(fā)表于 10-30 17:31 ?4704次閱讀
    <b class='flag-5'>STM32</b><b class='flag-5'>單片機(jī)</b>的<b class='flag-5'>堆棧</b>深入解析

    單片機(jī)堆棧是什么?的原理和作用又是什么?

    什么是單片機(jī)堆棧?在片內(nèi)RAM中,常常指定一個(gè)專門的區(qū)域來存放某些特別的數(shù)據(jù),遵循順序存取和后進(jìn)先出(LIFO/FILO)的原則,這個(gè)RAM區(qū)叫
    發(fā)表于 11-11 10:51 ?70次下載
    <b class='flag-5'>單片機(jī)</b><b class='flag-5'>堆棧</b>是什么?<b class='flag-5'>它</b>的原理和作用又是什么?

    STM32單片用什么編程?如何學(xué)習(xí)STM32單片機(jī)開發(fā)

    在大學(xué)剛開始接觸51單片機(jī)的時(shí)候,我們學(xué)習(xí)的都是匯編指令,再到后來學(xué)習(xí)了C語言,用C語言代替匯編指令來開發(fā)編程單片機(jī)。STM32
    發(fā)表于 11-13 12:51 ?28次下載
    <b class='flag-5'>STM32</b><b class='flag-5'>單片</b>用什么編程?如何<b class='flag-5'>學(xué)習(xí)</b><b class='flag-5'>STM32</b><b class='flag-5'>單片機(jī)</b>開發(fā)

    單片機(jī)學(xué)習(xí)STM32 和 51 區(qū)別

    單片機(jī)學(xué)習(xí)STM32 和 51 區(qū)別
    發(fā)表于 11-14 15:36 ?18次下載
    【<b class='flag-5'>單片機(jī)</b><b class='flag-5'>學(xué)習(xí)</b>】<b class='flag-5'>STM32</b> 和 51 區(qū)別

    分析單片機(jī)堆棧,分享個(gè)人理解

    看關(guān)于單片機(jī)方面的書籍的時(shí)候,總是能看到別人說的一些堆棧啊什么的操作,之前看到這個(gè)術(shù)語就直接跳過,沒想到去探究單片機(jī)內(nèi)部的原理。但是最近課程學(xué)習(xí)微機(jī)原理這門課,需要我們寫匯編程序,匯編
    發(fā)表于 11-22 09:21 ?6次下載
    分析<b class='flag-5'>單片機(jī)</b><b class='flag-5'>堆棧</b>,分享個(gè)人<b class='flag-5'>理解</b>

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

    學(xué)習(xí)STM32單片機(jī)的時(shí)候,總是能遇到“堆棧”這個(gè)概念。分享本文,希望對你理解堆棧有幫助。
    發(fā)表于 02-08 15:41 ?5次下載
    詳解<b class='flag-5'>STM32</b><b class='flag-5'>單片機(jī)</b>的<b class='flag-5'>堆棧</b>

    普通單片機(jī)STM32單片機(jī)堆棧的區(qū)別

    學(xué)習(xí)STM32單片機(jī)的時(shí)候,總是能遇到“堆棧”這個(gè)概念。分享本文,希望對你理解堆棧有幫助。
    的頭像 發(fā)表于 04-13 11:15 ?3159次閱讀
    RM新时代网站-首页