DSP_Interrupts
Ref:TMS320x2833x, 2823x System Control and Interrupts
CPU中斷
- 共14個CPU中斷(INT1~INT14)
- 其中12CPU中斷連結周邊中斷擴充,每個CPU中斷又可分8個周邊中斷
- 故總共12X8=96個中斷來源
周邊中斷示意圖
Maskable Interrupt Processing(可遮蔽中斷處理)
以下圖來說,我們必須關閉兩個開關以允許一個中斷請求。
- 特定中斷線上的有效信號會導致鎖存器在相應位中顯示“”1“”
- 如果個別和全局開關"turn on",則中斷到達內核
- 編譯器生成用於設置/清除IFR中斷的原子指令(不可中斷),用於設置/清除IFR中斷
- 如果在寫入IFR時發生中斷,則中斷優先
- 當中斷被CPU確認時,IFR(位)被清除
- 寄存器在復位時清零
- 編譯器生成用於設置/清除IER的原子指令(不可中斷)
- 寄存器在復位時清零
Peripheral Interrupt Expansion(外設中斷擴展)
所有96個可能的來源被分組為12個PIE中斷組,每組中斷有8個來源。要啟用/禁用單個源,我們必須編寫另一組寄存器:'PIEIFRx'和'PIEIERx'
根據此分配表,所有中斷源都連接到中斷組:
復位時的矢量表位置是:
Multiplexing of Interrupts Using the PIE Block
- CPU有12中斷,但每個中斷它可以擴充成八個週邊中斷(x為12個CPU中斷)
- 周邊中斷源
-
- 中斷向量表
-
- PIE中斷旗標暫存器(發生中斷產生Latch,把中斷的Bit鎖在這個地方)
- PIE中斷致能暫存器
- 當PIEACK為0時,表示CPU已準備接收中斷,中斷才能送至CPU層
- 中斷旗標暫存器(中斷請求發送到CPU,相應的CPU中斷旗標將set 1)
- 中斷致能暫存器
- 全域中斷遮罩位元(最後關卡,設為0才會送到CPU)
Typical PIE/CPU Interrupt Response - INTx.y(典型的PIE / CPU中斷響應 - INTx.y)
中斷路徑流程圖
- 包含PIE中斷源的任何週邊或外部中斷,且其自身週邊中斷模組亦能致能。
- PIE識別出INTx.y,且PIE中斷的位元被Latch住,PIEIFRx.y=1。
- 當中斷要由PIE送致CPU層要有兩個條件成立。
- PIEIERx.y=1 (要先有中斷請求)
- PIEACKx要被清成0
- 當3(a)與3(b)為真,送中斷由PIE到CPU層,此時應體會將PIEACKx設為1,表示可以在從PIE向CPU發送組中的其他中斷
- CPU中斷旗標暫存器會LATCH中斷,並顯示1
- Enable後才會傳遞給CPU
- CPU中斷遮罩位元設0時,才能送中斷到CPU
- CPU收到中斷後會清除IERx、INTM設為1並清除EALLOW,之後進行中斷服務。
- PIEIFRx與PIEIERx來解碼出中斷向量表,並判斷優先順序(如下圖)
權限比較的話:1為最高,8為最低
F2833x Timer Interrupt System
32-Bit CPU Timers 0/1/2
- 全部皆是32bit的計時器
- 只有0/1計時器可被使用,計時器2保留給DSP/BIOS
- 是32bit的下數記數暫存器。
- 記數道0發生中斷,並重新載入。
CPU Timers
與Resisger的對印關係(拿Timer0來做舉例)
定時器單元通常由一組寄存器初始化。我們不用自己設置每一個位,而是使用一個硬件抽象函數,我們只需要指定期望的定時器週期和處理器的時鐘速度。
此功能由德州儀器提供,作為一組此類功能的一部分。
控制暫存器TIMERxTCR
- TIF:計時器中斷旗標
- 寫1,可清除此旗標;寫0則無作用。
- 當記數器遞減為0時,此旗標為1。
- TIE:CPU Timer的中斷致能(0:Disabl,1:Enable)
- 當記數器遞減到0時且TIE設為1,計時器才會產生中斷。
- TRB:CPU Timer的重載單位
-
當TRB設為1時
- TIMH:TIM會載入暫存器PRDH:PRD
- PSCH:PSC會載入暫存器TDDRH:TDDR
-
- TSS:CPU Time的停止位元
- 讀取時=> 0:執行中;1:已停止
- 寫入時=> 0:重置(系統重置時TSS=0,Timer會自己啟動);1:停止
Example:Lab 6: CPU Timer 0 Interrupt and 4 LEDs
本實驗的目標是在Lab5_1的“LED計數器”項目中包含一個中斷系統的基本示例。
我們現在將使用3個核心CPU定時器之一來完成這項工作,而不是使用軟件延遲循環來生成輸出步驟之間的時間間隔,這是對處理器時間的不良使用。
定時器的一個最簡單的任務是產生一個週期性的中斷請求。我們可以使用它的中斷服務例程來執行定期活動或增加一個全局變量。然後這個變量將包含程序開始後經過的時間段的數量。
CPU定時器0正在使用外設中斷擴展(PIE)單元。這也讓我們有機會鍛煉這個單位。定時器1和2繞過PIE單元,它們通常保留用於德州儀器的實時操作系統,稱為“DSP / BIOS”。
因此,我們實現了Timer 0作為此練習的核心時鐘。
All Code
1 //########################################################################### 2 // 3 // FILE: Lab6.c 4 // 5 // TITLE: DSP28335ControlCARD; Digital Output 6 // 4 - bit - counter at 4 LEDs LD1(GPIO9), LD2(GPIO11), LD3(GPIO34) 7 // and LD4 (GPIO49) 8 // CPU Timer 0 period and Interrupt Service 9 // solution file for Lab6 10 //########################################################################### 11 // Ver | dd mmm yyyy | Who | Description of changes 12 // =====|=============|======|=============================================== 13 // 3.0 | 02 May 2008 | F.B. | Lab6 for F28335; 14 // 3.1 | 08 Nov 2009 | F.B | Lab6 for F28335 and PE revision5 15 //########################################################################### 16 #include "DSP2833x_Device.h" 17 18 // external function prototypes 19 extern void InitSysCtrl(void); 20 extern void InitPieCtrl(void); 21 extern void InitPieVectTable(void); 22 extern void InitCpuTimers(void); 23 extern void ConfigCpuTimer(struct CPUTIMER_VARS *, float, float); 24 25 // Prototype statements for functions found within this file. 26 void Gpio_select(void); 27 interrupt void cpu_timer0_isr(void); 28 29 //########################################################################### 30 // main code 31 //########################################################################### 32 void main(void) 33 { 34 int counter=0; // binary counter for digital output 35 36 InitSysCtrl(); // Basic Core Init from DSP2833x_SysCtrl.c 37 38 EALLOW; 39 SysCtrlRegs.WDCR= 0x00AF; // Re-enable the watchdog 40 EDIS; // 0x00AF to NOT disable the Watchdog, Prescaler = 64 41 42 DINT; // Disable all interrupts 43 44 Gpio_select(); // GPIO9, GPIO11, GPIO34 and GPIO49 as output 45 // to 4 LEDs at Peripheral Explorer) 46 47 InitPieCtrl(); // basic setup of PIE table; from DSP2833x_PieCtrl.c 48 49 InitPieVectTable(); // default ISR's in PIE 50 51 EALLOW; 52 PieVectTable.TINT0 = &cpu_timer0_isr; 53 EDIS; 54 55 InitCpuTimers(); // basic setup CPU Timer0, 1 and 2 56 57 ConfigCpuTimer(&CpuTimer0,150,100000); // CPU - Timer0 at 100 milliseconds 58 59 PieCtrlRegs.PIEIER1.bit.INTx7 = 1; 60 61 IER |=1; 62 63 EINT; 64 ERTM; 65 66 CpuTimer0Regs.TCR.bit.TSS = 0; // start timer0 67 68 while(1) 69 { 70 while(CpuTimer0.InterruptCount == 0); 71 CpuTimer0.InterruptCount = 0; 72 73 EALLOW; 74 SysCtrlRegs.WDKEY = 0x55; // service WD #1 75 EDIS; 76 77 counter++; 78 if(counter&1) GpioDataRegs.GPASET.bit.GPIO9 = 1; 79 else GpioDataRegs.GPACLEAR.bit.GPIO9 = 1; 80 if(counter&2) GpioDataRegs.GPASET.bit.GPIO11 = 1; 81 else GpioDataRegs.GPACLEAR.bit.GPIO11 = 1; 82 if(counter&4) GpioDataRegs.GPBSET.bit.GPIO34 = 1; 83 else GpioDataRegs.GPBCLEAR.bit.GPIO34 = 1; 84 if(counter&8) GpioDataRegs.GPBSET.bit.GPIO49 = 1; 85 else GpioDataRegs.GPBCLEAR.bit.GPIO49 = 1; 86 } 87 } 88 89 void Gpio_select(void) 90 { 91 EALLOW; 92 GpioCtrlRegs.GPAMUX1.all = 0; // GPIO15 ... GPIO0 = General Puropse I/O 93 GpioCtrlRegs.GPAMUX2.all = 0; // GPIO31 ... GPIO16 = General Purpose I/O 94 GpioCtrlRegs.GPBMUX1.all = 0; // GPIO47 ... GPIO32 = General Purpose I/O 95 GpioCtrlRegs.GPBMUX2.all = 0; // GPIO63 ... GPIO48 = General Purpose I/O 96 GpioCtrlRegs.GPCMUX1.all = 0; // GPIO79 ... GPIO64 = General Purpose I/O 97 GpioCtrlRegs.GPCMUX2.all = 0; // GPIO87 ... GPIO80 = General Purpose I/O 98 99 GpioCtrlRegs.GPADIR.all = 0; 100 GpioCtrlRegs.GPADIR.bit.GPIO9 = 1; // peripheral explorer: LED LD1 at GPIO9 101 GpioCtrlRegs.GPADIR.bit.GPIO11 = 1; // peripheral explorer: LED LD2 at GPIO11 102 103 GpioCtrlRegs.GPBDIR.all = 0; // GPIO63-32 as inputs 104 GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1; // peripheral explorer: LED LD3 at GPIO34 105 GpioCtrlRegs.GPBDIR.bit.GPIO49 = 1; // peripheral explorer: LED LD4 at GPIO49 106 GpioCtrlRegs.GPCDIR.all = 0; // GPIO87-64 as inputs 107 EDIS; 108 } 109 110 interrupt void cpu_timer0_isr(void) 111 { 112 CpuTimer0.InterruptCount++; 113 EALLOW; 114 SysCtrlRegs.WDKEY = 0xAA; // service WD #2 115 EDIS; 116 PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; 117 } 118 //=========================================================================== 119 // End of SourceCode. 120 //===========================================================================