S3C2440A 中的中断控制器接受来自60 个中断源的请求,部分中断源附带子中断源,他们共用一个中断源。两类中断:IRQ中断和FIQ中断,每一个中断都可以设为IRQ或FIQ,IRQ中断还需经过优先级判决器判定中断流程:以带子中断源的中断有中断为例:带子中断源的中断有中断长生,则子中断源请求寄存器(SUBSRCPND)相应位被置1,该位表明了是哪个子中断源长生的中断,然后看看该中断是否被屏蔽,该屏蔽由子中断屏蔽寄存器(SUBMASK)设置,然后源中断请求寄存器(SRCPND)相应为被置1,该位表明了是哪个中断源长生的,然后看看该中断是否被屏蔽,由中断屏蔽寄存器(MASK)设置,然后再看该中断被设为IRQ还是FIQ,该设置由中断模式寄存(MODE)设置,IRQ中断的话,还要看它的优先级,由优先级寄存器设定,最后得出优先级高的那个中断,在最终的中断请求寄存器(INTPND)中,相应的位被置1,最后等待着CPU响应中断。中断的清除顺序:首先清除SUBSRCPND,然后SRCPND,最后INTPND,清除标志位只须往相应的位写1即可中断优先级每个仲裁器的1 位仲裁器模式控制(ARB_MODE)和选择控制信号(ARB_SEL)的2 位控制优先级,如下:– 如果ARB_SEL 位为00b,优先级顺序为REQ0、REQ1、REQ2、REQ3、REQ4 和REQ5。– 如果ARB_SEL 位为01b,优先级顺序为REQ0、REQ2、REQ3、REQ4、REQ1 和REQ5。– 如果ARB_SEL 位为10b,优先级顺序为REQ0、REQ3、REQ4、REQ1、REQ2 和REQ5。– 如果ARB_SEL 位为11b,优先级顺序为REQ0、REQ4、REQ1、REQ2、REQ3 和REQ5。REQ0 的优先级总是最高并且REQ5 的优先级总是最低。通过改变ARB_SEL 位,可以轮换REQ1 到REQ4 的顺序。如果ARB_MODE 位被设置为0,ARB_SEL 位不能自动改变,这使得仲裁器操作在固定优先级模式中如果ARB_MODE 1,ARB_SEL 位会被轮换方式而改变,例如如果REQ1 被服务,ARB_SEL 位被自动改为01b 以便REQ1 进入到最低的优先级。ARB_SEL 改变的详细结果如下:– 如果REQ0 或REQ5 被服务,ARB_SEL 位不会改变– 如果REQ1 被服务,ARB_SEL 位被改为01b。– 如果REQ2 被服务,ARB_SEL 位被改为10b。– 如果REQ3 被服务,ARB_SEL 位被改为11b。– 如果REQ4 被服务,ARB_SEL 位被改为00b。IRQ类型的中断优先级,FIQ不存在,从上倒下,优先级依次降低中断向量:#define _RAM_STARTADDRESS 0x30000000#define _ISR_STARTADDRESS 0x33ffff00 #define _MMUTT_STARTADDRESS 0x33ff8000#define _STACK_BASEADDRESS 0x33ff8000#define HEAPEND 0x33ff0000#define _NONCACHE_STARTADDRESS 0x31000000#define pISR_RESET (*(unsigned *)(_ISR_STARTADDRESS+0x0))#define pISR_UNDEF (*(unsigned *)(_ISR_STARTADDRESS+0x4))#define pISR_SWI (*(unsigned *)(_ISR_STARTADDRESS+0x8))#define pISR_PABORT (*(unsigned *)(_ISR_STARTADDRESS+0xc))#define pISR_DABORT (*(unsigned *)(_ISR_STARTADDRESS+0x10))#define pISR_RESERVED (*(unsigned *)(_ISR_STARTADDRESS+0x14))#define pISR_IRQ (*(unsigned *)(_ISR_STARTADDRESS+0x18))#define pISR_FIQ (*(unsigned *)(_ISR_STARTADDRESS+0x1c))#define pISR_EINT0 (*(unsigned *)(_ISR_STARTADDRESS+0x20))#define pISR_EINT1 (*(unsigned *)(_ISR_STARTADDRESS+0x24))#define pISR_EINT2 (*(unsigned *)(_ISR_STARTADDRESS+0x28))#define pISR_EINT3 (*(unsigned *)(_ISR_STARTADDRESS+0x2c))#define pISR_EINT4_7 (*(unsigned *)(_ISR_STARTADDRESS+0x30))#define pISR_EINT8_23 (*(unsigned *)(_ISR_STARTADDRESS+0x34))#define pISR_CAM (*(unsigned *)(_ISR_STARTADDRESS+0x38))#define pISR_BAT_FLT (*(unsigned *)(_ISR_STARTADDRESS+0x3c))#define pISR_TICK (*(unsigned *)(_ISR_STARTADDRESS+0x40))#define pISR_WDT_AC97 (*(unsigned *)(_ISR_STARTADDRESS+0x44)) #define pISR_TIMER0 (*(unsigned *)(_ISR_STARTADDRESS+0x48))#define pISR_TIMER1 (*(unsigned *)(_ISR_STARTADDRESS+0x4c))#define pISR_TIMER2 (*(unsigned *)(_ISR_STARTADDRESS+0x50))#define pISR_TIMER3 (*(unsigned *)(_ISR_STARTADDRESS+0x54))#define pISR_TIMER4 (*(unsigned *)(_ISR_STARTADDRESS+0x58))#define pISR_UART2 (*(unsigned *)(_ISR_STARTADDRESS+0x5c))#define pISR_LCD (*(unsigned *)(_ISR_STARTADDRESS+0x60))#define pISR_DMA0 (*(unsigned *)(_ISR_STARTADDRESS+0x64))#define pISR_DMA1 (*(unsigned *)(_ISR_STARTADDRESS+0x68))#define pISR_DMA2 (*(unsigned *)(_ISR_STARTADDRESS+0x6c))#define pISR_DMA3 (*(unsigned *)(_ISR_STARTADDRESS+0x70))#define pISR_SDI (*(unsigned *)(_ISR_STARTADDRESS+0x74))#define pISR_SPI0 (*(unsigned *)(_ISR_STARTADDRESS+0x78))#define pISR_UART1 (*(unsigned *)(_ISR_STARTADDRESS+0x7c))#define pISR_NFCON (*(unsigned *)(_ISR_STARTADDRESS+0x80))#define pISR_USBD (*(unsigned *)(_ISR_STARTADDRESS+0x84))#define pISR_USBH (*(unsigned *)(_ISR_STARTADDRESS+0x88))#define pISR_IIC (*(unsigned *)(_ISR_STARTADDRESS+0x8c))#define pISR_UART0 (*(unsigned *)(_ISR_STARTADDRESS+0x90))#define pISR_SPI1 (*(unsigned *)(_ISR_STARTADDRESS+0x94))#define pISR_RTC (*(unsigned *)(_ISR_STARTADDRESS+0x98))#define pISR_ADC (*(unsigned *)(_ISR_STARTADDRESS+0x9c))//中断处理程序,以__irq标明
void __irq IicISR(void)
{
rSRCPND |= 0x1<<27;
rINTPND |= 0x1<<27;
flag = 0; //清标志
}
//中断处理程序与中断源的并联
pISR_UART0 = (U32)uartISR;
pISR_IIC = (U32)IicISR;
1,系统默认分配那几个向量地址
A,当然第一个是复位,复位程序那里禁用掉看门狗,设置各个中断模式的SP位置
注意:调用C函数,首先要设置好堆栈,例如main函数。
B,其他几个中断向量入口地址,当发生相应的中断后,系统自动跳到相应的入口地址处
2,中断处理程序:
a) 计算返回地址
b) 保护现场,压入那个模式的堆栈
c) 中断处理
d) 清除中断标志
e) 恢复现场
f) 中断返回
.global _start
_start:
b Reset
HandleUndef:
b HandleUndef
HandleSWI:
b HandleSWI
HandlePrefetchAbort:
b HandlePrefetchAbort
HandleDataAbort:
b HandleDataAbort
HandleNotUsed:
b HandleNotUsed
HandleIRQ:
b HandleIRQ
HandleFIQ:
b HandleFIQ
Reset:
ldr sp, =4096 @ 设置栈指针,因为以下都是C函数 bl disable_watch_dog @ 关闭看门狗否则CPU会不断重启
msr cpsr_c, #0xd2 @ 进入中断模式
ldr sp, =3072 @ 设置中断模式栈指针
msr cpsr_c, #0xd3 @ 进入管理模式
ldr sp, =4096 @ 设置管理模式栈指针,
@ 其实复位之后,CPU就处于管理模式,
bl init_led @ 初始化LED的GPIO管脚
bl init_irq @ 调用中断初始化函数,在init.c中
msr cpsr_c, #0x53 @ 设置I-bit=0,开IRQ中断
ldr lr, =halt_loop @ 设置返回地址
ldr pc, =main @ 调用main函数
halt_loop:
b halt_loop
HandleIRQ:
sub lr, lr, #4 @ 计算返回地址
stmdb sp!, { r0-r12,lr } @ 保存使用到的寄存器
@ 注意,此时的sp是中断模式的sp
@ 初始值是上面设置的3072
ldr lr, =int_return @ 设置调用EINT_Handle函数的返回地址
ldr pc, =EINT_Handle @ 调用中断服务函数在interrupt.c中
int_return:
ldmia sp!, { r0-r12,pc }^ @ 中断返回, ^表示将spsr的值复制到cpsr
void EINT_Handle()
{
unsigned long oft = INTOFFSET;
unsigned long val;
switch( oft )
{
// S2被按下
case
『本文转载自网络,版权归原作者所有,如有侵权请联系删除』