大家好,我是電源漫談,很高興和各位一起分享我的第37篇原創文章,喜歡和支持我的工程師,一定記得給我點贊、收藏、分享。
前述文章,MCU中斷處理那些事(一)中,我們簡要介紹了16位MCU的中斷處理系統的基本特點,本文基于上一次的話題繼續討論中斷相關的事情。
一.MCU的中斷處理過程
當一個中斷事件發生時,它主要經歷這樣一個過程:首先是外設硬件或者MCU內核檢測到這個事件,如果這個中斷的優先級高于當前CPU的優先級,當前的程序執行就會停下來,接著就開啟了中斷服務程序ISR.
當中斷服務程序執行完成時,硬件會恢復先前停止的程序運行,接著執行停下來時的下一條指令。
二.中斷的分類
16位MCU會識別兩種不同的中斷類型,其中一種是不可以mask的Traps事件。這里我們詳細了解一下Traps。Traps是一些不可以mask的,可以嵌套的中斷。這些中斷具有固定的中斷優先級。他們存在的意義主要是檢測并糾正一定的硬件和軟件問題。
圖1 Traps存在的意義
當用戶不想去糾正一些Trap錯誤條件時,中斷向量會指向讓器件復位的代碼,否則用戶應用代碼需要編程Trap中斷向量指向糾正Trap條件的代碼。
圖2 Traps的種類
在dsPIC33及PIC24芯片上主要有以上幾種Trap事件。一般來說,在Trap中斷服務程序開始前,引起Trap的指令是允許執行完成的,所以用戶需要考慮引起Traps的指令導致的一些影響。
對于Trap事件來說,他們具有固定的優先級,如振蕩器失效的Trap的優先級最高,而DMAC錯誤的優先級最低。Trap的源是可以分為兩類的,一類是Hard Trap,另一類是Soft Trap,大家需要注意。
除了Trap類型的中斷之外,就是外設和I/O的外部中斷。這些中斷是屬于一般的,可以被mask的中斷,這些中斷源都是來源于硬件外設的申請,例如外部中斷pin,比較器中斷,通信接口I2C或者UART中斷等。
三.CPU的中斷優先級
16位MCU的中斷處理系統的一個關鍵特性是,用戶可以對中斷優先級進行設定,包括外設中斷和外部中斷等,對于此,我們先了解一下CPU的中斷優先級的設定方式。
CPU的優先級可以設定為0-15這個范圍的共16個優先級水平,所以,中斷進行響應處理的一個前提是,中斷的優先級必須要高于CPU的當前的優先級。
外設或者外部中斷的優先級可以設定為0-7這些優先級水平,而需要注意的是CPU的8-15的優先級部分是為Traps事件所保留且是固定的。
當前執行線程的CPU的優先級是由CPU的狀態寄存器SR中的IPL<0-2>位及Core的控制寄存器中的IPL3所決定,如圖3和4。
圖3 CPU的SR寄存器中的IPL位
圖4 CORCON寄存器的IPL3位
圖5 CPU優先級的設定示例
如果我們將CPU的優先級設定為7,則所有的用戶中斷將被disable,因為所有的外設及外部中斷優先級不可能大于7.而IPL3這一位被系統設定為了1,意味著發生了Trap事件。
這里,有一個知識點需要注意,就是當器件復位后,CPU的優先級是默認為0的,也就是說它比任何優先級非0的外設中斷和外部中斷的優先級都要低,它是允許用戶中斷的。
那么,我們如何配置CPU的優先級呢?首先IPL<0-2>是可以根據用戶的需要手動配置的,它可以允許配置為7,允許系統在一段時間內mask所有的外設和外部中斷,以便密集執行一些CPU命令。
而IPL3是被CPU Core所設置的,它在發生Trap事件時,自動會設置為1.
四.中斷的嵌套功能
中斷處理系統不得不提的一個特性,就是中斷嵌套,在默認設置下,16位MCU是允許中斷嵌套功能的,任何一個高優先級的中斷都可以打斷一個低優先級的中斷復位程序,去執行高優先級的中斷服務程序。
這里我們有一個示例,用以說明中斷嵌套的執行,如圖6所示。
圖6 中斷嵌套示例
這里假定,當在主程序main執行任務時,有不同的優先級的三個ISR執行,此處使能了中斷嵌套功能,可以看到由于CPU的優先級是0,所以優先級為4的中斷打斷了CPU去執行其任務,在執行過程中,優先級為7的中斷觸發了,所以優先執行這個7優先級中斷,在此過程中,優先級為1的中斷觸發了,但是其優先級太低,所以排隊在后面再執行。7優先級中斷任務執行完之后,接著執行4優先級未執行完的任務,最終4優先級的中斷執行完成,最后執行1優先級的任務。這就是一個中斷嵌套的典型示例。
這里有一個知識點需要注意,在中斷嵌套允許時,由于低優先級的中斷可能會被打斷,所以其中斷延時會發生延長變化,比如它需要7個指令周期的中斷延時,3個指令周期用于走出前面的中斷,四個指令周期用于進入新的中斷。
當用戶不希望中斷在執行時被其它高優先級中斷打斷時,那么,可以disable中斷嵌套功能,具體可以在INTCON1中的NSTDIS位置位,這樣在一個中斷執行時,CPU的中斷優先級會被強制為7,這就可以mask所有的其它中斷,直到系統收到當前中斷執行完成的標志,則可以執行其它中斷,此時需要執行當時pending發生的最高優先級的中斷。關于中斷嵌套使能的功能這一個設置如圖7所示。
圖7 中斷嵌套的mask
五.中斷沖突的解決
當多個中斷源同時發生時,且他們的中斷優先級都是一樣的值,比如,他們被設為初始化時的中斷優先級4,那么此時如何解決他們的沖突呢?需要先執行響應誰呢?
事實上,每一個中斷源都有一個自然優先級,這個自然優先級取決于這個中斷向量在中斷向量表IVT上的位置,越小編號的中斷向量,其自然優先級越高。
圖8 中斷向量的自然優先級
所以,當出現同一個用戶設定的優先級沖突時,可以以自然優先級的順序來執行中斷申請,如圖8所示。
總的說來,解決中斷沖突,需要首先看用戶指定的中斷優先級,這個在IPC寄存器中設置,如果若干中斷的優先級一樣,那么需要以自然優先級為順序去響應中斷。
六.中斷功能的使用
在代碼中使用一個中斷,需要注意三個寄存器的使用,中斷標志位IF,中斷使能位IE,中斷優先級位IPC,中斷控制器會接收所有的中斷申請并判斷其優先級,然后發給CPU一個唯一的中斷申請源,及其優先級信息,如圖9所示。
圖9 中斷控制器的功能
這里,可以看出Trap的中斷優先級為8-15,在發生Trap時CPU的CORCON寄存器中的IPL3自動設為1,表示這是Trap的發生。
需要使用一個中斷,首先應該使能這個中斷,比如,此處以外部中斷INT0為例,將INT0IE設為1使能這個中斷。
圖10 中斷使能示例
需要注意的是,使能中斷和設置中斷的優先級的順序需要注意,一般不推薦在中斷使能后,再去改變中斷的優先級,這會導致在中斷發生時去改變其優先級,那么可能會丟失這個中斷,或者使用了錯誤的優先級。正確的做法是先disable中斷,設定其優先級,再使能中斷。
圖11 中斷的優先級設定
中斷的優先級設定使用IPC寄存器,此處以INT0中斷優先級設定為例說明,如圖11所示,通過三位的優先級設定位,可以設定0-7的優先級水平,值得注意的是,當中斷優先級設為0時,這個中斷是不被響應的,相當于disable了這個中斷。
圖12 中斷標志位
當一個中斷或者事件發生時,中斷標志位會置位為1,在用戶中斷服務程序中可以將其清零,作為用戶程序對此中斷的應答。
七.中斷服務程序相關的討論
標準的C語言規范并沒有說明如何去聲明一個函數作為中斷服務程序,MPLAB的XC16對中斷屬性進行了特殊定義,用于申明一個函數作為中斷服務程序。這里我們以INT0中斷為例說明。
圖13 中斷服務程序屬性聲明示例
在XC16的編譯器用戶手冊中或者芯片規格書中,我們可以找到中斷服務程序預定義的名字,如圖14,15所示(注:并非完整表格,僅僅截圖示意)。
圖14 編譯器定義的中斷服務程序名稱
圖15 編譯器定義的中斷服務程序名稱2
從上面的INT0中斷服務程序ISR來看,它的特點主要如下:
§ 沒有參數;
§ void返回類型;
§ 必須使用在XC16中定義的名字;
§ 不能在main函數中調用;
在中斷使能后,中斷可能在任何時候發生,所以它會破壞主程序原有使用的變量,16位單片機的硬件中斷處理器提供了一種機制,在堆棧中去保存和恢復CPU的背景內容。其中PC指針,PCH,PCL及CPU狀態寄存器的低位字節部分SRL,是自動在堆棧中存儲和恢復的。如圖16所示。
圖16 CPU背景保存和恢復
同時XC16還可以用額外的背景保存指令,保存和恢復諸如RCOUNT,W0-W13,W14,PSVPAG等寄存器內容。除此之外,還可以通過編譯器的save屬性去保存和恢復一些關心的變量,如圖17所示。
圖17 變量的保存和恢復
總結,本文延續前述文章,在中斷處理系統初步介紹的基礎上,去進一步探討了中斷的處理過程,中斷的優先級,CPU的優先級,及中斷的嵌套功能及如何處理中斷沖突,最后通過示例介紹了中斷的使用及中斷服務程序的一些要求,相對完整的對中斷處理有一個基本的認識,為后續進一步深入探討奠定基礎。
參考資料:
Exception Handling on a 16-bit PIC® MCU - Developer Help (microchipdeveloper.com)