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中的分佈情況如下表所示:
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標記位主動清除
}