知识点
1、中断的概念
2、中断源
3、中断过滤
4、中断处理
中断:
cpu在工作的过程中经常需要与外设进行交互,交互的方式包括轮询方式和中断方式。
轮询方式:
cpu不断地查询设备的状态,该方式实现简单,但是cpu消耗大。
中断方式:
CPU在告知硬件开始一项工作后,就调度到其他事情了,当该硬件完成该事件后,会向CPU发送信号,告知CPU它已经完成了该项工作。实际上是cpu有一个状态寄存器,每次执行指令的时候会检查状态寄存器的值。CPU接收到中断信号时,CPU会立即进入到中断模式。
中断的生命周期:
中断信号产生(中断源)---> 中断信号过滤(中断控制器)--->中断信号处理(CPU)
中断源:
在中断生命周期中,中断源的作用是负责产生中断信号,每个cpu支持的中断源数量是不同的。
s3c2440支持60个中断源
s5pv210支持93个中断源
中断过滤:
代码分析
start.S
.text .global _start _start: b reset ldr pc, _undifined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq _undifined_instruction: .word undifined_instruction _software_interrupt: .word software_interrupt _prefetch_abort: .word prefetch_abort _data_abort: .word data_abort _not_used: .word not_used _irq: .word irq _fiq: .word reset undifined_instruction: nop software_interrupt: nop prefetch_abort: nop data_abort: nop not_used: nop irq: sub lr, lr, #4 stmfd sp!, {r0-r12, lr} /* 保护现场 */ bl handle_int ldmfd sp!, {r0-r12, pc}^ /* 恢复现场,^表示把spsr恢复到cpsr */ fiq: nop reset: bl set_svc bl disable_watchdog bl disable_interrupt bl disable_mmu bl init_clock bl init_sdram bl copy_to_ram bl init_stack bl clean_bss ldr pc, =gboot_main @ bl light_led set_svc: mrs r0, cpsr bic r0, r0,#0x1f orr r0, r0,#0xd3 msr cpsr, r0 mov pc, lr #define pWTCON 0x53000000 disable_watchdog: ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] mov pc, lr disable_interrupt: mvn r1, #0x0 ldr r0, =0x4a000008 str r1, [r0] mov pc, lr disable_mmu: mcr p15,0,r0,c7,c7,0 mrc p15,0,r0,c1,c0,0 bic r0, r0, #0x00000007 mcr p15,0,r0,c1,c0,0 mov pc, lr #define CLKDIVN 0x4c000014 #define MPLLCON 0x4c000008 #define MPLL_405MHZ ((127<<12)|(2<<4)|(1<<0)) init_clock: ldr r0, =CLKDIVN mov r1, #0x5 str r1, [r0] mcr p15,0,r0,c1,c0,0 orr r0,r0,#0xc0000000 mcr p15,0,r0,c1,c0,0 ldr r0, =MPLLCON ldr r1, =MPLL_405MHZ str r1, [r0] mov pc, lr #define mem_contrl 0x48000000 init_sdram: ldr r0, =mem_contrl add r3, r0, #4*13 adrl r1, mem_data 0: ldr r2, [r1], #4 str r2, [r0], #4 cmp r0, r3 bne 0b mov pc, lr copy_to_ram: ldr r0, =0x0 ldr r1, =0x30008000 add r3, r0, #1024*4 copy_loop: ldr r2, [r0], #4 str r2, [r1], #4 cmp r0, r3 bne copy_loop mov pc, lr init_stack: msr cpsr_c, #0xd2 ldr sp, =0x33000000 @此处实际设置的是r13_irq msr cpsr_c, #0xd3 ldr sp, =0x34000000 @此处实际设置的是r13_svc mov pc, lr clean_bss: ldr r0, =bss_start ldr r1, =bss_end cmp r0, r1 moveq pc, lr clean_loop: mov r2, #0 str r2, [r0], #4 cmp r0, r1 bne clean_loop mov pc, lr mem_data: .long 0x22000000 .long 0x00000700 .long 0x00000700 .long 0x00000700 .long 0x00000700 .long 0x00000700 .long 0x00000700 .long 0x00018001 .long 0x00018001 .long 0x008c04f5 .long 0x000000b1 .long 0x00000030 .long 0x00000030 #define GPBCON 0x56000010 #define GPBDAT 0x56000014 light_led: ldr r0, =GPBCON ldr r1,=0x15400 str r1, [r0] ldr r0, =GPBDAT ldr r1,=0x6BF str r1, [r0] mov pc, lr
interrupt.c
/*interrupt registes*/ #define SRCPND (volatile unsigned long *)0x4A000000 #define INTMOD (volatile unsigned long *)0x4A000004 #define INTMSK (volatile unsigned long *)0x4A000008 #define PRIORITY (volatile unsigned long *)0x4A00000c #define INTPND (volatile unsigned long *)0x4A000010 #define INTOFFSET (volatile unsigned long *)0x4A000014 #define SUBSRCPND (volatile unsigned long *)0x4A000018 #define INTSUBMSK (volatile unsigned long *)0x4A00001c #define EINTMASK (volatile unsigned long *)0x560000a4 #define EINTPEND (volatile unsigned long *)0x560000a8 void init_irq() { // 对于EINT4,需要在EINTMASK寄存器中使能它 *(EINTMASK) &= ~(1<<4); // EINT0、EINT1、EINT2、EINT4_7使能 *(INTMSK) &= (~(1<<0)) & (~(1<<1)) & (~(1<<2)) & (~(1<<4)); __asm__( /*开中断*/ "mrs r0,cpsr\n" "bic r0, r0, #0x80\n" "msr cpsr_c, r0\n" : : ); } void handle_int() { /*读取产生中断的源*/ unsigned long value = *(INTOFFSET); //*(INTOFFSET)就可以直接过去中断源 switch(value) { case 0: //EINT0~K4 led_on(); break; case 1: //EINT1~K1 led_off(); break; case 2: //EINT2~K3 led_on(); break; case 4: //EINT4~K2 led_off(); break; default: break; } /* 中断清除 */ if(value == 4) *(EINTPEND) = (1 << 4); *(SRCPND) = 1 << value; *(INTPND) = 1 << value; }