/****************************************************************************************/ /* NAME: test.c */ /* DESC: test doby through I/O Port with timer interrupt(1s). */ /* Date: 06.18.2008 */ /* version: 0.0 */ /* Program: Shen Hui (Shh) */ /****************************************************************************************/ /* 程序主要演示怎样使用armulator的定时器中断.输入也可以不在程序中赋值,直接在内存中改 */ /* 关键的地方在: */ /* 1>.要打开中断. */ /* 2>.要更改IRQ的服务程序. */ /* 3>.'服务程序'必须离'矢量'在32MB范围内.即25位地址. */ /* 4>.无中断矢量初始化程序(无.s文件),只设置了IRQ. */ /* 5>.目标CPU必须与调试器一致(例如,同是arm920T). */ /* 6>.MMU/PU initialization Pagetab必须设置为NO_PAGERABLES,否则映射不对 */ /****************************************************************************************/ /*Input: */ /* 0805ff01: D0-start h active */ /* 0805ff02: D0-stop l active */ /*Output: */ /* 0805ff0d: D0-doby1 l active 0805ff0e: D0-doby1 l active */ /* D1-doby1 l active D1-doby1 l active */ /* D2-doby1 l active D2-doby1 l active */ /* D3-doby1 l active D3-doby1 l active */ /* D4-doby1 l active D4-doby1 l active */ /* D5-doby1 l active D5-doby1 l active */ /* D6-doby1 l active D6-doby1 l active */ /* D7-doby1 l active D7-doby1 l active */ /****************************************************************************************/
#include "test.h"
void itoa2(unsigned short n, unsigned char *str) {//not find itoa in stdlib.h int i=0; int swap; do { str[i]=n%2+'0'; i++; }while(n/=2); str[i--]='/0'; for(n=0; n<i; n++, i--) { swap=str[n]; str[n]=str[i]; str[i]=swap; } }
void __irq IRQ_Handler(void) { unsigned status;
status = IRQStatus; /* 处理中断源 */ if (status & IRQTimer1) { Timer1Clear = 0; /* 清除中断 */ IntCT1++; /* 置标记 */ } }
/* ************************************************** */ /* 更新'矢量'的内容使他包含一个转移到'服务程序'的指令 */ /* 函数返回原'矢量'值. */ /* 注意: '服务程序'必须离'矢量'在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) { unsigned short Mask=1; unsigned char *str; DOBYINPUT0_7=0xff; DOBYINPUT8_F=0xff; // itoa2(0x1234,str ); // printf("str %s/n",str); printf("Timer Interrupt/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; // 通过控制位关闭计数器 Timer1Clear = 0 ; // 通过写任何值到'清除'清除寄存器来清除中断 Timer1Load = 2000; // 装计数器值,可通过晶频计算,这里2000只是为了测试
Timer1Control = (TimerEnable | TimerPeriodic | TimerPrescale8 );
IRQEnableSet = IRQTimer1;
printf("Running.../n");
IntCT1 = 0; // 清 CT1 标记 while (START) { if(STOP) break; if (IntCT1 != 0) // 定时器1产生中断 { IntCT1 = 0; // 复位定时器1中断标记 DOBYOUTPUT0_7 = (~Mask) & 0xFF; DOBYOUTPUT8_F =((~Mask) & 0xFF00)>>8; itoa2(Mask,str); printf("%016s/n",str); Mask<<=1; if(Mask==0) Mask=1; } } printf("Ended/n"); disable_IRQ(); }