|
奇怪,我之前发的帖子怎么不见了?
搂主,你这个问题我解决了,你看看我下面贴的程序理注释的地方.没法改成红色的,就在注释未安装前的那个地方. 这个程序是可以运行的,你可以复制到你的机器上试试.
/* 说明: 下面程序从ads1.2\EXAMPLES\EMBEDDED\RPS_IRQ移植而来.
程序主要用来演示怎样使用armulator的定时器中断.
关键的地方在:
1>.要打开中断.
2>.要更改IRQ的服务程序.
3>.'服务程序'必须离'矢量'在32MB范围内.即25位地址.
4>.无中断矢量初始化程序(无.s文件),只修改了IRQ.
5>.目标CPU必须与调试器一致(如同是arm920T).
*/
#include // for printf()
#include // for exit(1)
/**********/
/* 中断源 */
/**********/
#define IRQUser 0x0001
#define IRQProgrammed 0x0002
#define IRQCommsRx 0x0004
#define IRQCommsTx 0x0008
#define IRQTimer1 0x0010
#define IRQTimer2 0x0020
/**************************/
/* 标准存储器映射外设基址 */
/**************************/
#define IntBase 0x0A000000 /* 中断控制器 */
#define TimerBase 0x0A800000 /* 定时器 */
/*****************/
/* 定时器寄存器 */
/*****************/
#define Timer1Load (*(volatile unsigned *)TimerBase)
#define Timer1Value (*(volatile unsigned *)(TimerBase + 0x04))
#define Timer1Control (*(volatile unsigned *)(TimerBase + 0x08))
#define Timer1Clear (*(volatile unsigned *)(TimerBase + 0x0C))
#define Timer2Load (*(volatile unsigned *)(TimerBase + 0x020))
#define Timer2Value (*(volatile unsigned *)(TimerBase + 0x024))
#define Timer2Control (*(volatile unsigned *)(TimerBase + 0x028))
#define Timer2Clear (*(volatile unsigned *)(TimerBase + 0x02C))
/****************/
/* 定时器控制位 */
/****************/
#define TimerEnable 0x80
#define TimerPeriodic 0x40
#define TimerPrescale0 0x00
#define TimerPrescale4 0x04
#define TimerPrescale8 0x08
#define TimerDisable 0x00
#define TimerCyclic 0x00
/*************************/
/* 中断控制器 IRQ 寄存器 */
/*************************/
#define IRQStatus (*(volatile unsigned *)IntBase)
#define IRQRawStatus (*(volatile unsigned *)(IntBase + 0x04))
#define IRQEnable (*(volatile unsigned *)(IntBase + 0x08))
#define IRQEnableSet (*(volatile unsigned *)(IntBase + 0x08))
#define IRQEnableClear (*(volatile unsigned *)(IntBase + 0x0c))
#define IRQSoft (*(volatile unsigned *)(IntBase + 0x10))
int IntCT1 = 0;
int IntCT2 = 0;
int Count = 0;
unsigned *irqvec = (unsigned *)0x18;//IRQ
void __irq IRQ_Handler(void)
{
unsigned status;
status = IRQStatus;
/* 处理中断源 */
if (status & IRQTimer1)
{
Timer1Clear = 0;/* 清除中断 */
IntCT1++; /* 置标记 */
}
else if (status & IRQTimer2)
{
Timer2Clear = 0;/* 清除中断 */
IntCT2++; /* 置标记 */
}
}
/* ************************************************** */
/* 更新'矢量'的内容使他包含一个转移到'服务程序'的指令 */
/* 函数返回原'矢量'值. */
/* 注意: '服务程序'必须离'矢量'在32MB范围内. */
/* ************************************************** */
unsigned Install_Handler (unsigned routine, unsigned *vector)
{
unsigned vec, oldvec;
vec = ((routine - (unsigned)vector - 0x8)>>2);
if (vec & 0xff000000)
{
printf ("Installation of Handler failed");
exit(1);
}
vec = 0xea000000 | vec;//EA=
oldvec = *vector;
*vector = vec;
return (oldvec);
}
/* ************************************************** */
/* 打开或关闭中断 */
/* 通过读 cpsr 标记然后更新第7位来打开或关闭中断 */
/* 这些函数只能用于 privileged 模式,因为cpsr和spsr的 */
/* 控制位在用户模式下不能改变. */
/* ************************************************** */
__inline void enable_IRQ(void)
{
int tmp;
__asm
{
MRS tmp, CPSR
BIC tmp, tmp, #0x80
MSR CPSR_c, tmp
}
}
//
__inline void disable_IRQ(void)
{
int tmp;
__asm
{
MRS tmp, CPSR
ORR tmp, tmp, #0x80
MSR CPSR_c, tmp
}
}
//
// 如果目标为920T则要清除所有中断捕获!
int main(void)
{
printf("Timer Interrupt Example\n");
//未安装前 00000018 [0xe7ff0010] dci 0xe7ff0010 ; ? undefined
//使地址(IRQ)00000018处为: [0xea002022] * b IRQ_Handler
Install_Handler ((unsigned)IRQ_Handler, irqvec);
printf("Normal (RAM at 0x8000, semihosting) version\n\n");
printf("Initializing...\n");
//打开中断
enable_IRQ();
//
IRQEnableClear = ~0; // 清除所有的中断
Timer1Control = 0; // 通过控制位关闭计数器
Timer2Control = 0;
Timer1Clear = 0 ; // 通过写任何值到'清除'清除寄存器来清除中断
Timer2Clear = 0 ;
Timer1Load = 2000; // 装计数器值
Timer2Load = 8000;
Timer1Control = (TimerEnable | // 使能定时器
TimerPeriodic | // 周期性产生中断
TimerPrescale8 ); // 置最大预分频8位
Timer2Control = (TimerEnable |
TimerPeriodic |
TimerPrescale8 );
IRQEnableSet = IRQTimer1 | IRQTimer2; // 使能2个定时器中断
printf("Running...\n");
IntCT1 = 0; // 清 CT1 标记
IntCT2 = 0; // 清 CT2 标记
Count = 0;
while ( Count < 20 )
{
if (IntCT1 != 0) // 定时器1产生中断
{
Count++;
printf("IntCT1\n");
IntCT1 = 0; // 复位定时器1中断标记
}
if (IntCT2 != 0) // 定时器2产生中断
{
Count++;
printf("IntCT2\n");
IntCT2 = 0; // 复位定时器2中断标记
}
}
printf("Ended\n");
disable_IRQ();
}
|
|