1. 程式人生 > >DSP2812之中斷系統

DSP2812之中斷系統

中斷系統概述

X2812的中斷系統從下至上分成了三級,即外設中斷、PIE級中斷、CPU級中斷,三級中斷類似於串聯的關係,共同完成中斷訊號的發生、判斷及次處理。現對中斷系統的執行流程作簡要概述: 首先,如果有外設產生中斷事件,則暫存器中相應的中斷標誌位被置1,如果相應的中斷使能位被置位,那麼外設將向PIE控制器發出一箇中斷請求。 其次,當外設向PIE控制器傳送中斷請求時,相應的PIE中斷標誌位(PIEIFRx.y)置1,如果相應的PIE中斷使能位(PIEIERx.y)也被置位,則PIE將檢查相應的PIEACKx位,以確定CPU是否位該組中斷準備好,如果PIEACKx位被清除,則PIE會向CPU傳送管理請求,如果PIEACKx位為1,則PIE將一直等待直到該位被清除才向CPU傳送中斷請求。 最後,當中斷請求被髮送到CPU,相應的CPU級中斷標誌位置1。當中斷標誌鎖存到標誌暫存器後,會檢查CPU中斷使能暫存器(IER)或除錯中斷使能暫存器(DBGIER)和全域性中斷遮蔽位(INTM)被使能後才被執行。 X2812的三級中斷機制如下圖所示:

1.外設級中斷

外設中斷操作流程

在程式執行過程中,某一外設產生了一箇中斷事件,那麼這個外設的某暫存器中與該中斷事件相關的中斷標誌位(IF)被置位為1。此時,如果該中斷相應的中斷使能位(IE)已經被置位,也就是該值為1,該外設就會向PIE控制器發出一箇中斷請求,如果中斷使能位未被置位,外設不會向PIE控制器提出中斷請求,但是相應的中斷標誌位會一直保持,除非用程式將其手動清除,或者中斷被使能,外設也會立即向PIE發出中斷請求。 以CPU定時器為例,手動請求清除定時器中斷標誌位程式碼如下:

CpuTimer0Regs.TCR.bit.TIF= 1;     //清除定時器中斷標誌位
// TCR: Control register bit definitions:
struct  TCR_BITS {          // bits  description
   Uint16    rsvd1:4;       // 3:0   reserved
   Uint16    TSS:1;         // 4     Timer Start/Stop
   Uint16    TRB:1;         // 5     Timer reload
   Uint16    rsvd2:4;       // 9:6   reserved
   Uint16    SOFT:1;        // 10    Emulation modes
   Uint16    FREE:1;        // 11
   Uint16    rsvd3:2;       // 12:13 reserved
   Uint16    TIE:1;         // 14    Output enable       定時器中斷使能位
   Uint16    TIF:1;         // 15    Interrupt flag          定時器中斷標誌位
};

如上述程式碼所示,當CPU定時器0的計數器暫存器TIMH:TIM計數到0時,就產生一個T0INT事件,即CPU定時器0的週期中斷,此刻第15位定時器中斷標誌TIF被置位,這時,如果第14位TIE位1,CPU定時器0就會向PIE控制器發出中斷請求。

2.PIE級中斷

2.1 PIE中斷概述

中斷控制器PIE,專門處理外設中斷的擴充套件模組(Peripheral Interrupt Expansion),它能夠對各種中斷請求源做出判斷和相應決策。 PIE一共可以支援96個不同的中斷,且將這些中斷分成了12組,每組8個,12組依次反饋到CPU核心的INT1~INT12這12條中斷線中的某一條上。平時能夠用到的外設在PIE中的分佈情況如下表所示: 在這裡插入圖片描述

從上表中看到,CPU定時器0的週期中斷TINT0對應於INT1,在PIE第一組的第七位。PIE第一組的所有外設中斷複用CPU中斷INT1,依次類推,PIE第12組的所有外設中斷複用CPU中斷INT12。在PIE同組內,INTx.1的優先順序高於比INTx.2高,不同組之間,排在前面組內的任何一箇中斷優先順序要比排在後面組內的任何一箇中斷的優先順序高。

2.2 PIE中斷暫存器

