SRCPND--源中断指示寄存器 则相应的中断源
32位中的每一位对应着一个中断源,每一位被设置为1,则相应的中断源产生中断请求并且等待中断被服务因此这个寄存器表明哪个中断源在等待中断请求被处理。注意:SRCPND寄存器是自动设置的。,同时不管INTMSK寄存器中的屏蔽位是否置1.在指定的中断源的服务程序中。SRCPND相应的位必须被清除,这样才可以正确的响应同一中断源的中断请求。如果从ISR返回而没有清除相应的位,也就是说SRCPND中对应的还是1,那么就会一直相应这个中断请求。如何清除:相应位写1。
INTMOD--中断模式寄存器
32位中的每一位对应一个中断源,当每一位都设置为1,则ARM内核将以FIQ模式相应中断,否则以IRQ模式。
INTPND--中断请求寄存器
32位中的每一位对应着相应的中断请求,经过优先级逻辑后,INTPND寄存器只能有一位被设置为1。并且ARM产生中断请求。在IRQ中断服务程序中能够读取这个寄存器的值来决定32个中断源的哪一个中断被服务。同SRCPND寄存器,在中断服务程序里,这个寄存器的相应为需要被清除。我们可以向INTPND寄存器写一个数据1,来清除寄存器的指定位。
INTMSK--中断屏蔽寄存器
如果相应指定位被设置为1,ARM将不相应中断源的中断请求(注意:即使SRCPND相应为被置位1的条件下也不响应),相反为0时候,则响应。
SUBSRCPND--次级中断指示寄存器
INTSUBMSK--次级中断屏蔽寄存器
下面结合今天学习的红外模块的实验理解中断控制器的相关编程:
//红外模块发送测试程序
void Test_IrDA_Tx(void)
{
int i;
IrDA_cnt=0;
IrDA_end=0;
IrDAdataFl=(volatile U8 *)IrDABUFFER;//volatile U8 *IrDAdataFl,IrDABUFFER=0x31000000
IrDAdataPt=(volatile U8 *)IrDABUFFER;
IrDA_Port_Init();
for(i=0;i<IrDA_BUFLEN;i++) *IrDAdataFl++=i; // Initialize IrDA Tx data
pISR_UART2=(U32)IrDA_TxInt;
//指针指向这个函数。这里是UART2向量中断入口,IrDA_Txint是服务程序的 函数,下面再分析。
//这里为什么要这样来执行这个函数呢?我的理解是:每次有数据时候
//都要发生一次中断,都要做一些保持记录相关数据,在这里有0x100个数据
//这样进入中断的时间就成为0x100倍时间了,占用了很多时间。所以现在就用空间换时间
//的方法,先把这个函数的地址在程序空间保存起来,然后每次要中断的时候PC指针就执行执行
//这个地址开始的代码。
/*其中#define pISR_UART2 (*(unsigned *)(_ISR_STARTADDRESS+0x5c)) 定义了向量入口地址因为之前在ISR_INIT()里面把所谓的总开关INTMSK写了1,屏蔽了中断,所以刚开始的时候不会发生中断,也就是说不会跳到这个中断地址里面执行,但会把IrDA_TxInt这个函数的地址放到向量中断pISR_UART2这里。如下反汇编代码可以看到保持段地址偏移量pc指针
0x00000290: e59f0144 D... LDR r0,0x3dc
0x00000294: e59f1144 D... LDR r1,0x3e0
0x00000298: e5810f5c \... STR r0,[r1,#0xf5c]
0x0000029c: e28f0f50 P... ADD r0,pc,#0x140 ; #0x3e4
。。。。。
$d
0x000003dc: 00000000 .... DCD 0
0x000003e0: 33fff000 ...3 DCD 872411136
0x000003e4: 6c65530a .Sel DCD 1818579722
。。。。。。。*/
Uart_Printf("\nSelect the baud rate\n"); // Select IrDA baud rate
Uart_Printf("1)9600 2)19200 3)38400 4)57600 5)115200\n");
i=Uart_Getch ();
switch(i)//选择设置波特率
{
case '1':
IrDA_BAUD=9600;
break;
case '2':
IrDA_BAUD=19200;
break;
case '3':
IrDA_BAUD=38400;
break;
case '4':
IrDA_BAUD=57600;
break;
case '5':
IrDA_BAUD=115200;
break;
default:
break;
}
rUBRDIV2=( (int)(PCLK/16./IrDA_BAUD) -1 );
Uart_Printf("rUBRDIV2=%d\n", rUBRDIV2);
Uart_Printf("[UART IrDA Tx Test]\n");
Uart_Printf("Start Rx first and press any key and...\n");
Uart_TxEmpty(1);
//transmit FIFO=16B;receive FIFO=1B;Tx FIFO reset;Rx FIFO reset;FIFO Enable
rUFCON2=(1<<6)|(0<<4)|(1<<2)|(1<<1)|(1);
//Tx and Rx FIFO Trigger Level:4byte,Tx and Rx FIFO Reset,FIFO on
rUCON2=(0<<10)|(1<<9)|(1<<8)|(0<<7)|(0<<6)|(0<<5)|(0<<4)|(0<<2)|(0); // From H/W
//Infrared Tx/Rx mode;No parity;One stop bit;8bit
rULCON2=(1<<6)|(0<<3)|(0<<2)|(3); // IrDA,No parity,One stop bit, 8bit
Uart_Getch();
rUCON2 |= (1<<2); // Tx enable
Uart_Printf("Now... Tx with IrDA\n");
//开UART2中断及子中断
rINTMSK=~(BIT_UART2);
rINTSUBMSK=~(BIT_SUB_RXD2|BIT_SUB_TXD2|BIT_SUB_ERR2);
while(!IrDA_end);//发送结束
//关UART2子中断
rINTSUBMSK|=(BIT_SUB_RXD2|BIT_SUB_TXD2|BIT_SUB_ERR2);
//transmit FIFO=48B;receive FIFO=32B;Tx FIFO reset;Rx FIFO reset;FIFO disable
rUFCON2=(3<<6)|(2<<4)|(1<<2)|(1<<1)|(0);
Uart_Printf("\nEnd Tx, transfer data count=%d\n",IrDA_cnt);
}
********************************************************************************************************************************
/*解析中断流程:开始在中断初始化的时候设置》中断模式》INTMSK和INTSUBMSK(总屏蔽和子屏蔽开关)写1屏蔽掉》开INTMSK相应位》开INTSUBMSK相应位》中断发生》进入中断》关相应的中断》《相应服务处理程序》》发生中断后的处理(清楚相应中断请求》SRCPND,INTPND,SUBSRCPND『这些只包括UART CAM WTDAC ADC』这些,还有EINTPEND)》》又开相应中断等待中断
void __irq IrDA_TxInt(void)
{
//关闭UART2子中断 这里用到的是次级中断,所以程序只是针对INTSUBMSK来设置
rINTSUBMSK|=(BIT_SUB_RXD2|BIT_SUB_TXD2|BIT_SUB_ERR2);//写入1,屏蔽中断 08.4.21 caibaihui
if(IrDA_cnt < (IrDA_BUFLEN))
{
Uart_Printf("%d,",*IrDAdataPt);//上面初始化了它的值1.2.3.....0x100
WrUTXH2(*IrDAdataPt++);
IrDA_cnt++;
//清除UART2中断
ClearPending(BIT_UART2);
/*__inline void ClearPending(int bit)
{
rSRCPND |= bit;
rINTPND |= bit;
*/
//清除TXD2子中断
rSUBSRCPND=(BIT_SUB_TXD2);
//开TXD2子中断
rINTSUBMSK&=~(BIT_SUB_TXD2);
}
else
{
IrDA_end=1;
while(rUFSTAT2 & 0x2f0); //Until FIFO is empty
while(!(rUTRSTAT2 & 0x4)); //Until Tx shifter is empty
//清除TXD2子中断
ClearPending(BIT_UART2);
//关UART2
rINTMSK|=BIT_UART2;
}
}
评论
发表评论