最近一工程師向我反饋一個(gè)問題,Ta說:我程序會(huì)死在這一行,大概是什么原因?

以下是Ta所說程序會(huì)死的地方,

用過HAL庫的童鞋應(yīng)該比較熟悉這個(gè)函數(shù),它是延時(shí)函數(shù)。

拿到工程代碼后我就開始Debug之旅了,現(xiàn)象確實(shí)如Ta所說,剛開始Hal_delay函數(shù)調(diào)用沒問題,但是過了幾秒之后就卡住了。因?yàn)樵摵瘮?shù)的計(jì)時(shí)是依賴Systick中斷,這個(gè)現(xiàn)象說明Systick中斷進(jìn)不去了,通過debug模式下Systick中斷服務(wù)函數(shù)里加斷點(diǎn),可以驗(yàn)證這一點(diǎn)。但是為什么剛開始好好的,后面就進(jìn)不去中斷了呢?最初我想是不是Systick中斷被關(guān)掉了,通過查看Systick寄存器,發(fā)現(xiàn)并沒有,Systick依然在計(jì)時(shí)并且中斷使能也沒有關(guān)。
程序里初始化時(shí)開啟了RTC中斷,周期是1s,Systick中斷周期是1ms。剛開始時(shí)這兩個(gè)中斷都能進(jìn),幾秒之后這倆中斷就都進(jìn)不去了。

這個(gè)現(xiàn)象看起來確實(shí)挺詭異,因?yàn)榻o我的代碼里糅雜了很多業(yè)務(wù)代碼,寫的也有點(diǎn)亂,看的我很煩躁,后來還是靜下心來仔細(xì)的分析,找到了問題所在。
原因是這樣:Ta在RTC的中斷服務(wù)函數(shù)里,在某個(gè)分支函數(shù)里調(diào)用了Hal_delay函數(shù)。因?yàn)镽TC的中斷優(yōu)先級(jí)和Systick中斷優(yōu)先級(jí)一樣,所以Systick中斷就進(jìn)不去了,導(dǎo)致Hal_delay函數(shù)也就執(zhí)行不過去了,所以就出現(xiàn)了所謂的卡死現(xiàn)象。之所以剛開始沒問題,過了幾秒才出問題,是因?yàn)閯傞_始前幾秒的RTC中斷服務(wù)函數(shù)里沒有進(jìn)到調(diào)用Hal_delay函數(shù)的那個(gè)分支處理里,Ta是在初始化幾秒之后,設(shè)置了一個(gè)標(biāo)志位,導(dǎo)致后來RTC中斷處理里調(diào)用了Hal_delay函數(shù)。
問題找到了,如何解決呢?
最簡(jiǎn)單的方法是,把Systick和RTC的中斷優(yōu)先級(jí)設(shè)置不一樣,讓Systick優(yōu)先級(jí)比RTC高一點(diǎn),這樣可以保證Systick中斷能夠打斷RTC中斷,從而不會(huì)卡死。
ARM Cortex MCU的中斷控制器英文名叫做NVIC,Nested Vectored Interrupt Controller,翻譯過來就是嵌套向量中斷控制器,所謂中斷嵌套是指當(dāng)正在執(zhí)行一個(gè)中斷服務(wù)程序時(shí),這時(shí)如果來了優(yōu)先級(jí)更高的中斷,新來的中斷會(huì)打斷原來還沒有處理完的中斷服務(wù)程序,等新中斷處理完畢之后再回到原中斷服務(wù)繼續(xù)處理。
Cortex-M0/M0+中斷優(yōu)先級(jí)設(shè)置非常簡(jiǎn)單,只需要通過CMSIS標(biāo)準(zhǔn)接口函數(shù)__NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)即可完成,優(yōu)先級(jí)只有4個(gè),分別為0、1、2、3,數(shù)字越小優(yōu)先級(jí)越高。
問題解決了,總結(jié)不能少:
1)我當(dāng)時(shí)找這個(gè)問題花了較長(zhǎng)時(shí)間,反思一下,其實(shí)是可以更快的定位問題的。當(dāng)卡死在Hal_delay函數(shù)時(shí),首先應(yīng)該去分析是哪里調(diào)用這個(gè)函數(shù)導(dǎo)致卡死的,因?yàn)楣こ汤镎{(diào)用的地方有好多處,可以通過在可能出現(xiàn)問題的調(diào)用前給一個(gè)全局變量賦不同的值,卡住時(shí)看全局變量,就可以定位到是從哪里進(jìn)去的。這樣倒著往前推,可以更快的定位問題。
2)通常情況下中斷服務(wù)函數(shù)應(yīng)該盡可能的短,最好不要在中斷里做延時(shí)之類的占用CPU時(shí)間長(zhǎng)的工作。
-
寄存器
+關(guān)注
關(guān)注
31文章
5608瀏覽量
129968 -
函數(shù)
+關(guān)注
關(guān)注
3文章
4417瀏覽量
67502 -
Systick
+關(guān)注
關(guān)注
0文章
67瀏覽量
13968
原文標(biāo)題:中斷里面這樣延時(shí),有點(diǎn)猛~
文章出處:【微信號(hào):嵌入式情報(bào)局,微信公眾號(hào):嵌入式情報(bào)局】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
如何在Zephyr RTOS中實(shí)現(xiàn)延時(shí)和計(jì)時(shí)函數(shù)
RISC-V怎么實(shí)現(xiàn)核間中斷?核心本地中斷控制器(CLINT)深度解析
mcu短時(shí)間內(nèi)發(fā)生多次中斷,如何解決中斷丟失問題呢?
使用系統(tǒng)定時(shí)器SysTick來實(shí)現(xiàn)精確延時(shí)微秒和毫秒函數(shù)
感知再進(jìn)化,新增“觸發(fā)延時(shí)”功能!
求助,關(guān)于蜂鳥mcu外部中斷的問題求解
【NCS隨筆】如何進(jìn)入system_off深度睡眠模式以及配置GPIO中斷喚醒
探頭的延時(shí)介紹
認(rèn)識(shí)探頭的延時(shí)
為什么中斷回調(diào)函數(shù)中不能使用接收中斷開啟函數(shù)?
第六章 外部中斷
為什么中斷回調(diào)函數(shù)中不能使用接收中斷開啟函數(shù)?
【S32K 進(jìn)階之旅】如何使用 S32K3 PIT 定時(shí)器實(shí)現(xiàn)精準(zhǔn)延時(shí)?
中斷里面這樣延時(shí),有點(diǎn)猛~
評(píng)論