您的位置:首页 > 其它

s3c24xx中断号(非向量中断)浅析

2016-07-01 16:14 197 查看
以S3C24XX为例:

 

根据中断入口跳转方法的不同,中断可分为向量中断和非向量中断。采用向量中断的CPU通常为不同的中断分配不同的中断号,当检测到某中断号中断到来后,就自动跳转到与该中断号对应的地址执行。不同的中断号的中断有不同的入口地址。非向量中断的多个中断共享一个入口地址,进入该入口地址后,再通过软件判断中断标志来识别具体是哪个中断。

 

也就是说,向量中断由硬件提供中断服务程序的入口地址,非向量中断由软件提供中断服务程序入口地址。

 

-------------------------------------------------------------------------------

asm_do_IRQ为中断的C语言入口函数:

asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)

{

struct pt_regs *old_regs = set_irq_regs(regs);

struct irq_desc *desc = irq_desc + irq;

/*

 * Some hardware gives randomly wrong interrupts.  Rather

 * than crashing, do something sensible.

 */

if (irq >= NR_IRQS)

desc = &bad_irq_desc;

irq_enter();

desc_handle_irq(irq, desc);

/* AT91 specific workaround */

irq_finish(irq);

irq_exit();

set_irq_regs(old_regs);

}

-------------------------------------------------------------------------------

其中,desc_handle_irq函数调用desc 结构中的handle_irq成员函数,它就是irq_desc[irq].handle_irq。

 

另外,asm_do_IRQ函数中参数irq的取值范围为(IRQ_EINT0~IRQ_ADCPARENT),共有32个取值。它可能对应一个实际的中断号, 也可能是一组中断的中断号,这是由芯片的特性决定的。

 

发生中断时INTPND寄存器的某一位被置1,INTOFFSET寄存器中记录了是哪一位(0~31),中断向量调用asm_do_IRQ之前根据INTOFFSET寄存器的值确定irq参数。

 

每一个实际的中断在irq_desc数组中都有一项与它对应,它们的数目不止32。

 

当asm_do_IRQ函数中参数irq表示的是一组中断时,irq_desc[irq].handle_irq成员函数还需要进一步分辨出是哪一个中断(假设中断号为52,对应IRQ_EINT8/S3C2410_IRQ(36)),然后调用irq_desc[52].handle_irq来进行处理。

-------------------------------------------------------------------------------

下面以外部中断EINT8~EINT23为例进一步分析:

 

它们被触发时,INTOFFSET寄存器中的值都是5,asm_do_IRQ函数中参数irq的值为IRQ_EINT8t23(21),
a5d9
则asm_do_IRQ函数中将调用irq_desc[IRQ_EINT8t23].handle_irq。

 

irq_desc[IRQ_EINT8t23].handle_irq在s3c24xx_init_irq函数中初始化中断体系结构的时候被设为s3c_irq_demux_extint8。

set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);

 

s3c_irq_demux_extint8函数首先读取EINTPEND、EINTMASK寄存器,确定发生了哪些中断,重新计算它们的中断号,然后调用desc
数组项中的handle_irq成员函数。

 

比如发生中断时对应的是EINT8,查看芯片手册可知,对应EINTPEND寄存器的第8位被置1,

所以irq=8+(IRQ_EINT4-4)=8+(48-4)=52,正好对应IRQ_EINT8/S3C2410_IRQ(36)=52,也就是说对应数组项irq_desc[52]。

 

s3c_irq_demux_extint8(unsigned int irq, struct irq_desc *desc)

{

unsigned long eintpnd = __raw_readl(S3C24XX_EINTPEND);

unsigned long eintmsk = __raw_readl(S3C24XX_EINTMASK);

eintpnd &= ~eintmsk;

eintpnd &= ~0xff; /* ignore lower irqs */

/* we may as well handle all the pending IRQs here */

while (eintpnd) {

irq = __ffs(eintpnd);

eintpnd &= ~(1<<irq);

irq += (IRQ_EINT4 - 4);

desc_handle_irq(irq, irq_desc + irq);

}

}

 

 

-------------------------------------------------------------------------------

/* we keep the first set of CPU IRQs out of the range of

 * the ISA space, so that the PC104 has them to itself

 * and we don't end up having to do horrible things to the

 * standard ISA drivers....

 */

 

