S3C2410中断的定义的中断向量是从16~47.然后外部中断从48~69.70~80.一共有66(80-16)个中断其中70~78 UART是用来与PC进行通信的。
01 | 25 #define S3C2410_CPUIRQ_OFFSET (16) |
03 | 27 #define S3C2410_IRQ(x) ((x) + S3C2410_CPUIRQ_OFFSET) |
05 | 29 /* main cpu interrupts */ |
06 | 30 #define IRQ_EINT0 S3C2410_IRQ(0) /* 16 */ |
07 | 31 #define IRQ_EINT1 S3C2410_IRQ(1) |
08 | 32 #define IRQ_EINT2 S3C2410_IRQ(2) |
09 | 33 #define IRQ_EINT3 S3C2410_IRQ(3) |
10 | 34 #define IRQ_EINT4t7 S3C2410_IRQ(4) /* 20 */ |
11 | 35 #define IRQ_EINT8t23 S3C2410_IRQ(5) |
12 | 36 #define IRQ_RESERVED6 S3C2410_IRQ(6) /* for s3c2410 */ |
13 | 37 #define IRQ_CAM S3C2410_IRQ(6) /* for s3c2440,s3c2443 */ |
14 | 38 #define IRQ_BATT_FLT S3C2410_IRQ(7) |
15 | 39 #define IRQ_TICK S3C2410_IRQ(8) /* 24 */ |
16 | 40 #define IRQ_WDT S3C2410_IRQ(9) /* WDT/AC97 for s3c2443 */ |
17 | 41 #define IRQ_TIMER0 S3C2410_IRQ(10) |
18 | 42 #define IRQ_TIMER1 S3C2410_IRQ(11) |
19 | 43 #define IRQ_TIMER2 S3C2410_IRQ(12) |
20 | 44 #define IRQ_TIMER3 S3C2410_IRQ(13) |
21 | 45 #define IRQ_TIMER4 S3C2410_IRQ(14) |
22 | 46 #define IRQ_UART2 S3C2410_IRQ(15) |
23 | 47 #define IRQ_LCD S3C2410_IRQ(16) /* 32 */ |
24 | 48 #define IRQ_DMA0 S3C2410_IRQ(17) /* IRQ_DMA for s3c2443 */ |
25 | 49 #define IRQ_DMA1 S3C2410_IRQ(18) |
26 | 50 #define IRQ_DMA2 S3C2410_IRQ(19) |
27 | 51 #define IRQ_DMA3 S3C2410_IRQ(20) |
28 | 52 #define IRQ_SDI S3C2410_IRQ(21) |
29 | 53 #define IRQ_SPI0 S3C2410_IRQ(22) |
30 | 54 #define IRQ_UART1 S3C2410_IRQ(23) |
31 | 55 #define IRQ_RESERVED24 S3C2410_IRQ(24) /* 40 */ |
32 | 56 #define IRQ_NFCON S3C2410_IRQ(24) /* for s3c2440 */ |
33 | 57 #define IRQ_USBD S3C2410_IRQ(25) |
34 | 58 #define IRQ_USBH S3C2410_IRQ(26) |
35 | 59 #define IRQ_IIC S3C2410_IRQ(27) |
36 | 60 #define IRQ_UART0 S3C2410_IRQ(28) /* 44 */ |
37 | 61 #define IRQ_SPI1 S3C2410_IRQ(29) |
38 | 62 #define IRQ_RTC S3C2410_IRQ(30) |
39 | 63 #define IRQ_ADCPARENT S3C2410_IRQ(31) |
01 | 65 /* interrupts generated from the external interrupts sources */ |
02 | 66 #define IRQ_EINT4 S3C2410_IRQ(32) /* 48 */ |
03 | 67 #define IRQ_EINT5 S3C2410_IRQ(33) |
04 | 68 #define IRQ_EINT6 S3C2410_IRQ(34) |
05 | 69 #define IRQ_EINT7 S3C2410_IRQ(35) |
06 | 70 #define IRQ_EINT8 S3C2410_IRQ(36) |
07 | 71 #define IRQ_EINT9 S3C2410_IRQ(37) |
08 | 72 #define IRQ_EINT10 S3C2410_IRQ(38) |
09 | 73 #define IRQ_EINT11 S3C2410_IRQ(39) |
10 | 74 #define IRQ_EINT12 S3C2410_IRQ(40) |
11 | 75 #define IRQ_EINT13 S3C2410_IRQ(41) |
12 | 76 #define IRQ_EINT14 S3C2410_IRQ(42) |
13 | 77 #define IRQ_EINT15 S3C2410_IRQ(43) |
14 | 78 #define IRQ_EINT16 S3C2410_IRQ(44) |
15 | 79 #define IRQ_EINT17 S3C2410_IRQ(45) |
16 | 80 #define IRQ_EINT18 S3C2410_IRQ(46) |
17 | 81 #define IRQ_EINT19 S3C2410_IRQ(47) |
18 | 82 #define IRQ_EINT20 S3C2410_IRQ(48) /* 64 */ |
19 | 83 #define IRQ_EINT21 S3C2410_IRQ(49) |
20 | 84 #define IRQ_EINT22 S3C2410_IRQ(50) |
21 | 85 #define IRQ_EINT23 S3C2410_IRQ(51) |
24 | 88 #define IRQ_EINT(x) S3C2410_IRQ((x >= 4) ? (IRQ_EINT4 + (x) - 4) : (S3C2410_IRQ(0) + (x))) |
26 | 90 #define IRQ_LCD_FIFO S3C2410_IRQ(52) |
27 | 91 #define IRQ_LCD_FRAME S3C2410_IRQ(53) |
28 | 98 #define S3C2410_IRQSUB(x) S3C2410_IRQ((x)+54) |
30 | 100 #define IRQ_S3CUART_RX0 S3C2410_IRQSUB(0) /* 70 */ |
31 | 101 #define IRQ_S3CUART_TX0 S3C2410_IRQSUB(1) |
32 | 102 #define IRQ_S3CUART_ERR0 S3C2410_IRQSUB(2) |
34 | 104 #define IRQ_S3CUART_RX1 S3C2410_IRQSUB(3) /* 73 */ |
35 | 105 #define IRQ_S3CUART_TX1 S3C2410_IRQSUB(4) |
36 | 106 #define IRQ_S3CUART_ERR1 S3C2410_IRQSUB(5) |
38 | 108 #define IRQ_S3CUART_RX2 S3C2410_IRQSUB(6) /* 76 */ |
39 | 109 #define IRQ_S3CUART_TX2 S3C2410_IRQSUB(7) |
40 | 110 #define IRQ_S3CUART_ERR2 S3C2410_IRQSUB(8) |
42 | 112 #define IRQ_TC S3C2410_IRQSUB(9) |
43 | 113 #define IRQ_ADC S3C2410_IRQSUB(10) |
45 | 115 /* extra irqs for s3c2440 */ |
那么前16就是trap了。
这些中断向量的初始化是由
001 | 661 void __init s3c24xx_init_irq(void) |
003 | 663 unsigned long pend; |
004 | 664 unsigned long last; |
008 | 668 irqdbf("s3c2410_init_irq: clearing interrupt status flags\n"); |
010 | 670 /* first, clear all interrupts pending... */ |
013 | 673 for (i = 0; i < 4; i++) { |
014 | 674 pend = __raw_readl(S3C24XX_EINTPEND); |
016 | 676 if (pend == 0 || pend == last) |
019 | 679 __raw_writel(pend, S3C24XX_EINTPEND); |
020 | 680 printk("irq: clearing pending ext status %08x\n", (int)pend); |
025 | 685 for (i = 0; i < 4; i++) { |
026 | 686 pend = __raw_readl(S3C2410_INTPND); |
028 | 688 if (pend == 0 || pend == last) |
031 | 691 __raw_writel(pend, S3C2410_SRCPND); |
032 | 692 __raw_writel(pend, S3C2410_INTPND); |
033 | 693 printk("irq: clearing pending status %08x\n", (int)pend); |
038 | 698 for (i = 0; i < 4; i++) { |
039 | 699 pend = __raw_readl(S3C2410_SUBSRCPND); |
041 | 701 if (pend == 0 || pend == last) |
044 | 704 printk("irq: clearing subpending status %08x\n", (int)pend); |
045 | 705 __raw_writel(pend, S3C2410_SUBSRCPND); |
049 | 709 /* register the main interrupts */ |
051 | 711 irqdbf("s3c2410_init_irq: registering s3c2410 interrupt handlers\n"); |
053 | 713 for (irqno = IRQ_EINT4t7; irqno <= IRQ_ADCPARENT; irqno++) { |
054 | 714 /* set all the s3c2410 internal irqs */ |
057 | 717 /* deal with the special IRQs (cascaded) */ |
060 | 720 case IRQ_EINT8t23: |
064 | 724 case IRQ_ADCPARENT: |
065 | 725 set_irq_chip(irqno, &s3c_irq_level_chip); |
066 | 726 set_irq_handler(irqno, handle_level_irq); |
069 | 729 case IRQ_RESERVED6: |
070 | 730 case IRQ_RESERVED24: |
075 | 735 //irqdbf("registering irq %d (s3c irq)\n", irqno); |
076 | 736 set_irq_chip(irqno, &s3c_irq_chip); |
077 | 737 set_irq_handler(irqno, handle_edge_irq); |
078 | 738 set_irq_flags(irqno, IRQF_VALID); |
082 | 742 /* setup the cascade irq handlers */ |
084 | 744 set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7); |
085 | 745 set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8); |
087 | 747 set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0); |
088 | 748 set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1); |
089 | 749 set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2); |
090 | 750 set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc); |
092 | 752 /* external interrupts */ |
094 | 754 for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) { |
095 | 755 irqdbf("registering irq %d (ext int)\n", irqno); |
096 | 756 set_irq_chip(irqno, &s3c_irq_eint0t4); |
097 | 757 set_irq_handler(irqno, handle_edge_irq); |
098 | 758 set_irq_flags(irqno, IRQF_VALID); |
101 | 761 for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) { |
102 | 762 irqdbf("registering irq %d (extended s3c irq)\n", irqno); |
103 | 763 set_irq_chip(irqno, &s3c_irqext_chip); |
104 | 764 set_irq_handler(irqno, handle_edge_irq); |
105 | 765 set_irq_flags(irqno, IRQF_VALID); |
108 | 768 /* register the uart interrupts */ |
110 | 770 irqdbf("s3c2410: registering external interrupts\n"); |
112 | 772 for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) { |
113 | 773 irqdbf("registering irq %d (s3c uart0 irq)\n", irqno); |
114 | 774 set_irq_chip(irqno, &s3c_irq_uart0); |
115 | 775 set_irq_handler(irqno, handle_level_irq); |
116 | 776 set_irq_flags(irqno, IRQF_VALID); |
119 | 779 for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) { |
120 | 780 irqdbf("registering irq %d (s3c uart1 irq)\n", irqno); |
121 | 781 set_irq_chip(irqno, &s3c_irq_uart1); |
122 | 782 set_irq_handler(irqno, handle_level_irq); |
123 | 783 set_irq_flags(irqno, IRQF_VALID); |
126 | 786 for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) { |
127 | 787 irqdbf("registering irq %d (s3c uart2 irq)\n", irqno); |
128 | 788 set_irq_chip(irqno, &s3c_irq_uart2); |
129 | 789 set_irq_handler(irqno, handle_level_irq); |
130 | 790 set_irq_flags(irqno, IRQF_VALID); |
133 | 793 for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) { |
134 | 794 irqdbf("registering irq %d (s3c adc irq)\n", irqno); |
135 | 795 set_irq_chip(irqno, &s3c_irq_adc); |
136 | 796 set_irq_handler(irqno, handle_edge_irq); |
137 | 797 set_irq_flags(irqno, IRQF_VALID); |
140 | 800 irqdbf("s3c2410: registered interrupt handlers\n"); |
上面便是对中断向量进行赋值了。其中set_irq_chip是设置irq上的中断控制器。set_irq_handle便是设置该中断线上的处理函数了,比如ack mark之类的。set_irq_flags是设置该中断线的标志位,有哪些呢?
01 | 49 #define IRQ_INPROGRESS 0x00000100 /* IRQ handler active - do not enter! */ |
02 | 50 #define IRQ_DISABLED 0x00000200 /* IRQ disabled - do not enter! */ |
03 | 51 #define IRQ_PENDING 0x00000400 /* IRQ pending - replay on enable */ |
04 | 52 #define IRQ_REPLAY 0x00000800 /* IRQ has been replayed but not acked yet */ |
05 | 53 #define IRQ_AUTODETECT 0x00001000 /* IRQ is being autodetected */ |
06 | 54 #define IRQ_WAITING 0x00002000 /* IRQ not yet seen - for autodetection */ |
07 | 55 #define IRQ_LEVEL 0x00004000 /* IRQ level triggered */ |
08 | 56 #define IRQ_MASKED 0x00008000 /* IRQ masked - shouldn't be seen again */ |
09 | 57 #define IRQ_PER_CPU 0x00010000 /* IRQ is per CPU */ |
10 | 58 #define IRQ_NOPROBE 0x00020000 /* IRQ is not valid for probing */ |
11 | 59 #define IRQ_NOREQUEST 0x00040000 /* IRQ cannot be requested */ |
12 | 60 #define IRQ_NOAUTOEN 0x00080000 /* IRQ will not be enabled on request irq */ |
13 | 61 #define IRQ_WAKEUP 0x00100000 /* IRQ triggers system wakeup */ |
14 | 62 #define IRQ_MOVE_PENDING 0x00200000 /* need to re-target IRQ destination */ |
15 | 63 #define IRQ_NO_BALANCING 0x00400000 /* IRQ is excluded from balancing */ |
另外set_irq_handler我们来看一下:
02 | 535 __set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained, |
05 | 538 struct irq_desc *desc; |
06 | 539 unsigned long flags; |
08 | 541 if (irq >= NR_IRQS) { |
10 | 543 "Trying to install type control for IRQ%d\n", irq); |
14 | 547 desc = irq_desc + irq; |
16 | 549 if (!handle) //如果形参handle没有被赋值,那么先将之赋值为handle_bad_irq.在后面567行我们会看到,实际上是会执行卸载操作 |
17 | 550 handle = handle_bad_irq; |
18 | 551 else if (desc->chip == &no_irq_chip) { |
19 | 552 printk(KERN_WARNING "Trying to install %sinterrupt handler " |
20 | 553 "for IRQ%d\n", is_chained ? "chained " : "", irq); |
22 | 555 * Some ARM implementations install a handler for really dumb |
23 | 556 * interrupt hardware without setting an irq_chip. This worked |
24 | 557 * with the ARM no_irq_chip but the check in setup_irq would |
25 | 558 * prevent us to setup the interrupt at all. Switch it to |
26 | 559 * dummy_irq_chip for easy transition. |
28 | 561 desc->chip = &dummy_irq_chip; |
31 | 564 spin_lock_irqsave(&desc->lock, flags); |
34 | 567 if (handle == handle_bad_irq) { |
35 | 568 if (desc->chip != &no_irq_chip) |
36 | 569 mask_ack_irq(desc, irq); |
37 | 570 desc->status |= IRQ_DISABLED; |
40 | 573 desc->handle_irq = handle; |
另外,现在已经设置好中断向量了,那么这些中断向量在哪里放着呢?因为如果要响应中断的话,必须找到入口啊。
看一下trap_init函数:
01 | 678 void __init trap_init(void) |
03 | 680 unsigned long vectors = CONFIG_VECTORS_BASE; |
04 | 681 extern char __stubs_start[], __stubs_end[]; |
05 | 682 extern char __vectors_start[], __vectors_end[]; |
06 | 683 extern char __kuser_helper_start[], __kuser_helper_end[]; |
07 | 684 int kuser_sz = __kuser_helper_end - __kuser_helper_start; |
10 | 687 * Copy the vectors, stubs and kuser helpers (in entry-armv.S) |
11 | 688 * into the vector page, mapped at 0xffff0000, and ensure these |
12 | 689 * are visible to the instruction stream. |
14 | 691 memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start); |
15 | 692 memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start); |
16 | 693 memcpy((void *)vectors + 0x1000 - kuser_sz, __kuser_helper_start, kuser_sz); |
19 | 696 * Copy signal return handlers into the vector page, and |
20 | 697 * set sigreturn to be a pointer to these. |
22 | 699 memcpy((void *)KERN_SIGRETURN_CODE, sigreturn_codes, |
23 | 700 sizeof(sigreturn_codes)); |
25 | 702 flush_icache_range(vectors, vectors + PAGE_SIZE); |
26 | 703 modify_domain(DOMAIN_USER, DOMAIN_CLIENT); |
看到了吧,将__vectors_start~__vectors_end还有stub都移到了vector的位置,而vector的位置既是 CONFIG_VECTORS_BASE,
1 | 147 #define CONFIG_VECTORS_BASE 0xffff0000 |
那么__vector_start在哪里捏?
~/linux-2.6.21.1/arch/arm/kernel/entry-armv.S
1062 __vectors_start:
1063 swi SYS_ERROR0
1064 b vector_und + stubs_offset
1065 ldr pc, .LCvswi + stubs_offset
1066 b vector_pabt + stubs_offset
1067 b vector_dabt + stubs_offset
1068 b vector_addrexcptn + stubs_offset
1069 b vector_irq + stubs_offset
1070 b vector_fiq + stubs_offset
1071
1072 .globl __vectors_end
1073 __vectors_end:
在该文件,我们也可以找到__stub_start的变量地址。