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

在STM32上移植的一個(gè)穩(wěn)定可靠的FIFO
分享兩個(gè)STM32應(yīng)用中的實(shí)戰(zhàn)案例
兩個(gè)LED和兩個(gè)按鈕的使用

評論