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 0:
case1:
。。。。。
}
//清中断
if( oft == 5
)
EINTPEND
= (1<<11); // EINT8_23合用IRQ5
SRCPND =
1<
INTPND =
1<
}
阅读(2451) | 评论(0) | 转发(0) |