在線做網(wǎng)站 自動(dòng)生成手機(jī)版seo的定義是什么
目錄
前言
一、程序跑飛原因
二、調(diào)試工具
2.1Registers工具
2.2 Memory工具
2.3?Disassembly工具
2.4?Call Stack工具
三、找到程序跑飛位置
方式一、
方式二、
前言
我們初學(xué)STM32的時(shí)候代碼難免會(huì)出現(xiàn)疏忽,導(dǎo)致程序跑飛,不再正常運(yùn)行,那么都是什么情況會(huì)導(dǎo)致STM32程序跑飛呢?
一、程序跑飛原因
軟件導(dǎo)致STM32跑飛(程序失控或死機(jī))的原因有多種,主要包括以下幾個(gè)方面:
-
中斷處理不當(dāng):
- 未響應(yīng)或清除中斷標(biāo)志:如果打開了某個(gè)中斷但沒有及時(shí)響應(yīng)和清除中斷標(biāo)志,程序可能會(huì)持續(xù)進(jìn)入中斷,造成死機(jī)假象。
- 中斷變量處理不妥:如果定義了某些會(huì)在中斷中修改的全局變量,但沒有正確管理這些變量(如使用
volatile
關(guān)鍵字聲明,或在讀取前關(guān)閉全局中斷),可能會(huì)導(dǎo)致數(shù)據(jù)不一致或程序異常。
-
堆棧溢出:
- 當(dāng)項(xiàng)目代碼量較大時(shí),如果默認(rèn)的堆棧設(shè)置過小,或者程序中存在大量的函數(shù)調(diào)用和局部變量,可能導(dǎo)致堆棧溢出,使程序跑飛。
-
不合理的內(nèi)存操作:
- 內(nèi)部Flash存儲(chǔ)操作不當(dāng):不合理的Flash內(nèi)存操作也可能導(dǎo)致程序死機(jī)。
- 數(shù)組越界:如果在使用數(shù)組時(shí)沒有控制好下標(biāo),導(dǎo)致數(shù)組越界,可能會(huì)意外修改系統(tǒng)的寄存器或數(shù)據(jù),造成程序失控。
-
死循環(huán):
- 程序中存在的無條件的死循環(huán)(如
while(1)
循環(huán)中缺少跳出條件)也可能導(dǎo)致程序無法繼續(xù)執(zhí)行后續(xù)操作。
- 程序中存在的無條件的死循環(huán)(如
-
看門狗未喂或未關(guān)閉:
- 如果使用了看門狗功能但沒有在適當(dāng)?shù)臅r(shí)候喂狗,或者看門狗被意外開啟但沒有關(guān)閉,都可能導(dǎo)致程序被頻繁復(fù)位。
二、調(diào)試工具
我們要發(fā)現(xiàn)程序在哪跑飛了,肯定是要借助調(diào)試工具了,以下幾個(gè)工具是我們需要用到的。
2.1Registers工具
(1)通用寄存器(R0~R12)
- R0~R7:這些是低組寄存器,所有指令都可以訪問。它們的大小為32位,復(fù)位后的初始值不定。
- R8~R12:這些是高組寄存器,只有部分的16位Thumb指令可以訪問,而32位Thumb-2指令則不受限制。它們的大小同樣為32位,復(fù)位后的初始值也不定。
(2)特殊功能寄存器
- 堆棧指針(SP):也稱為R13,在Cortex-M4內(nèi)核中,有兩個(gè)堆棧指針——主堆棧指針(MSP)和進(jìn)程堆棧指針(PSP)。MSP用于異常服務(wù)例程和需要特權(quán)訪問的應(yīng)用程序代碼,而PSP則用于常規(guī)的應(yīng)用代碼。
- 連接寄存器(LR):即R14,主要作用是保存子程序的返回地址,以便在執(zhí)行完子程序時(shí)恢復(fù)現(xiàn)場。
- 程序計(jì)數(shù)器(PC):即R15,用于指示當(dāng)前執(zhí)行的指令地址。在Cortex-M系列中,由于采用指令流水線技術(shù),讀取PC會(huì)返回當(dāng)前指令地址+4(以兼容Thumb代碼)。
(3)程序狀態(tài)寄存器(xPSR)
xPSR是程序狀態(tài)寄存器,它又被分為三個(gè)子狀態(tài)寄存器:
- 應(yīng)用程序狀態(tài)寄存器(APSR)
- 中斷狀態(tài)寄存器(IPSR)
- PRIMASK:只有1個(gè)位,置1時(shí)關(guān)閉所有可屏蔽的異常。
- FAULTMASK:只有1個(gè)位,置1時(shí)只有NMI(非屏蔽中斷)可以響應(yīng)。
- BASEPRI:8位寄存器,定義了被屏蔽優(yōu)先級的閾值。
(4)控制寄存器(Control)
控制寄存器用于控制FPU(浮點(diǎn)單元)的激活、堆棧指針的選擇以及線程模式的特權(quán)級等。
2.2 Memory工具
Memory Window是Keil調(diào)試環(huán)境中的一個(gè)窗口,它提供了對程序內(nèi)存的直接訪問。通過這個(gè)窗口,你可以查看內(nèi)存中的字節(jié)、字、雙字等數(shù)據(jù),并可以實(shí)時(shí)修改這些數(shù)據(jù)以測試程序的行為。這對于調(diào)試和驗(yàn)證程序中的內(nèi)存訪問、堆棧使用、變量存儲(chǔ)等問題非常有幫助。
2.3?Disassembly工具
在Disassembly窗口中,你可以看到程序的反匯編代碼。這些代碼是程序在CPU上實(shí)際執(zhí)行的指令的文本表示。你可以滾動(dòng)窗口來查看不同的部分,或者使用窗口中的搜索功能來定位特定的代碼或地址。
2.4?Call Stack工具
Call Stack(調(diào)用堆棧)界面是一個(gè)關(guān)鍵的調(diào)試工具,它允許開發(fā)者查看程序執(zhí)行過程中函數(shù)調(diào)用的順序和當(dāng)前的位置。Call Stack窗口將顯示當(dāng)前函數(shù)調(diào)用的堆棧。這包括每個(gè)函數(shù)的調(diào)用順序、每個(gè)函數(shù)的名稱(如果可用)以及調(diào)用該函數(shù)的地址。你可以看到程序是如何從main
函數(shù)開始,逐步調(diào)用其他函數(shù),直到達(dá)到當(dāng)前執(zhí)行點(diǎn)的。
三、找到程序跑飛位置
介紹完了程序跑飛的原因以及調(diào)試工具以后,接下來我為大家說一下如何找到程序跑飛的位置,有兩種方式。
方式一、
(1)在HardFault_Handler這個(gè)函數(shù)里面打上斷點(diǎn),程序跑飛都會(huì)進(jìn)入這個(gè)中斷。
(2)在Registers工具中找到R13的值。
(3)在Memory工具中搜索剛才R13的值,然后找到0800開頭的值。
(4)在Disassembly工具中右鍵選擇Show Disassembly at Address,然后將0x08001548復(fù)制進(jìn)去,點(diǎn)GO TO,就找到程序在哪跑飛了。
方式二、
?(1)和上面第一步一樣,在HardFault_Handler這個(gè)函數(shù)里面打上斷點(diǎn)。
(2)程序進(jìn)入斷點(diǎn)以后,先點(diǎn)繼續(xù)運(yùn)行,然后停止運(yùn)行程序
,打開Call Stack工具,找到HardFault_Handler,然后右鍵選擇 show Caller Code就可以找到跑飛之前運(yùn)行的代碼了。
注意:
(1)方式一和方式二都需要先在HardFault_Handler打斷點(diǎn)才能進(jìn)行
(2)方式二不停止程序不會(huì)出現(xiàn)show Caller Code
(3)如果是堆棧溢出方式一二均無效,因?yàn)檫@兩個(gè)方式都是通過堆棧進(jìn)行尋址的。