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的变量地址。