有STM32用戶將基于STM32F0芯片的代碼移植到STM32F4系列時(shí)遇到了些麻煩。其中有個(gè)問(wèn)題跟中斷處理有關(guān)。有個(gè)中斷服務(wù)程序代碼在STM32F0芯片里運(yùn)行正常,移植到STM32F4芯片并使用同樣的程序代碼卻明顯異常,感覺(jué)每次中斷都進(jìn)了兩次。
經(jīng)過(guò)他一番網(wǎng)上搜索,大致找到了問(wèn)題原因和解決辦法。原因就是他在中斷服務(wù)程序里做中斷請(qǐng)求標(biāo)志清零的代碼放在服務(wù)程序的結(jié)尾處了,將其挪至服務(wù)程序的入口處就可以了。
問(wèn)題是解決了,但依然還是有兩個(gè)小疑問(wèn)如鯁在喉。
第一個(gè)疑問(wèn),為什么同樣的操作在F0系列正常,而在F4系列卻異常呢??jī)H僅是因?yàn)镕4系列跑得快?
其實(shí),這里的主要原因是內(nèi)核差異導(dǎo)致的。STM32F0系列芯片是基于ARM Cortex-M0內(nèi)核的微處理器,STM32F4系列芯片是基于ARM Cortex-M4內(nèi)核的微處理器,二者在內(nèi)核上存在一些差異,其中一個(gè)差異就是,M4內(nèi)核相比M0內(nèi)核多了針對(duì)寫(xiě)操作的寫(xiě)緩沖以及相應(yīng)執(zhí)行機(jī)構(gòu),這里不妨稱之為“緩沖寫(xiě)”單元。
對(duì)于F0系列,由于沒(méi)有“緩沖寫(xiě)單元”,CPU在做中斷請(qǐng)求標(biāo)志清零時(shí)需全程執(zhí)行直到清零完成才能做中斷返回。對(duì)于F4系列,由于有“緩沖寫(xiě)單元”協(xié)助,在做中斷請(qǐng)求標(biāo)志清零時(shí)CPU只需執(zhí)行相應(yīng)程序,交代清楚寫(xiě)些什么到哪里即可,具體的寫(xiě)操作就交給“緩沖寫(xiě)”單元完成,然后繼續(xù)執(zhí)行后續(xù)程序,后面跟F0系列就有點(diǎn)不一樣了。由于清零操作代碼執(zhí)行時(shí)刻與準(zhǔn)備出棧時(shí)刻太接近,“緩沖寫(xiě)”單元尚未完成對(duì)標(biāo)志的清零,CPU因而再次進(jìn)了一次中斷服務(wù)程序。顯然程序再運(yùn)行一次后,一般來(lái)講那個(gè)標(biāo)志的清零都會(huì)完成了。因此,類(lèi)似情況我們往往最多也就看到進(jìn)了兩次中斷。
第二個(gè)疑問(wèn)呢?
用戶發(fā)現(xiàn)在使用STM32F4芯片時(shí),即使清中斷標(biāo)志代碼放在服務(wù)程序的結(jié)尾,一般只需在其后面追加3到4個(gè)NOP操作后就保證不會(huì)發(fā)生1次事件進(jìn)入2次中斷服務(wù)程序的情況。也就是說(shuō),在清中斷標(biāo)志代碼后面稍加延時(shí)3~5個(gè)時(shí)鐘就能保證清零完成。
對(duì)于Cortex-M內(nèi)核的芯片,中斷出棧不會(huì)少于12系統(tǒng)時(shí)鐘。這樣說(shuō)來(lái),即使不加那幾個(gè)NOP操作延時(shí),這12個(gè)時(shí)鐘也足以讓清零完成。這意味著出棧后中斷請(qǐng)求標(biāo)志早已完成清零,那么第2次再進(jìn)中斷是依據(jù)什么而響應(yīng)的呢?
這里就涉及到ARM Cortex-M內(nèi)核的中斷響應(yīng)咬尾機(jī)制。簡(jiǎn)單點(diǎn)說(shuō),當(dāng)CPU剛執(zhí)行完某中斷服務(wù)程序準(zhǔn)備出棧返回時(shí),若內(nèi)核硬件發(fā)現(xiàn)外邊正有嗷嗷待哺的其它中斷請(qǐng)求候著時(shí),就果斷決定不做出棧了,立馬響應(yīng)新的中斷請(qǐng)求并執(zhí)行相應(yīng)服務(wù)程序。
具體到這里,當(dāng)STM32F4的中斷服務(wù)程序里最后一行清中斷標(biāo)志代碼執(zhí)行完后(具體寫(xiě)操作交給“緩沖寫(xiě)單元”了),CPU準(zhǔn)備做出棧返回時(shí),由于寫(xiě)緩沖單元尚未完成清零,硬件發(fā)現(xiàn)有個(gè)中斷請(qǐng)求存在,于是乎果斷決定放棄出棧,稍作準(zhǔn)備后也不做壓棧就執(zhí)行當(dāng)前中斷請(qǐng)求所對(duì)應(yīng)的服務(wù)程序,這里就是把剛才的中斷服務(wù)程序再跑一次。
看到這里,我們應(yīng)該明白了,中斷再進(jìn)一次的關(guān)鍵是CPU準(zhǔn)備出棧時(shí)發(fā)現(xiàn)還有中斷請(qǐng)求存在,至于出棧時(shí)間多長(zhǎng)多短已經(jīng)不重要,因?yàn)檫@時(shí)壓根就不做出棧操作了。這也就可以解除上面提到的疑惑了。
下圖就是示意中斷前后兩次執(zhí)行的情況。【假定中斷第一次是打斷主程序或強(qiáng)占其它進(jìn)來(lái)的】
第一次進(jìn)中斷時(shí),發(fā)生了壓棧。第二次進(jìn)中斷是緊跟著第一次中斷服務(wù)程序之后,未做出棧稍加準(zhǔn)備后就開(kāi)始執(zhí)行服務(wù)程序,之后才做出棧操作。
看到這里,或許有人會(huì)問(wèn)上面提到的稍加準(zhǔn)備難道不要時(shí)間嗎?也是要的,如果Flash訪問(wèn)取指延時(shí)為0等待的話,最短6個(gè)時(shí)鐘。
或許有人繼續(xù)問(wèn),這個(gè)6個(gè)時(shí)鐘跟平常壓棧的10來(lái)個(gè)時(shí)鐘是什么關(guān)系呢?
當(dāng)有壓棧時(shí),這個(gè)6個(gè)時(shí)鐘就包含于壓棧時(shí)間里了,它大致用來(lái)做中斷向量的提取、Exc_return值的擬定等,這些操作跟壓棧操作是并行重疊的,有壓棧時(shí)就不提這幾個(gè)時(shí)鐘的時(shí)間了,只說(shuō)壓棧時(shí)間。
對(duì)于前面提到的第2次基于咬尾機(jī)制進(jìn)中斷的情形,如果希望得到較為直觀地體驗(yàn)、感受,可以借助斷點(diǎn),觀察棧幀的變化來(lái)滿足。我們可以明顯地觀察到中斷服務(wù)程序運(yùn)行了兩次,壓棧只發(fā)生一次。
好,今天的話題就分享到這里,供君參考。下次再聊。
審核編輯:湯梓紅
-
mcu
+關(guān)注
關(guān)注
146文章
17123瀏覽量
350975 -
STM32
+關(guān)注
關(guān)注
2270文章
10895瀏覽量
355721 -
微處理器
+關(guān)注
關(guān)注
11文章
2258瀏覽量
82402 -
移植
+關(guān)注
關(guān)注
1文章
379瀏覽量
28124 -
中斷
+關(guān)注
關(guān)注
5文章
898瀏覽量
41470
原文標(biāo)題:因STM32移植而引發(fā)的兩個(gè)小疑問(wèn)
文章出處:【微信號(hào):stmcu832,微信公眾號(hào):茶話MCU】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論