TMS320F28335学习笔记:
EALLOW,EDIS是成对使用的,有些寄存器是受到保护的,不能任意写,EALLOW相当于去掉保护,对写保护的寄存器进行操作后EDIS是重新把这个寄存器保护起来的意思。
关于中断
TMS320F28335内部有16个中短线,其中包括2个不可屏蔽中断(RESET和NMI)与14个可屏蔽中断通过相应的中断使能寄存器可以使能或者禁止产生的中断。
外部中断源:DSP芯片IO引脚上的电平变化触发中断
内部中断源:DSP内部CPU和各个外设模块产生的中断比如ADC、PWM、SCI、SPI等等模块产生的中断。
TMS320F28335处理器中,定时器1和定时器2预留给实时操作系统使用,其中中断分配给INT13和INT14,两个不可屏蔽的中断RESET和NMI各自占用独立的专用中断,同时NMI中断可以直接同定时器1复用INT13,其余12个可屏蔽中断直接连接在外设中断扩展模块(PIE模块),供外部中断可处理器内部外设单元使用。
PIE模块
PIE模块通过12根线与28335核的12个中断线相连。而PIE的另外一侧有12*8根线分别连接到外设,如AD、SPI、EXINT等等。这样PIE共管理12*8=96个外部中断。这12组大中断由28335核的中断寄存器IER来控制,即IER确定每个中断到底属于哪一组大中断(如IER |= M_INT12;说明我们要用第12组的中断,但是第12组里面的什么中断CPU并不知道需要再由PIEIER确定)。接下来再由PIE模块中的寄存器PIEIER中的低8确定该中断是这一组的第几个中断,这些配置都要告诉CPU(我们不难想象到PIEIER共有12总即从PIEIER1-PIEIER12)。另外,PIE模块还有中断标志寄存器PIEIFR,同样它的低8位是来自外部中断的8个标志位,同样CPU的IFR寄存器是中断组的标志寄存器。由此看来,CPU的所有中断寄存器控制12组的中断,PIE的所有中断寄存器控制每组内8个的中断。除此之外,我们用到哪一个外部中断,相应的还有外部中断的寄存器,需要注意的就是外部中断的标志要自己通过软件来清零。而PIE和CPU的中断标志寄存器由硬件来清零。
用户中断分为三部分:外设级、PIE级、CPU级
三级串联构成一路中断。
1.外设级中断——中断标志必须采用软件进行清除
2.PIE中断可以支持96个独立中断,这些中断分为8个小组,每个小组包含12个中断。
CPU经过9个时钟周期获取中断向量地址和保存关键寄存器数据之后才能执行中断程序。
28335在CPU级支持一个不可屏蔽中断(NMI)和16个可屏蔽中断(INT1-INT14,RTOSINT,DLOGINT)。
PIE模块汇集8个外设和管脚中断进入一个CPU中断
PIE group1 ----group12分别对应了CPU中断1---中断12
对于不可屏蔽中断来说,它直接进入CPU级。
对于可屏蔽中断来说,PIE模块有相关的标志寄存器(PIEIFRx和PIEIERx)(x=1-------12)每一个位设为y(y=1-----8)
PIEIERx.y和PIEIFRx.y,
除此之外,对于每一个PIE中断组来说(1----12)还有一个PIE响应标志位PIEACK,如PIEACKx(x=1----12)
机理如下:当有中断请求进入PIE控制器的时候,相关的PIE中断标志位PIEIFRx.y置高。如果PIE中断允许位PIEIERx.y也置高的时候,PIE控制器机会检查PIEACKx标志位来决定CPU是否已经准备好接收这个PIE中断组的中断。
如果PIEACKZx被清零了,那么PIE会把这个中断请求送到CPU级。
如果PIEACKx位置一,那么PIE就会等待直到这个标志位清零然后发送中断请求给CPU级的INTx。(TMS320F2833XSYSTEM CONTROL AND INTERRUPTS REFERENCE GUIDE)
PIE中断寄存器:PIECTRL,PIEACK,PIEIFRx
3 CPU级中断
一旦中断请求到达CPU级,CPU级和INTx相对应的中断标志位(IFR)置一,如果CPU中断允许寄存器(IER)或者调试中断允许寄存器(DBGIER)和全局中断屏蔽位(INTM)允许的话,CPU才会执行这个中断申请。
中断过程中需要手动清零的寄存器:PIEACKx写1清零
CPU中断寄存器:IFR,IER,XINTnCR外部中断控制寄存器(支持XINT1~XINT7,n=1~7。XINT13和不可屏蔽中断XNMI多路复用),XNMICR外部NMI中断控制寄存器
定时器对一般的控制器和DSP芯片来说是一个基本的外设,C2000系列DSP的定时器操作方法基本上差不多,就以28335的定时器0为例,说下其使用。
定时器0使用
(1)首先应打开Timer的时钟使能 SysCtrlRegs.PCLKCR3.bit.CPUTIMER0ENCLK = 1;// CPU Timer 0
(2)在主程序添加外设中断句柄(a)使能定时器中断TCR寄存器(b)IER|=M_INT1;使能连接的INT1中断;(c)PieCtrlRegs.PIEIER1.bit.INTx7=1;使能TINT0,1组中第7中断;
(3)初始化时钟:包括初始化Timer0定时器指向相应的地址;定时周期设定;定时器时钟配置,定时器分频设定,可概括为InitCpuTimers();
(4)配置Timer0,即为ConfigCpuTimer(&CpuTimer0,150, 500000);
(5)开中断EINT;ERTM;
(6)开定时器:CpuTimer0Regs.TCR.bit.TSS=0;
(7)中断响应函数中需要:PieCtrlRegs.PIEACK.all= PIEACK_GROUP1;
下面是一个外部中断的例子,外面有一个按钮接到GPIO15上输入作为外部中断源,每次按一下按钮触发一个中断,在ISR中count+1。
// TITLE: DSP2833xExternal Interrupt test program.
// Xint1 inputis synched to SYSCLKOUT
// WatchVariables:
// Xint1Countfor the number of times through Xint1 interrupt
// LoopCountfor the number of times through the idle loop
#include "DSP28x_Project.h" // Device Headerfile and Examples IncludeFile
// Prototype statements for functions found within thisfile.
interrupt void xint1_isr(void);
// Global variables for this example
volatile Uint32 Xint1Count;
Uint32 LoopCount;
#define DELAY 35.700L
void main(void)
{
// Step 1. Initialize SystemControl:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in theDSP2833x_SysCtrl.c file.
InitSysCtrl();
// Step 2. Initalize GPIO:
// This example function is found in the DSP2833x_Gpio.cfile and
// illustrates how to set the GPIO to it's default state.
// InitGpio(); // Skipped for thisexample
// Step 3. Clear all interrupts andinitialize PIE vector table:
// Disable CPU interrupts
DINT;
// Initialize PIE control registers to their defaultstate.
// The default state is all PIE interrupts disabled andflags
// are cleared.
// This function is found in the DSP2833x_PieCtrl.c file.
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interruptflags:
IER = 0x0000;
IFR = 0x0000;
// Initialize the PIE vector table with pointers to theshell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if theinterrupt
// is not used in this example. This is useful for debug purposes.
// The shell ISR routines are found inDSP2833x_DefaultIsr.c.
// This function is found in DSP2833x_PieVect.c.
InitPieVectTable();
// Interrupts that are used in this example are re-mappedto
// ISR functions found within this file.
EALLOW; // Thisis needed to write to EALLOW protected registers
PieVectTable.XINT1= &xint1_isr;
EDIS; // This is needed to disable write to EALLOWprotected registers
// Step 4. Initialize all theDevice Peripherals:
// This function is found in DSP2833x_InitPeripherals.c
// InitPeripherals(); // Not required for this example
// Step 5. User specific code,enable interrupts:
// Clear the counters
Xint1Count = 0;// Count Xint1 interrupts
LoopCount =0; // Count times through idle loop
// 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
PieCtrlRegs.PIEIER1.bit.INTx4= 1; // Enable PIE Gropu 1INT4 XINT1
IER |=M_INT1; // Enable CPU int1
EINT; //Enable Global Interrupts
// GPIO0 are inputs
EALLOW;
GpioCtrlRegs.GPAMUX1.bit.GPIO15= 0; // GPIO 15作为GPIO ,接到按钮上
GpioCtrlRegs.GPADIR.bit.GPIO15 = 0; // input作为输入
GpioCtrlRegs.GPAQSEL1.bit.GPIO15 = 0;// Xint1 Synch to SYSCLKOUT only,在PDF里搜GPAQSEL关键词
EDIS;
// GPIO15 is XINT1
EALLOW;
GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL = 15; // Xint1 is GPIO0 修改 GPIO15 GPIO 15作为外部中断1
EDIS;
// Configure XINT1
XIntruptRegs.XINT1CR.bit.POLARITY = 0; // Falling edge interrupt 下降沿触发
// Enable XINT1
XIntruptRegs.XINT1CR.bit.ENABLE = 1; // Enable Xint1
// Step 6. IDLE loop:
for(;;)
{ }
}
// Step 7. Insert all localInterrupt Service Routines (ISRs) and functions here:
// If local ISRs are used, reassign vector addresses invector table as
// shown inStep 5
interrupt void xint1_isr(void)
{
//GpioDataRegs.GPBCLEAR.all = 0x4; // GPIO34 is low
Xint1Count++;
// Acknowledge this interrupt to get more from group 1
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1; //0x0001,第一组的ACK写1清零
}
DINT :禁止中断
EINT :允许中断