單片機(jī)堆棧是什么?
簡(jiǎn)單來(lái)說(shuō)是在RAM區(qū)的一塊存儲(chǔ)空間,在系統(tǒng)空間中用作臨時(shí)數(shù)據(jù)存儲(chǔ),遵循后進(jìn)先出的原則。
棧空間操作的關(guān)鍵點(diǎn)之一就是棧指針寄存器,每次執(zhí)行棧操作時(shí),棧指針的內(nèi)容自動(dòng)調(diào)整。
按照通常的說(shuō)法,向棧中存儲(chǔ)數(shù)據(jù)稱為“壓棧”(使用PUSH指令),恢復(fù)數(shù)據(jù)稱為“出棧”(使用POP指令)。根據(jù)所使用架構(gòu)的不同,有些處理器在向棧存入數(shù)據(jù)時(shí)地址會(huì)自動(dòng)增加,而有些則會(huì)減小。
這就意味著棧指針始終指向棧空間的最后一個(gè)數(shù)據(jù),在執(zhí)行數(shù)據(jù)存儲(chǔ)前(PUSH),棧指針會(huì)首先減小。
PUSH和POP通常用在函數(shù)或子程序的開(kāi)始和結(jié)尾處。在函數(shù)開(kāi)始執(zhí)行時(shí),PUSH操作將寄存器的當(dāng)前內(nèi)容存入棧空間;執(zhí)行結(jié)束前,POP又將棧空間存儲(chǔ)的數(shù)據(jù)恢復(fù)。一般說(shuō)來(lái),對(duì)每個(gè)寄存器的PUSH操作都應(yīng)相應(yīng)的進(jìn)行POP操作。否則恢復(fù)的數(shù)據(jù)可能無(wú)法對(duì)應(yīng)之前的寄存器,這樣會(huì)導(dǎo)致無(wú)法預(yù)期的后果,比如棧溢出。
下面看一下壓棧和出棧的操作過(guò)程:


再來(lái)說(shuō)一下堆棧的作用:
子程序調(diào)用和中斷服務(wù)時(shí),CPU自動(dòng)將當(dāng)前PC值壓棧保存,返回時(shí)自動(dòng)將PC值彈棧。
保護(hù)現(xiàn)場(chǎng)/恢復(fù)現(xiàn)場(chǎng)。
數(shù)據(jù)傳輸
再來(lái)說(shuō)一下堆棧操作的一些規(guī)則。
比如Cortex-M0處理器每次出棧以及壓棧操作的最小單位是4字節(jié)(32位),還可以使用一條指令實(shí)現(xiàn)對(duì)多個(gè)寄存器的壓棧和出棧操作。顯然Cortex-M0的棧空間被設(shè)計(jì)為字對(duì)齊的(地址值必須是4的倍數(shù),比如0x0、0x4、0x8等)。
對(duì)于Cortex-M0處理器,可以通過(guò)R13或SP訪問(wèn)R13或SP,根據(jù)處理器狀態(tài)和CONTROL寄存器值的不同,訪問(wèn)的棧指針可以是主棧指針(MSP),也可以是進(jìn)程棧指針(PSP)。許多簡(jiǎn)單的應(yīng)用只會(huì)用到一個(gè)棧指針,一般默認(rèn)是主棧指針(MSP),進(jìn)程棧指針通過(guò)只用于嵌入式應(yīng)用的操作系統(tǒng)(OS)。
對(duì)于Cortex-M0處理器由于棧是向下生長(zhǎng)的(滿遞減),內(nèi)存的上邊界通常會(huì)被用作棧指針的初始值。例如,如果內(nèi)存區(qū)域?yàn)?x20000000~0x20007FFF,我們可以將棧指針的初始值設(shè)為0x20008000,在這種情況下,第一次壓棧操作會(huì)將數(shù)據(jù)存至0x20007FFC開(kāi)始的字中,這也是內(nèi)存的最高4字節(jié)。
往期回顧:
●你知道USB的NRZI編碼嗎?
●什么是USB的描述符?
●什么是單片機(jī)的閂鎖效應(yīng)?
END

