中断架构
C28x CPU
有
14
个外设中断线。 其中两个(INT13 和
INT14
)分别直接连接到
CPU
定时器
1
和
2
。 其 余12
个通过增强型外设中断扩展模块(ePIE 或缩写版
PIE
)连接到外设中断信号。
PIE
将多达十六个外设中断复用到每个 CPU
中断线中。 它还扩展向量表,以允许每个中断具有自己的
ISR
。 这允许
CPU
支 持大量的外设。
TMS320F2837X
系列
DSP
的中断由
3
级组成,外设级,
PIE
级,
CPU
级(
PIE
),它们的构成如图:

中断路径分为三个阶段-外设级中断,PIE 级中断和 CPU 级中断。每级中断有自己的使能和标志寄存器。该系统允许 CPU 处理一个中断,而其他中断处于待处理状态,在软件中实现和优先化嵌套中断,并在某些关键任务期间禁用中断。最内核的部分为 CPU 级中断,也就是 CPU只能响应从 CPU 中断线上过来的中断请求,但 28377 中断源众多,CPU 没有那么多中断线在有限中断线的情况下,只能安排中断线进行复用。每级中断有自己的使能和标志寄存器。 该系统允许 CPU 处理一个中断,而其他中断处于待处理状态,在软件中实现和优先化嵌套中 断,并在某些关键任务期间禁用中断。图 2.6.4 显示了 28377 中断的传递路径架构。
当外设产生中断(在 PIE 组 x,通道 y 上)时,它会触发以下事件序列:
1.
中断被锁存在
PIEIFRx.y
中。
2.
如果设置了
PIEIERx.y
,中断将传递。
3.
如果
PIEACK.x
清零,则中断传递,
PIEACK.x
被置位。
4.
中断在
IFR.x
中被锁存。
5.
如果设置了
IER.x
,则中断传播。
6.
如果
INTM
清零,
CPU
接收中断。
7.
在通道的
D2
或更后阶段的任何指令都要完成。早期阶段的指令被刷新。
8.
CPU
将其上下文保存在堆栈中。
9.
清除
IFR.x
和
IER.x
。
INTM
设置。
EALLOW
被清除。
10.
CPU
从
PIE
中获取
ISR
向量。
PIEIFRx.y
被清除。
11.
CPU
分支到
ISR
。
中断延迟是
PIEIFRx.y
锁存中断和第一条
ISR
指令进入
CPU
流水线执行阶段之间的时间。最小中断延迟为 14 个
SYSCLK
周期。
ISR
或堆栈存储器上的等待状态将增加延迟。外部中断至少为
GPIO
同步增加两个 SYSCLK 周期,以及额外的输入验证时间(如果使用)。使用
C28x RPT
指令创建的循环不能中断。
使用与配置
上电时,默认情况下不会启用中断。
PIEIER
和
IER
寄存器被清零,
INTM
置
1
。 应用代码负责配置和使能 所有外设中断。
要启用外设中断,请执行以下步骤:
1.
全局禁止中断(
DINT
或
SETC INTM
)。
2.
通过设置
PIECTRL
寄存器的
ENPIE
位来使能
PIE
。
3.
将每个中断的
ISR
向量写入
PIE
向量表中的相应位置,可在
Table 2-2
中找到。
4.
为每个中断设置相应的
PIEIERx
位。
PIE
组和通道分配可以在
Table 2-2
中找到。
5.
为包含已启用中断的任何
PIE
组设置
CPU IER
位。
6.
在外设中使能中断。
7.
全局使能中断(
EINT
或
CLRC INTM
)。
步骤
4
不适用于直接连接到
CPU。

