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

評論