PIE的每個組都有三個相關的暫存器,分別是PIE中斷使能暫存器PIEIERx、PIE中斷標誌暫存器PIEIFRx和PIE中斷應答暫存器PIEACKx(介紹省略)。

2.3 PIE中斷向量表

PIE一共可以支援96箇中斷,每個中斷都會有終端服務子程式ISR,DSP將各個中斷服務子程式的地址儲存在一片連續的RAM空間內,稱之為PIE中斷向量表。

2.4 PIE中斷操作流程

當外設將中斷請求提交給PIE,PIE中對應外設中斷組的標誌暫存器PIEIFRx將被置位,此時如果對應組的中斷使能暫存器PIEIERx為使能狀態,則PIE會根據中斷的優先順序優先處理高優先順序中斷,同時PIE暫存器還將根據中斷應答暫存器PIEACK表示PIE是否準備好去響應這些組內中斷。如CPU定時器0的週期中斷被響應了,則PIEACK的第0位(對應於PIE1,即INT1)就會被置位,並且一直保持直到手動清除這個標誌位,清除語句如下所示:

PieCtrlRegs.PIEACK.bit.ACK1 = 1;     //可以響應組1內的其他中斷

所以,每個外設中斷被響應之後,一定要對PIEACK的相關位進行手動復位,以使得PIE控制器能夠響應組內的其他中斷。

3.CPU級中斷

X2812一共支援32個CPU中斷,其中每一箇中斷都是一個32位的中斷向量,用於儲存相應的中斷服務子程式的入口地址。CPU中斷裡,INT1~INT14是14個通用中斷,也是可遮蔽中斷,可通過CPU中斷使能暫存器IER和中斷標誌暫存器IFR來響應中斷。 當一個外設中斷請求通過PIE傳送到CPU時,CPU中斷標誌暫存器IFR中相對應的中斷標誌位INTx就會被置位。這時,CPU不會立即執行中斷,而是檢查IER暫存器中相關位的使能情況和CPU暫存器ST1中全域性中斷遮蔽位INTM的是能情況。如果IER中的相關位被置位,並且INTM的值為0,則中斷就會被CPU響應。

4.CPU定時器0的週期中斷控制LED燈閃爍例項

#include "DSP2833x_Device.h"     // DSP2833x Headerfile Include File
#include "DSP2833x_Examples.h"   // DSP2833x Examples Include File

interrupt void cpu_timer0_isr(void);           //定義定時器週期中斷響應子函式

void main(void)
{
   InitSysCtrl();                              //初始化系統控制暫存器,包括鎖相環、看門狗級外部時鐘
   DINT;                                       //禁止CPU中斷(INTM)
   InitPieCtrl();                              //初始化PIE控制暫存器置預設狀態
   IER = 0x0000;                               //禁止CPU中斷使能暫存器
   IFR = 0x0000;                               //禁止CPU中斷標誌暫存器
   InitPieVectTable();                         //初始化PIE中斷向量表
   EALLOW;  
   PieVectTable.TINT0 = &cpu_timer0_isr;       //定時器的響應子程式賦值給TINT中斷向量表
   EDIS;    
   InitCpuTimers();   // 初始化CPU計時器
   ConfigCpuTimer(&CpuTimer0, 150, 1000000);   //配置CPU計時器,每1響應一次定時器中斷
   CpuTimer0Regs.TCR.all = 0x4001;             // 定時器外設中斷使能
   EALLOW;
   GpioCtrlRegs.GPCMUX1.bit.GPIO66 = 0;        //配置GPIO66為IO口
   GpioCtrlRegs.GPCDIR.bit.GPIO66 = 1;         //配置GPIO66方向為輸出
   EDIS;
   IER |= M_INT1;                              //CPU中斷使能
   PieCtrlRegs.PIEIER1.bit.INTx7 = 1;          //PIE中斷第一組的INTx7中斷使能
   EINT;                                       //使能全域性中斷中斷
   ERTM;                                       // 使能實時中斷
   for(;;);
}
interrupt void cpu_timer0_isr(void)
{
   CpuTimer0.InterruptCount++;
   GpioDataRegs.GPCTOGGLE.bit.GPIO66 = 1;       // 反轉 GPIO66 的輸出高低電平
   PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;      // 執行定時器中斷子程式後,PIEACK標記位主動清除
}