看了TI的文檔:TMS321x281x DSP System Control and Interrupts Reference Guide,spru078b.pdf
有一些心得:
1、一個外設中斷要到達CPU,讓CPU處理,得經過許多道門
PIEIER->(PIEACKx)->IER->INTM
在CPU級別上面,有1個不可屏蔽中斷(NMI),16個可屏蔽中斷(INT1~INT14,RTOSINT和DLOGINT)。其中的INT1~INT12每個又通過PIE擴展出8個外設中斷,所以外設中斷可以有12*8=96個,F2812僅僅用了其中45個:
2、關於中斷嵌套,硬件上沒直接支持,但軟件可實現
先看F2812的處理流程圖:
可以看到,在進入中斷服務程序之前的Stage H,INTM已經被置位(中斷關閉),所以不可能在響應其他的中斷了,之后的其他中斷都會在Stage G這里卡住。所以,如果你要允許中斷嵌套,除非在你的中斷程序里面手動把INTM清零(EINT),具體例子可看sprc097的sw_prioritized_interrupts,里面的例子就是這么干的,它的中斷服務程序都有EINT這一句,以此為基礎,來實現中斷的嵌套。
3、關於優先級
不能自己設定,硬件本身有自己的一套優先級,當時看上面流程圖可知,因為硬件不可實現中斷嵌套,所以這個優先級僅僅當兩個中斷同時發生的時候才起作用,所以一般不用管了。sprc097的sw_prioritized_interrupts例子可以有軟件優先級。
4、一個需要注意的地方,PIEACKx的清零
先想一個問題,我們知道,給PIEACK的對應位寫1即可清除這個位,以便讓中斷控制器響應同組的其他中斷,但下面這樣清除Group1的PIEACK位對不對:
PieCtrl.PIEACK.bit.Ack1 = 1;
回答這個問題之前,先參考第2點中的流程圖,考慮一個問題,PIEAck這個寄存器我們用了第0~11位來對應第1到第12組中斷,那么這12位中可不可能同時有多個位為1?答案是肯定的,因為雖然不能中斷嵌套,但是各組中斷被卡的地方在Stage G,假如同時有多組中都有中斷發生,那么到Stage G才會被卡,這個之前,對應各組的PIEAck都已經在Stage C之后被置1了,所以PIEAck完全有可能有多個位被置1.
再來考慮上面寫法,雖然上面用了位域的寫法,語法上只是對Ack1這一位寫1,但是位域最終在處理器的執行上,還是要一次重新寫一次寄存器,而這個寫入是按照讀-修改-寫的流程的,即先讀取PIEAck的值,再把Ack1修改為1(按上面語句),最后再把修改完之后的值寫入寄存器PIEAck,這個時候就會出現問題了,因為在讀入的PIEAck中,可能有其他組有中斷在等待了,它對應的Ack為1,你這樣一寫1進去,就有可能導致同組的其他中斷把這個中斷覆蓋掉。所以正確的寫法應該是:
#define PIEACK_GROUP1 0x0001 …… PieCtrl.PIEACK.all = PIEACK_GROUP1;
因為PIEACK寫0無效,不起作用,這樣寫就僅僅影響了第一位了。
這個具體可見sprc097中的DSP281x_HeaderFiles_QuickStart_Readme.pdf 6.1.1一節。