中断处理

来源:互联网 发布:java编写中文软件 编辑:程序博客网 时间:2024/04/29 08:26


#define GPNCON     (*((volatile unsigned long *)0x7F008830))
#define GPNDAT     (*((volatile unsigned long *)0x7F008834))

#define EINT0CON0  (*((volatile unsigned long *)0x7F008900))
#define EINT0MASK  (*((volatile unsigned long *)0x7F008920))

#define EINT0PEND  (*((volatile unsigned long *)0x7F008924))

#define PRIORITY    (*((volatile unsigned long *)0x7F008280))
#define SERVICE     (*((volatile unsigned long *)0x7F008284))
#define SERVICEPEND (*((volatile unsigned long *)0x7F008288))


#define VIC0IRQSTATUS  (*((volatile unsigned long *)0x71200000))
#define VIC0FIQSTATUS  (*((volatile unsigned long *)0x71200004))
#define VIC0RAWINTR    (*((volatile unsigned long *)0x71200008))
#define VIC0INTSELECT  (*((volatile unsigned long *)0x7120000c))
#define VIC0INTENABLE  (*((volatile unsigned long *)0x71200010))
#define VIC0INTENCLEAR (*((volatile unsigned long *)0x71200014))
#define VIC0PROTECTION (*((volatile unsigned long *)0x71200020))
#define VIC0SWPRIORITYMASK (*((volatile unsigned long *)0x71200024))
#define VIC0PRIORITYDAISY  (*((volatile unsigned long *)0x71200028))

#define VIC0ADDRESS        (*((volatile unsigned long *)0x71200f00))


void irq_init(void)
{
 /* 配置GPIO引脚为中断引脚 */
 /* GPN0~5 设为中断引脚 */

 GPNCON &= ~(0xfff);
 GPNCON |= 0xaaa;                   

 /* 设置中断触发方式为: 双边沿触发 */
 EINT0CON0 &= ~(0xfff);
 EINT0CON0 |= 0x777;

 /* 使能中断 */
 EINT0MASK &= ~(0x3f);

 /* 在中断控制器里使能这些中断 */
 VIC0INTENABLE |= (0x3);                         
/* bit0: eint0~3, bit1: eint4~11 */


}


//中断处理

void do_irq(void)
{
 int i = 0;
 
 printf("do_irq\n\r");
 printf("SERVICE     = 0x%x\n\r", SERVICE);
 printf("SERVICEPEND = 0x%x\n\r", SERVICEPEND);
 printf("EINT0PEND   = 0x%x\n\r", EINT0PEND);
 
 /* 2.1 分辨是哪个中断 */
 for (i = 0; i < 6; i ++)
 {
  if (EINT0PEND & (1<<i))
  {
   if (GPNDAT & (1<<i))
   {
    printf("K%d released\n\r", i+1);
   }
   else
   {
    printf("K%d pressed\n\r", i+1);
   }
  }
 }


 /* 2.2 调用它的处理函数 */ 

 /* 2.3 清中断 */ 
 EINT0PEND   = 0x3f;  /* 清中断 */
 VIC0ADDRESS = 0;

}


 


.globl _start
_start:

 /* 0 地址 */
 b reset                 /* 复位时,cpu跳到0地址 */
 ldr pc, =undefined_instruction  /* cpu遇到不能识别的指令时 */
 ldr pc, _vector_swi             /* 当执行swi指令时, 进入swi模 式 */
 b halt     @ldr pc, _prefetch_abort /* 预取中止异常 */
 b halt     @ldr pc, _data_abort     /* 数据访问异常 */
 b halt     @ldr pc, _not_used       /* 没用到 */
 ldr pc, _irq            /* 0x18 中断异常 */
 b halt     @ldr pc, _fiq            /* 快中断异常 */

_irq :
 .word vector_irq

_vector_swi:
 .word vector_swi
  
vector_swi:
 /* 1. 保存现场 */
 ldr sp, =0x56000000
 stmdb sp!, {r0-r12, lr}  /* lr就是swi的下一条指令地址 */

 /* 2. 处理异常 */
 mrs r0, cpsr
 ldr r1, =swi_str
 bl print_cpsr

 /* 3. 恢复现场 */
 ldmia sp!, {r0-r12, pc}^ /* ^表示把spsr恢复到cpsr */
 
swi_str:
 .word 0x00697773  /* swi */
 
undefined_instruction:
 /* 1. 保存现场 */
 ldr sp, =0x55000000
 stmdb sp!, {r0-r12, lr}

 /* 2. 处理异常 */
 mrs r0, cpsr
 ldr r1, =und_str
 bl print_cpsr

 /* 3. 恢复现场 */
 ldmia sp!, {r0-r12, pc}^  /* ^表示把spsr恢复到cpsr */

und_str:
 .word 0x00646e75  /* und */

usr_str:
 .word 0x00727375  /* usr */


vector_irq:
 /* 1. 保存现场 */
 ldr sp, =0x54000000
 sub lr, lr, #4
 stmdb sp!, {r0-r12, lr}  /* lr就是swi的下一条指令地址 */

 /* 2. 处理异常 */
 bl do_irq
 
 /* 3. 恢复现场 */
 ldmia sp!, {r0-r12, pc}^  /* ^表示把spsr恢复到cpsr */

reset:
/* 硬件相关的设置 */
    /* Peri port setup */
    ldr r0, =0x70000000
    orr r0, r0, #0x13
    mcr p15,0,r0,c15,c2,4       @ 256M(0x70000000-0x7fffffff)
   
/* 关看门狗 */
/* 往WTCON(0x7E004000)写0 */
 
 ldr r0, =0x7E004000
 mov r1, #0
 str r1, [r0]
 
 /* 设置栈 */
 ldr sp, =8*1024  /* sp_svc */

 /* 设置时钟 */
 bl clock_init
 bl ddr_init
 bl init_uart

/* 把程序的代码段、数据段复制到它的链接地址去 */ 
 adr r0, _start   /* 获得_start指令当前所在的地址 : 0*/
 ldr r1, =_start  /* _start的链接地址 0x51000000 */
 
 ldr r2, =bss_start      /* bss段的起始链接地址 */
 
 sub r2, r2, r1
 
 cmp r0,r1
 beq clean_bss
 
 bl copy2ddr
 cmp r0, #0
 bne halt
  
 /* 清BSS */
/* 把BSS段对应的内存清零 */
clean_bss:
 ldr r0, =bss_start
 ldr r1, =bss_end
 mov r3, #0
 cmp r0, r1
 ldreq pc, =on_ddr
clean_loop:
 str r3, [r0], #4
 cmp r0, r1 
 bne clean_loop  
 ldr pc, =on_ddr

on_ddr: 

 bl irq_init

 mrs r0, cpsr
 bic r0,r0,#0x9f  /* 清cpsr的I位,M4~M0 */
 orr r0,r0,#0x10
 msr cpsr,r0      /* 进入user mode */

 ldr sp, =0x57000000  /* sp_sys/usr */

 ldr r1, =usr_str
 bl print_cpsr
 
 swi 0    /*
           * cpu进入svc模式
           * 把之前的cpsr保存到spsr_svc
           * 切换到r13_svc, r14_svc
           * 把swi的下一条指令存到r14(lr)_svc
           * 跳到地址8
           */
 bl hello
undef:
 .word 0xff000000 /*
             * cpu进入Undefined模式
             * 把之前的cpsr保存到spsr_und
             * 切换到r13_und, r14_und
             * 把下一条指令存到r14(lr)_und
             * 跳到地址4
             */
 
swi_ret:
 bl main
 

halt:
 b halt 


 

 

0 0
原创粉丝点击