通过按键玩中断

中断源产生信号->中断控制器->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    
    

 

posted @ 2018-01-31 22:22  sanshijvshi  阅读(219)  评论(0编辑  收藏  举报