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)
-------------------------------------------------------------------------------
根据中断入口跳转方法的不同,中断可分为向量中断和非向量中断。采用向量中断的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)
-------------------------------------------------------------------------------
相关文章推荐
- Spring MVC整理系列(05)————Spring MVC配置解析及整合SpriSpring MVC之@ModelAttribute、@SessionAttributes以及Model的使用介绍
- Android自定义弹出框开发-生成Window容器
- 新安装的Centos 7找不到hgfs
- centOS目录结构详细版
- Android 性能优化 二 TraceView工具的使用
- 解决6.0以上ScrollView嵌套RecyclerView能同时滑动的问题。
- 深入浅出 - Android系统移植与平台开发(十四) - Sensor HAL框架分析之四
- tomcat的webApps和work目录.
- Hadoop家族系列文章
- 项目管理理论与实践(1)——企业项目管理介绍
- pod安装失败,Operation not permitted - /usr/bin/pod
- Python设置默认编码为utf8的方法
- mybatis框架(动态SQL语句)
- Codeforces Round #360 (Div. 2)
- Spring @Transactional工作原理
- Spring + iBatis 的多库横向切分简易解决思路
- Apache模块管理
- Assetbundle资料整理(二)
- 项目管理理论与实践(2)——软件需求分析
- 项目管理理论与实践(3)——如何进行有效的项目管理