中断源产生信号->中断控制器->cpu处理中断
2440:非向量方式,中断总服务程序入口---保护环境---判断中断源---调用对应该中断源的终端服务程序---恢复环境
6410/210:向量方式,当中断产生,CPU直接跳转到用户设置好的中断处理程序处---保护环境---设备的中断处理---恢复环境
interrupt.c
#define INTMSK (volatile unsigned long*)0x4a000008 #define INTOFFSET (volatile unsigned long*)0x4a000014 #define SRCPND (volatile unsigned long*)0x4a000000 #define INTPND (volatile unsigned long*)0x4a000010 #define EINTMSK (volatile unsigned long*)0x560000a4 #define EINTPND (volatile unsigned long*)0x560000a8 void init_irq() { //设置这个寄存器一定要在INMSK寄存器之前设置 *(EINTMSK) &= (~(1<<8)) & (~(1<<11)) & (~(1<<13)) & (~(1<<14)) & (~(1<<15)) & (~(1<<19)); *(INTMSK) &= (~(1<<5)); //打开中断 __asm__( "mrs r0, cpsr\n" "bic r0, r0, #0x80\n" "msr cpsr_c, r0\n" : : ); } void handle_int() { //判断产生中断的中断源 unsigned long value = *(EINTPND) & ((1<<8)|(1<<11)|(1<<13)|(1<<14)|(1<<15)|(1<<19)); //根据中断源,执行不同的中断处理 switch(value) { case (1<<8): //K1 led_on(); break; case (1<<11): //K2 led_on(); break; case (1<<13): //K3 led_on(); break; case (1<<14): //K4 led_off(); break; case (1<<15): //K5 led_off(); break; case (1<<19): //K6 led_off(); break; default: break; } //中断清除 *(EINTPND) = value; *(SRCPND) = (1<<5); *(INTPND) = (1<<5); }
mmu.c
#define MMU_FULL_ACCESS (3<<10) #define MMU_DOMAIN (0<<5) #define MMU_SPECIAL (1<<4) #define MMU_CACHEENABLE (1<<3) #define MMU_BUFFERABLE (1<<2) #define MMU_SECTION (2<<0) #define SECDESC (MMU_SECTION|MMU_SPECIAL|MMU_SPECIAL|MMU_FULL_ACCESS) #define SECDESC_WB (MMU_SECTION|MMU_SPECIAL|MMU_SPECIAL|MMU_FULL_ACCESS|MMU_CACHEENABLE|MMU_BUFFERABLE) void creat_page_table() { unsigned long *ttb = (unsigned long *)0x30000000; unsigned long vaddr,paddr; vaddr = 0xA0000000; paddr = 0x56000000; *(ttb + (vaddr >> 20)) = ((paddr & 0xfff00000)|SECDESC); vaddr = 0x30000000; paddr = 0x30000000; while(vaddr += 0x34000000) { *(ttb + (vaddr >> 20)) = ((paddr & 0xfff00000)|SECDESC); vaddr += 0x10000; paddr += 0x10000; } } void mmu_enable() { __asm__( //设置TTB "ldr r0, =0x3000000\n" "mcr p15,0,r0,c2,c0,0\n" //不进行权限检查 "mvn r0,#0\n" "mcr p15,0,r0,c3,c0,0\n" //使能mmu "mrc p15,0,r0,c1,c0,0\n" "orr r0,r0,#0x0001\n" "mcr p15,0,r0,c0,c1,0\n" : : ); } void mmu_init() { creat_page_table(); mmu_enable(); }
button.c
#define GPGCON (volatile unsigned long*)0x56000060 #define GPG0_MSK (3<<(0*2)) #define GPG3_MSK (3<<(3*2)) #define GPG5_MSK (3<<(5*2)) #define GPG6_MSK (3<<(6*2)) #define GPG7_MSK (3<<(7*2)) #define GPG11_MSK (3<<(11*2)) #define GPG0_INT (0x2<<(0*2)) #define GPG3_INT (0x2<<(3*2)) #define GPG5_INT (0x2<<(5*2)) #define GPG6_INT (0x2<<(6*2)) #define GPG7_INT (0x2<<(7*2)) #define GPG11_INT (0x2<<(11*2)) void button_init() { *(GPGCON) &= ~(GPG0_MSK | GPG3_MSK | GPG5_MSK | GPG6_MSK | GPG7_MSK |GPG11_MSK); *(GPGCON) |= (GPG0_INT | GPG3_INT | GPG5_INT | GPG6_INT | GPG7_INT | GPG11_INT); }
start.S
.text .global _start _start: b reset ldr pc, _undefined_instruction ldr pc, _software_interrupt ldr pc, _prefetch_abort ldr pc, _data_abort ldr pc, _not_used ldr pc, _irq ldr pc, _fiq _undefined_instruction: .word undefined_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 undefined_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} fiq: nop reset: bl set_svc bl disable_watchdog bl disable_interrupt bl disable_mmu bl clock_init bl sdram_init bl copy_to_ram bl stack_init bl clean_bss @ bl light_led ldr pc, =gboot_main 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 0x4c000004 #define MPLL_405MHZ ((127<<12)|(2<<4)|(1<<0)) clock_init: ldr r0, =CLKDIVN mov r1, #0x5 str r1, [r0] mrc 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 sdram_init: 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 stack_init: 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 mov r1, #0x400 str r1,[r0] ldr r0, =GPBDAT mov r1, #0x0 str r1, [r0] mov pc, lr