阅读:2030回复:1
ARM中中断使用请教
小弟我初来乍到的,先问声好!
这段时间我正好遇到一个ARM中断的问题,想请教各位。 我的ARM CPU 是用OKI的uPLAT 7C(ARM7TDMI),RTOS 是用的uITRON 3.0。他们的资料在网上都有(如果找不到,给我mail,我传给你,我现在忘记他们的URL了)。 下面是我的系统的某些方面的描述(不好意思,是用英文写的): There is a interrupt enable register: TIE, which is at the address: 0xB000_041C; There is a interrupt request register: TIREQ, which is at the address: 0xB000_0424; There is a interrupt status register: TIRST, which is at the address: 0xB000_0434; These 3 register is a group, and the \"status register\" = \"enable regsiter\" AND(&) \"request register\". That is mean CPU set the enable register, the hardware set the request register, and the CPU check whether is there interrupt by checking the status register. And the CPU clear the interrupt by clearing the request register. The TIREQ\'s bit0 indicate: sync word reception interrupt; The TIREQ\'s bit1 indicate: packet header reception interrupt; The TIREQ\'s bit2 indicate: receive data read request; TIREQ\'s bit3 - bit7 are other interrupt. Actually, I just want to control the sync word reception interrupt correctly at first. And, all these hardware generated interrupt just affect the IRQ15(my system defined). That is to say it affect the IRQ(0x7800_0000)\'s bit15. The RTOS has defined the interrupt vector table as following code: //Code begin /* Interrupt vector Table */ #ifndef INTVEC #define INTVEC 0x1000000L #endif #ifndef INTVSZ #define INTVSZ 512 #endif //code end But unfortunately, RTOS defined INTVEC value will cause the system halt, because it use a un-exist memory address(0x1000000) in my board. The RTOS require use the sysini() function to init the system. This function will invoke the following function: //Code begin ER intini(void) { #if (INTVSZ!=0) int i; /* Initialize vector table */ for (i = 0; i < (INTVSZ) / 4; i++) ((UW *)INTVEC) = (UW)interr;//Get problem here!!! #endif return E_OK; } //Code end So, I change INTVEC as the other value. I have change it to: 0x78000000(IRQ\'s address) and 0xB0000434(TIRST\'s address), just let the RTOS can init the system. Actually, I don\'t know what the right value should be set here. And the following is the uPLAT ARM CPU\'s interrupt controller define(provided by the RTOS): /* Interrupt Controller Register Address */ #define IRQ 0x78000000 /* IRQ Status Register */ #define IRQS 0x78000004 /* IRQ Software Interrupt Register */ #define FIQ 0x78000008 /* FIQ Status Register */ #define FIQRAW 0x7800000C /* FIQRAW Status Register */ #define FIQEN 0x78000010 /* FIQ Enable Register */ #define IRNR 0x78000014 /* IRQ Number Register */ #define CILR 0x78000018 /* Current IRQ Level Register */ #define IRL 0x7800001C /* IRQ Level Register */ #define ILCR0 0x78000020 /* IRQ Level Control Register0 */ #define ILCR1 0x78000024 /* IRQ Level Control Register1 */ /* Interrupt Number */ #define INT_nIR0 0 #define INT_TIMER 0 #define INT_nIR1 1 #define INT_nIR2 2 #define INT_nIR3 3 #define INT_nIR4 4 #define INT_nIR5 5 #define INT_nIR6 6 #define INT_nIR7 7 #define INT_nIR8 8 #define INT_nIR9 9 #define INT_nIR10 10 #define INT_SIO 10 #define INT_nIR11 11 #define INT_nIR12 12 #define INT_nIR13 13 #define INT_nIR14 14 #define INT_nIR15 15 我写下面两个中断出来测试程序。一个是ARM的例子,另外一个是iTRON的用法。 In the iTRON, there are several related functions: ent_ini: interrupt handler start; ret_int: return from the interrupt handler; debug_counter is global structure in the program. And the counter debug_counter.interrupt is the counter for interrupt. //Code begin //ISR 方法1 __irq void IRQ_handler(void) { volatile u32 *source = (u32 *)0xB0000434; if (*source & 0x01 ) { debug_counter.interrupt = debug_counter.interrupt + 1; if (debug_counter.interrupt>=0xefffffff) debug_counter.interrupt = 0; } *(source+1) = 0; } //ISR 方法2 INTHDR inthdr_test(void) { ent_int(); debug_counter.interrupt = debug_counter.interrupt + 1; if (debug_counter.interrupt>=0xefffffff) debug_counter.interrupt = 0; ret_int(); } //Code end 我的main函数如下: //Code begin void main(void) { volatile s32 iTRON_error_flg; u32 i,j,k; /* Initialize processor Please customize !!*/ init_peripheral(); /* Initialize system */ sysini(); ini_pio(); /*Test function is here!*/ IRQ_handler(); //inthdr_test(); iTRON_error_flg = cre_tsk(TSK_MAIN, &ctsk_main); iTRON_error_flg = cre_tsk(TSK_RCV_BB, &ctsk_rcv_BB); iTRON_error_flg = cre_tsk(TSK_SND_BB, &ctsk_snd_BB); iTRON_error_flg = cre_tsk(TSK_RCV_HCI, &ctsk_rcv_HCI); iTRON_error_flg = cre_tsk(TSK_SND_HCI, &ctsk_snd_HCI); // cre_sem(SEM_BB_SEND, &csem_BB_send); iTRON_error_flg = cre_mbx(MBX_ID_BB_SEND, &cmbx_BB_send); iTRON_error_flg = sta_tsk(TSK_RCV_BB, 0); iTRON_error_flg = sta_tsk(TSK_SND_BB, 0); iTRON_error_flg = sta_tsk(TSK_RCV_HCI, 0); iTRON_error_flg = sta_tsk(TSK_SND_HCI, 0); iTRON_error_flg = sta_tsk(TSK_MAIN, 0); // iTRON_error_flg = sta_tsk(TSK_MAIN_SUB, 0); /* Start multitask system */ intsta(); /* Start interval timer interrupt */ syssta(); /* enter into multi task */ } //Code end If I use the IRQ_handler function, if there is interrupt(TIRST\'s bit0, I can check it in the ADW by its address), the counter will change. But, the program always there. When it finished IRQ_handler function\'s code, and it jump out, but the cursor still stay in this function, and the program will jump into this function again(no relationship whether is there interrupt). So, the program can\'t run the following other code. If I use the inthdr_test function, when the program run the ret_int(), the program will get an error and return to the ENTRY area. 我的问题有如下几个: 1、INTVEC 的define应该是多少? 2、我的中断服务程序(ISR)的写法对吗?(我其实只要相应IRQ中的IRQ15就可以了,然后再在ISR中根据相应寄存器的哪个比特是1来判断作什么工作)我应该用上面两种中的哪种? 3、ISR程序应该怎样用? 是把他放在main()中,当成一个函数一样呢(如前面的main函数)?还是就定义ISR,然后不管它,有硬件中断(IRQ15)时它自动跑进来(但是这样我的counter一直是0)? 4、怎样清中断? 是不是直接对TIREQ寄存器的相应比特置0。 |
|
最新喜欢:flyhua... |
沙发#
发布于:2002-05-23 16:02
不是很明白,我有一个在UC/OS系统上运行的程序,启动代码是用汇编做的,具体的处理是用C写的。
|
|