//按键按下,对应数码显示数字+1
#include "F28x_Project.h" // Device Headerfile and Examples Include File
#include "F2837xD_Ipc_drivers.h"
void GPIO_Setup(void);
void SEG_DATA(unsigned char d);
interrupt void xint1_isr(void);
interrupt void xint2_isr(void);
interrupt void xint3_isr(void);
interrupt void xint4_isr(void);
void ExintInit();
#define SBIT3 GpioDataRegs.GPBDAT.bit.GPIO58
#define SBIT2 GpioDataRegs.GPBDAT.bit.GPIO59
#define SBIT1 GpioDataRegs.GPBDAT.bit.GPIO60
#define SBIT0 GpioDataRegs.GPBDAT.bit.GPIO61
unsigned char const table[]={//共阴极0~f数码管编码
0xfc,0x60,0xda,0xf2, //0~3
0x66,0xb6,0xbe,0xe0, //4~7
0xfe,0xf6 //8~9
};
Uint16 InterruptCount1 = 0,InterruptCount2 = 0,InterruptCount3 = 0,InterruptCount4 = 0;
void main(void)
{
// Step 1. 初始化系统,锁相环,看门狗,外设时钟
InitSysCtrl();
#ifdef _STANDALONE
#ifdef _FLASH
// 发送引导命令以允许CPU2应用程序开始执行烧写
IPCBootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH);
#else
// 发送引导命令以允许CPU2应用程序开始仿真
IPCBootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_RAM);
#endif
#endif
#ifdef _FLASH
InitFlash();
#endif
// Step 2. 初始化GPIO:
InitGpio();
GPIO_Setup();
ExintInit();
// Step 3. 清除所有中断;初始化中断向量表;禁止CPU中断
DINT;
// 初始化PIE控制寄存器至默认状态,默认状态所有PIE中断被禁止;所有标志位被清除。
InitPieCtrl();
//禁止所有CPU中断,清除CPU中断相关标志位。
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found in F2837xD_DefaultIsr.c.
// This function is found in F2837xD_PieVect.c.
InitPieVectTable();
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.XINT1_INT = &xint1_isr;//地址赋给PIE通道的这几个中断
PieVectTable.XINT2_INT = &xint2_isr;
PieVectTable.XINT3_INT = &xint3_isr;
PieVectTable.XINT4_INT = &xint4_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
// Step 4. User specific code, enable interrupts:
// Enable XINT1 and XINT2 in the PIE: Group 1 interrupt 4 & 5
// Enable INT1 which is connected to WAKEINT:
PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable the PIE block
/*使能PIE通道*/
PieCtrlRegs.PIEIER1.bit.INTx4 = 1; // Enable PIE Group 1 INT4
PieCtrlRegs.PIEIER1.bit.INTx5 = 1; // Enable PIE Group 1 INT5
PieCtrlRegs.PIEIER12.bit.INTx1 = 1; // Enable PIE Group 12 INT1
PieCtrlRegs.PIEIER12.bit.INTx2 = 1; // Enable PIE Group 12 INT2
/*使能PIE组*/
IER |= M_INT1;//根据CPU向量中断表使能PIE1组和12组
IER |= M_INT12;
// Enable global Interrupts and higher priority real-time debug events:
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
SBIT0=1;DELAY_US(1);
SBIT1=1;DELAY_US(1);
SBIT2=1;DELAY_US(1);
SBIT3=1;DELAY_US(1);
SEG_DATA(table[0]);
while(1)
{
SEG_DATA(table[InterruptCount2]);
SBIT0=0;DELAY_US(1);
SBIT2=1;DELAY_US(1);
SBIT1=1;DELAY_US(1);
SBIT3=1;
DELAY_US(100);
SBIT0=1;
SEG_DATA(0);
SEG_DATA(table[InterruptCount1]);
SBIT1=0;DELAY_US(1);
SBIT2=1;DELAY_US(1);
SBIT3=1;DELAY_US(1);
SBIT0=1;
DELAY_US(100);
SBIT1=1;
SEG_DATA(0);
SEG_DATA(table[InterruptCount4]);
SBIT2=0;DELAY_US(1);
SBIT1=1; DELAY_US(1);
SBIT3=1;DELAY_US(1);
SBIT0=1;
DELAY_US(100);
SBIT2=1;
SEG_DATA(0);
SEG_DATA(table[InterruptCount3]);
SBIT3=0;DELAY_US(1);
SBIT1=1;DELAY_US(1);
SBIT2=1;DELAY_US(1);
SBIT0=1;
DELAY_US(100);
SBIT3=1;
SEG_DATA(0);
}
}
void GPIO_Setup()
{
GPIO_SetupPinMux(58, GPIO_MUX_CPU1, 0);//BIT3
GPIO_SetupPinOptions(58, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(59, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(59, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(60, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions(60, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(61, GPIO_MUX_CPU1, 0);//BIT0
GPIO_SetupPinOptions(61, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(77, GPIO_MUX_CPU1, 0);//dp
GPIO_SetupPinOptions(77, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(78, GPIO_MUX_CPU1, 0);//g
GPIO_SetupPinOptions(78, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(79, GPIO_MUX_CPU1, 0);//f
GPIO_SetupPinOptions(79, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(80, GPIO_MUX_CPU1, 0);//e
GPIO_SetupPinOptions(80, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(81, GPIO_MUX_CPU1, 0);//d
GPIO_SetupPinOptions(81, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(82, GPIO_MUX_CPU1, 0);//c
GPIO_SetupPinOptions(82, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(83, GPIO_MUX_CPU1, 0);//b
GPIO_SetupPinOptions(83, GPIO_OUTPUT, GPIO_PUSHPULL);
GPIO_SetupPinMux(85, GPIO_MUX_CPU1, 0);//a
GPIO_SetupPinOptions(85, GPIO_OUTPUT, GPIO_PUSHPULL);
}
void ExintInit()
{
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO12 = 0; // GPIO
GpioCtrlRegs.GPADIR.bit.GPIO12 = 0; // input
GpioCtrlRegs.GPAQSEL1.bit.GPIO12 = 1; // XINT1 Synch to SYSCLKOUT only
GpioCtrlRegs.GPAMUX1.bit.GPIO13 = 0; // GPIO
GpioCtrlRegs.GPADIR.bit.GPIO13 = 0; // input
GpioCtrlRegs.GPAQSEL1.bit.GPIO13 = 1; // XINT2 Synch to SYSCLKOUT only
GpioCtrlRegs.GPAMUX1.bit.GPIO14 = 0; // GPIO
GpioCtrlRegs.GPADIR.bit.GPIO14 = 0; // input
GpioCtrlRegs.GPAQSEL1.bit.GPIO14 = 1; // XINT4 Synch to SYSCLKOUT only
GpioCtrlRegs.GPAMUX1.bit.GPIO15 = 0; // GPIO
GpioCtrlRegs.GPADIR.bit.GPIO15 = 0; // input
GpioCtrlRegs.GPAQSEL1.bit.GPIO15 = 1; // XINT5 Synch to SYSCLKOUT only
EDIS;
GPIO_SetupXINT1Gpio(12); // GPIO12 is XINT1
XintRegs.XINT1CR.bit.POLARITY = 0; // Falling edge interrupt
XintRegs.XINT1CR.bit.ENABLE = 1; // Enable XINT1
GPIO_SetupXINT2Gpio(13); // GPIO13 is XINT2
XintRegs.XINT2CR.bit.POLARITY = 0; // Falling edge interrupt
XintRegs.XINT2CR.bit.ENABLE = 1; // Enable XINT1
GPIO_SetupXINT3Gpio(14); // GPIO14 is XINT4
XintRegs.XINT3CR.bit.POLARITY = 0; // Falling edge interrupt
XintRegs.XINT3CR.bit.ENABLE = 1; // Enable XINT12
GPIO_SetupXINT4Gpio(15); // GPIO15 is XINT5
XintRegs.XINT4CR.bit.POLARITY = 0; // Falling edge interrupt
XintRegs.XINT4CR.bit.ENABLE = 1; // Enable XINT12
}
void SEG_DATA(unsigned char d)
{
Uint32 dat1 = 0,dat2 = 0;
dat1 = d;//假设0,则0xfc=0x1111 1010
dat1 <<= 13; //左移13位, C组GPIO是从GPIO64开始的(77-64=13) 0x1111 1010 13个0
dat2 = d;//假设0,则0xfc=0x1111 1010
dat2 <<= 13;//0x1111 1010 13个0 映射到 95~85-84-83-82-81-80-79-78-77~64
dat2 &= 0x100000;//0x1111 1010 13个0
dat2 <<= 1;//1111 0100 12个0 1 映射到 95~85-84-83-82-81-80-79-78-77~64
dat1 |= dat2;//0x1111 1010 13个0 | 1111 0100 12个0 1 = 0x1111 1110 12个0 1
GpioDataRegs.GPCDAT.all = dat1;//C组GPIO95-64
}
interrupt void xint1_isr(void)
{
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;//PIE组应答
DELAY_US(1000);
if(GpioDataRegs.GPADAT.bit.GPIO12 == 0) InterruptCount1++;
if(InterruptCount1 > 9) InterruptCount1 = 0;
}
interrupt void xint2_isr(void)
{
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
DELAY_US(1000);
if(GpioDataRegs.GPADAT.bit.GPIO13 == 0) InterruptCount2++;
if(InterruptCount2 > 9) InterruptCount2 = 0;
}
interrupt void xint3_isr(void)
{
PieCtrlRegs.PIEACK.all = PIEACK_GROUP12;
DELAY_US(1000);
if(GpioDataRegs.GPADAT.bit.GPIO14 == 0) InterruptCount3++;
if(InterruptCount3 > 9) InterruptCount3 = 0;
}
interrupt void xint4_isr(void)
{
PieCtrlRegs.PIEACK.all = PIEACK_GROUP12;
DELAY_US(1000);
if(GpioDataRegs.GPADAT.bit.GPIO15 == 0) InterruptCount4++;
if(InterruptCount4 > 9) InterruptCount4 = 0;
}