最近在學(xué)習(xí)DSP,想把自己的學(xué)習(xí)感想,記錄下來,大家討論一下。
DSP的三級中斷機(jī)制,分別是外設(shè)級,PIE級和CPU級,也就是說,對于一個具體的外設(shè)中斷請求,我們需要三級的許可。
CPU相當(dāng)于分組,分成了12個小組,而PIE是CPU組里邊的成員每個小組又有8個成員。PIE的英語稱作Peripheral interrupt Expansion block
專門處理外設(shè)中斷的擴(kuò)展模塊。很準(zhǔn)確的描述了PIE的含義。
書上用了一個使用CPU定時器0的周期中斷來控制LED燈的例子。
CPU定時器0在完成一個周期的計(jì)數(shù)之后,會產(chǎn)生一個周期中斷,設(shè)置CPU定時器0的周期為1S,每隔1S進(jìn)入一次周期中斷,在中斷服務(wù)程序里邊
改變了GPIO引腳的電平。
void main(void)
{ InitSysCtrl(); //初始化系統(tǒng)函數(shù)
DINT;
IER = 0x0000; //禁止CPU中斷
IFR = 0x0000; //清除CPU中斷標(biāo)志
這兩個寄存器分別是中斷使能寄存器和中斷標(biāo)志寄存器,說明這個程序里邊的中斷時可屏蔽中斷,
InitPieCtrl(); //初始化PIE控制寄存器
InitPieVectTable(); //初始化PIE中斷向量表
InitPeripherals(); //初始化Cpu定時器模塊 I
nitGpio(); //初始化GPIO
PieCtrl.PIEIER1.bit.INTx7 =1; //使能PIE模塊中的Cpu定時器0的中斷 I
ER|=M_INT1; //開CPU中斷
EINT; //使能全局中斷
ERTM; //使能實(shí)時中斷
ConfigCpuTimer(&CpuTimer0, 150, 1000000); //Cpu定時器0的周期為1s
StartCpuTimer0(); //啟動Cpu定時器0 for(;;) { }
}
以上的MIAN的主程序,下邊是DSP28_PIEVECT.H這個頭文件,書上說定義了PIE的中斷向量,我覺得這個頭文件還有一個重點(diǎn)
就是定義了PINT的指針,指向了中斷。之后要去找找這個PINT的指針在哪里。
#ifndef DSP28_PIE_VECT_H #define DSP28_PIE_VECT_H // 定義一個名稱為PINT的指針,指向中斷: typedef interrupt void(*PINT)(void); // 定義中斷向量表: struct PIE_VECT_TABLE { //中斷向量表起始地址為0x3FFFC0, 在BOOT ROM還是XINTF ZONE7 取決于引腳XMP/MC的狀態(tài) //當(dāng)XMP/MC=0時,向量表在BOOT ROM內(nèi);當(dāng)XMP/MC=1,向量表在XINTF ZONE7內(nèi) PINT PIE1_RESERVED; ........ // 非外設(shè)中斷: PINT XINT13; // XINT13 ..... // PIE組1外設(shè)中斷向量: PINT PDPINTA; // EV-A ..... // PIE組2外設(shè)中斷向量: PINT CMP1INT; // EV-A ........ // PIE組3外設(shè)中斷向量: PINT T2PINT; // EV-A ........ // PIE組4外設(shè)中斷向量: PINT CMP4INT; // EV-B ........ // PIE組5外設(shè)中斷向量: PINT T4PINT; // EV-B .......
......... extern struct PIE_VECT_TABLE PieVectTable; #endif
InitPieCtrl這個函數(shù)對PIE的中斷使能寄存器進(jìn)行初始化,對應(yīng)上圖畫紅圈的寄存器。
程序里邊第一步先是給PieCtrl.PIECRTL.bit.ENPIE = 0;對PIE控制寄存器的ENPIE位置0,此時PIE塊是無效的。
第二步,對PIE中斷使能寄存器設(shè)置,這個寄存器一共有12個分別為PIEIERx,而每個寄存器正好有8位,對應(yīng)每個CPU小組里邊的8個成員。
也就是說這個PIE中斷使能寄存器有96個分別使能每個成員中斷。對應(yīng)上邊圖中的開關(guān)閉合對應(yīng)每個CPU小組里邊的8個成員。也就是說這個PIE中斷使能寄存器有96個分別使能每個成員中斷。對應(yīng)上邊圖中的開關(guān)閉合
第三步,對PIE中斷標(biāo)志寄存器設(shè)置,和中斷使能寄存器類似分成12組,每個組有8個成員,一共12個寄存器,每個寄存器8位。書上說當(dāng)中斷激活的時候,各個寄存器位置1,當(dāng)中斷被處理完成或者向該位寫0,該為清0.還不能理解--------------------------------------------------------------------------------
void InitPieCtrl(void) { // 禁止PIE模塊 PieCtrl.PIECRTL.bit.ENPIE = 0; // 禁止PIE所有中斷 PieCtrl.PIEIER1.all = 0; PieCtrl.PIEIER2.all = 0; PieCtrl.PIEIER3.all = 0; PieCtrl.PIEIER4.all = 0; PieCtrl.PIEIER5.all = 0; PieCtrl.PIEIER6.all = 0; PieCtrl.PIEIER7.all = 0; PieCtrl.PIEIER8.all = 0; PieCtrl.PIEIER9.all = 0; PieCtrl.PIEIER10.all = 0; PieCtrl.PIEIER11.all = 0; PieCtrl.PIEIER12.all = 0; // 清除所有PIEIFR的中斷標(biāo)志位 PieCtrl.PIEIFR1.all = 0; PieCtrl.PIEIFR2.all = 0; PieCtrl.PIEIFR3.all = 0; PieCtrl.PIEIFR4.all = 0; PieCtrl.PIEIFR5.all = 0; PieCtrl.PIEIFR6.all = 0; PieCtrl.PIEIFR7.all = 0; PieCtrl.PIEIFR8.all = 0; PieCtrl.PIEIFR9.all = 0; PieCtrl.PIEIFR10.all = 0; PieCtrl.PIEIFR11.all = 0; PieCtrl.PIEIFR12.all = 0; // 使能PIE模塊 PieCtrl.PIECRTL.bit.ENPIE = 1; PieCtrl.PIEACK.all = 0xFFFF; } 下邊是DSP28_PieVect.c對PIE中斷向量初始化,執(zhí)行完這個程序之后,各個中斷函數(shù)有了入口地址。const struct PIE_VECT_TABLE PieVectTableInit = {省去}void InitPieVectTable(void) { int16 i; Uint32 *Source = (void *) &PieVectTableInit; Uint32 *Dest = (void *) &PieVectTable; EALLOW; for(i=0; i < 128; i++) *Dest++ = *Source++; EDIS; // 使能PIE向量表 PieCtrl.PIECRTL.bit.ENPIE = 1; }for(i=0; i < 128; i++)注意這里賦值了128次
這個程序大概就是設(shè)置定時器0的周期為1S,每隔1S進(jìn)入一次周期中斷
ConfigCpuTimer(&CpuTimer0, 150, 1000000); //Cpu定時器0的周期為1s StartCpuTimer0(); //啟動Cpu定時器0
void ConfigCpuTimer(struct CPUTIMER_VARS *Timer, float Freq, float Period) { Uint32 temp; Timer->CPUFreqInMHz = Freq; Timer->PeriodInUSec = Period; temp = (long) (Freq * Period); Timer->RegsAddr->PRD.all = temp; //給定時器周期寄存器賦值 Timer->RegsAddr->TPR.all = 0; //給定時器預(yù)定標(biāo)寄存器賦值 Timer->RegsAddr->TPRH.all = 0; // 初始化定時器控制寄存器: Timer->RegsAddr->TCR.bit.TIF=1; //清除中斷標(biāo)志位 Timer->RegsAddr->TCR.bit.TSS = 1; //停止定時器 Timer->RegsAddr->TCR.bit.TRB = 1; //定時器重裝,將定時器周期寄存器的值裝入定時器計(jì)數(shù)器寄存器 Timer->RegsAddr->TCR.bit.SOFT = 1; Timer->RegsAddr->TCR.bit.FREE = 1; Timer->RegsAddr->TCR.bit.TIE = 1; //使能定時器中斷 Timer->InterruptCount = 0; //初始化定時器中斷計(jì)數(shù)器 }然后每計(jì)數(shù)1S進(jìn)入一次中斷在中斷里邊編寫了燈閃碩的代碼
interrupt void TINT0_ISR(void) // CPU-Timer0中斷函數(shù) { CpuTimer0.InterruptCount++; if(CpuTimer0.InterruptCount==1) { GpioDataRegs.GPFCLEAR.bit.GPIOF14=1; //XF引腳低電平,D3亮 } if(CpuTimer0.InterruptCount==2) { GpioDataRegs.GPFSET.bit.GPIOF14=1; //XF引腳高電平,D3滅 CpuTimer0.InterruptCount=0; } CpuTimer0Regs.TCR.bit.TIF=1; //清除定時器中斷標(biāo)志位 PieCtrl.PIEACK.bit.ACK1=1; //響應(yīng)同組其他中斷 EINT; //開全局中斷 }