Chinaunix首页 | 论坛 | 博客
  • 博客访问: 482064
  • 博文数量: 98
  • 博客积分: 3265
  • 博客等级: 中校
  • 技术积分: 1227
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-23 00:29
文章分类

全部博文(98)

文章存档

2012年(6)

2011年(83)

2010年(9)

分类: 嵌入式

2011-03-18 15:41:45

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            @ 初始化LEDGPIO管脚

    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) |
给主人留下些什么吧!~~