DSP

F2812 PIE简介

2019-07-13 16:04发布

外设中断扩展模块(PIE:Peripheral Interrupt Expansion)是为了使 F2812 DSP 微处理器能够有效管理众多的中断而设计的。PIE 将 DSP 微处理器中的中断分组,使多个中断信号复用 1 个 CPU 级中断信号,从而使 CPU 能够高效地管理中断信号请求。
    
 
    PIE 管理的中断源共 96 个(其中正在使用的有45个,其它的作为扩展资源供厂商测试或留待芯片升级时使用),这些中断分为12 组,每个组有 8 个中断。这 12 组从 1 开始编号,依次分别接到 CPU 级的 INT1-INT12 中断信号上。96 个中断源对应 96 个中断向量,在存储器空间中专门留出一块来保存 96 个中断向量,当中断发生时,其对应的中断向量能够自动被取出从而调用相应的中断服务程序F2812 中断向量的取出和跳转是由硬件自动完成的,相对于软件分离子中断的方式,这种方式能够大大提高中断的响应速度)。 
    
   
注意:中断向量表是受 EALLOW 保护的。

PIE 配置及控制寄存器:
    
         
    PIE 相关的寄存器咋看一下非常多,但是如果按组归类,对于一个特定的中断,与它相关的寄存器就只有 PIECTRL、PIEACK、PIEIERx、PIEIFRx
    

    

    
   
    
    除了上述寄存器,中断还与 IFR、IER 寄存器及全局中断屏蔽位 INTM 相关,下图是典型的 PIE - CPU 响应流程:
    

    下面通过分析源代码来深入理解 F2812 中断机制:

void main()
{
   DINT;//关全局可屏蔽中断 #define  DINT   asm(" setc INTM")
   InitPieCtrl();//初始化pie寄存器
   IER = 0x0000;//禁止所有的中断
   IFR = 0x0000;
   InitPieVectTable();//初始化pie中断向量表
   EALLOW;  // This is needed to write to EALLOW protected registers
   PieVectTable.TINT0 = &cpu_timer0_isr;//指定中断服务子程序
   EDIS;

   ……    
// Enable CPU INT1 which is connected to CPU-Timer 0:
   IER |= M_INT1;  //#define M_INT1  0x0001
// Enable TINT0 in the PIE: Group 1 interrupt 7
   PieCtrlRegs.PIEIER1.bit.INTx7 = 1;
// Enable global Interrupts 
   EINT;   //#define  EINT   asm(" clrc INTM")

}    

// This function initializes the PIE control registers to a known state.
void InitPieCtrl(void)    @ DSP281x_PieCtrl.c
{
    // Disable Interrupts at the CPU level:
    DINT;

    // Disable the PIE
    PieCtrlRegs.PIECRTL.bit.ENPIE = 0;

    // Clear all PIEIER registers:
    PieCtrlRegs.PIEIER1.all = 0;
    PieCtrlRegs.PIEIER2.all = 0;
    PieCtrlRegs.PIEIER3.all = 0;    
    PieCtrlRegs.PIEIER4.all = 0;
    PieCtrlRegs.PIEIER5.all = 0;
    PieCtrlRegs.PIEIER6.all = 0;
    PieCtrlRegs.PIEIER7.all = 0;
    PieCtrlRegs.PIEIER8.all = 0;
    PieCtrlRegs.PIEIER9.all = 0;
    PieCtrlRegs.PIEIER10.all = 0;
    PieCtrlRegs.PIEIER11.all = 0;
    PieCtrlRegs.PIEIER12.all = 0;

    // Clear all PIEIFR registers:
    PieCtrlRegs.PIEIFR1.all = 0;
    PieCtrlRegs.PIEIFR2.all = 0;
    PieCtrlRegs.PIEIFR3.all = 0;    
    PieCtrlRegs.PIEIFR4.all = 0;
    PieCtrlRegs.PIEIFR5.all = 0;
    PieCtrlRegs.PIEIFR6.all = 0;
    PieCtrlRegs.PIEIFR7.all = 0;
    PieCtrlRegs.PIEIFR8.all = 0;
    PieCtrlRegs.PIEIFR9.all = 0;
    PieCtrlRegs.PIEIFR10.all = 0;
    PieCtrlRegs.PIEIFR11.all = 0;
    PieCtrlRegs.PIEIFR12.all = 0;
}

    使用 PIE 最重要的就是定义中断向量表,然后将其映射到指定的内存位置(0x00 0D00 - 0x00 0DFF,在 TI 提供的源代码中,向量表的定义如下(@ DSP281x_PieVector.h):
// Define Vector Table:  32+96 个函数指针,每个函数指针 32 位,整个向量表映射到 0x00 0D00 - 0x00 0DFF。

struct PIE_VECT_TABLE {
// Reset is never fetched from this table.  
// It will always be fetched from 0x3FFFC0 in either
// boot ROM or XINTF Zone 7 depending on the state of
// the XMP/MC input signal. 

      PINT     PIE1_RESERVED;  //
typedef interrupt void(*PINT)(void);
      PINT     PIE2_RESERVED;
      PINT     PIE3_RESERVED;
      PINT     PIE4_RESERVED;
      PINT     PIE5_RESERVED;
      ……
// Non-Peripheral Interrupts:
      PINT     XINT13;    // XINT13
      PINT     TINT2;     // CPU-Timer2
      PINT     DATALOG;   // Datalogging interrupt
      ……
// Group 1 PIE Peripheral Vectors:  定义12组PIE中断向量表
      PINT     PDPINTA;   // EV-A
      PINT     PDPINTB;   // EV-B
      ……
// Group 12 PIE Peripheral Vectors:
      PINT     rsvd12_1;
      PINT     rsvd12_2;
      ……
}
    上述只是定义一个中断向量表的结构体,在文件的最末尾才真正定义了一个 PIE_VECT_TABLE 变量:extern struct PIE_VECT_TABLE PieVectTable; 它的初始化是在 DSP281x_PieVector.文件 InitPieVectTable() 函数中完成的。
void InitPieVectTable(void)
{
    int16    i;
    Uint32 *Source = (void *) &PieVectTableInit;
    Uint32 *Dest = (void *) &PieVectTable;
        
    EALLOW;    
    for(i=0; i < 128; i++)
        *Dest++ = *Source++;    
    EDIS;

    // Enable the PIE Vector Table
    PieCtrlRegs.PIECRTL.bit.ENPIE = 1;    
            
}
    
InitPieVectTable() 函数中通过 PieVectTableInit 变量来初始化中断向量表 PieVectTable,PieVectTableInit 也是PIE_VECT_TABLE 结构体变量,里面初始化了各种中断函数的入口地址(定义在