#define S3C2410_CPUIRQ_OFFSET  (16)

 

#define S3C2410_IRQ(x) ((x) + S3C2410_CPUIRQ_OFFSET)

 

/* main cpu interrupts */

#define IRQ_EINT0      S3C2410_IRQ(0)     /* 16 */

#define IRQ_EINT1      S3C2410_IRQ(1)

#define IRQ_EINT2      S3C2410_IRQ(2)

#define IRQ_EINT3      S3C2410_IRQ(3)

#define IRQ_EINT4t7    S3C2410_IRQ(4)     /* 20 */

#define IRQ_EINT8t23   S3C2410_IRQ(5)

#define IRQ_RESERVED6  S3C2410_IRQ(6)     /* for s3c2410 */

#define IRQ_CAM        S3C2410_IRQ(6)     /* for s3c2440,s3c2443 */

#define IRQ_BATT_FLT   S3C2410_IRQ(7)

#define IRQ_TICK       S3C2410_IRQ(8)     /* 24 */

#define IRQ_WDT        S3C2410_IRQ(9)     /* WDT/AC97 for s3c2443 */

#define IRQ_TIMER0     S3C2410_IRQ(10)

#define IRQ_TIMER1     S3C2410_IRQ(11)

#define IRQ_TIMER2     S3C2410_IRQ(12)

#define IRQ_TIMER3     S3C2410_IRQ(13)

#define IRQ_TIMER4     S3C2410_IRQ(14)

#define IRQ_UART2      S3C2410_IRQ(15)

#define IRQ_LCD        S3C2410_IRQ(16)     /* 32 */

#define IRQ_DMA0       S3C2410_IRQ(17)     /* IRQ_DMA for s3c2443 */

#define IRQ_DMA1       S3C2410_IRQ(18)

#define IRQ_DMA2       S3C2410_IRQ(19)

#define IRQ_DMA3       S3C2410_IRQ(20)

#define IRQ_SDI        S3C2410_IRQ(21)

#define IRQ_SPI0       S3C2410_IRQ(22)

#define IRQ_UART1      S3C2410_IRQ(23)

#define IRQ_RESERVED24 S3C2410_IRQ(24)     /* 40 */

#define IRQ_NFCON      S3C2410_IRQ(24)     /* for s3c2440 */

#define IRQ_USBD       S3C2410_IRQ(25)

#define IRQ_USBH       S3C2410_IRQ(26)

#define IRQ_IIC        S3C2410_IRQ(27)

#define IRQ_UART0      S3C2410_IRQ(28)     /* 44 */

#define IRQ_SPI1       S3C2410_IRQ(29)

#define IRQ_RTC        S3C2410_IRQ(30)

#define IRQ_ADCPARENT  S3C2410_IRQ(31)

 

/* interrupts generated from the external interrupts sources */

#define IRQ_EINT4      S3C2410_IRQ(32)    /* 48 */

#define IRQ_EINT5      S3C2410_IRQ(33)

#define IRQ_EINT6      S3C2410_IRQ(34)

#define IRQ_EINT7      S3C2410_IRQ(35)

#define IRQ_EINT8      S3C2410_IRQ(36)

#define IRQ_EINT9      S3C2410_IRQ(37)

#define IRQ_EINT10     S3C2410_IRQ(38)

#define IRQ_EINT11     S3C2410_IRQ(39)

#define IRQ_EINT12     S3C2410_IRQ(40)

#define IRQ_EINT13     S3C2410_IRQ(41)

#define IRQ_EINT14     S3C2410_IRQ(42)

#define IRQ_EINT15     S3C2410_IRQ(43)

#define IRQ_EINT16     S3C2410_IRQ(44)

#define IRQ_EINT17     S3C2410_IRQ(45)

#define IRQ_EINT18     S3C2410_IRQ(46)

#define IRQ_EINT19     S3C2410_IRQ(47)

#define IRQ_EINT20     S3C2410_IRQ(48)    /* 64 */

#define IRQ_EINT21     S3C2410_IRQ(49)

#define IRQ_EINT22     S3C2410_IRQ(50)

#define IRQ_EINT23     S3C2410_IRQ(51)

-------------------------------------------------------------------------------
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: