Chinaunix首页 | 论坛 | 博客
  • 博客访问: 97372
  • 博文数量: 65
  • 博客积分: 2520
  • 博客等级: 少校
  • 技术积分: 680
  • 用 户 组: 普通用户
  • 注册时间: 2010-05-22 15:10
文章分类

全部博文(65)

文章存档

2011年(1)

2010年(64)

我的朋友
最近访客

分类:

2010-06-15 20:29:11

#include
#include
#include
 
#define EINT0  0
#define IRQNUMBER 32
static void (*irq_handlers[IRQNUMBER])(void);
void irq_init(void)
{
 struct interrupt *const irq = get_base_interrupt();
 irq->INTMSK = ~0;
 
 /* 修改cpsr,开启中断 */
 __asm__ __volatile__ (
  "mrs r0, cpsr\n\t"
  "bic r0, r0, #0x80\n\t"
  "msr cpsr, r0\n\t"
  :
  :
  :"r0"
 );
}

void request_irq(int num, void (*handler)(void))
{
 struct interrupt *const irq = get_base_interrupt();
 if(num >= 0 && num < IRQNUMBER && irq_handlers[num] == 0)
 {
  irq_handlers[num] = handler;
  /* 启用中断服务 */
  set0(irq->INTMSK, num);
 }
}
void do_irq(void)
{
 struct interrupt *const irq = get_base_interrupt();
 const int num = irq->INTOFFSET & 0x1f;
 if(irq_handlers[num])
  irq_handlers[num]();
 /* 中断处理完后或无中断处理函数,清中断 */
 irq->SRCPND = irq->INTPND;
 irq->INTPND = irq->INTPND;
}

void key(void)
{
 puts("hello key");
}
int do_key(int argc, char *argv[])
{
 struct gpio *const gpio = get_base_gpio();
 /* 配置GPF0为EINT0中断模式,启用上拉 */
 setval(gpio->GPFCON, 0x2, 2, 0);
 set1(gpio->GPFUP, 0);
 request_irq(EINT0, key);
 return 0;
}
G_BOOT_CMD(key, do_key);
 
//==========================================================
以下汇编的启动代码:
 .text
.global _start
_start:
 ldr pc, _start_code
 ldr pc, _undefined_instruction
 ldr pc, _software_interrupt
 ldr pc, _prefetch_abort
 ldr pc, _data_abort
 b _start
 ldr pc, _irq
 ldr pc, _fiq
_start_code:
 .word start_code
_undefined_instruction:
 .word undefined_instruction
_software_interrupt:
 .word software_interrupt
_prefetch_abort:
 .word prefetch_abort
_data_abort:
 .word data_abort
_irq:
 .word irq
_fiq:
 .word fiq
start_code:
/* 将r4-r14和cpsr的值保存到预留的80byte空间里 */
 ldr r0, =u_boot_reg
 stmia r0!, {r4-r14}
 mrs r1, cpsr
 str r1, [r0]
/* =============== 切换svc模式 ============ */
 mov r0, #0xd3
 msr cpsr, r0
/* ========== 设置栈的起始地址 ============ */
 mov sp, #0x33800000

/* =================== 自拷贝 ============= */
/*
 *  从0x30000000地址处拷贝64byte到0x0的地址处
 *  就是开头line4 - line32的这段代码
 */
 mov r0, #0x30000000
 mov r1, #0
 mov r2, #4*16
1:
 ldr r3, [r0], #4
 str r3, [r1], #4
 cmp r1, r2
 blt 1b
/* ============ 自拷贝完 64byte =========== */
/* ============== 初始 sp 为0 ========== */
 ldr r0, bss_start
 ldr r1, bss_end
 mov r2, #0
2:
        str r2, [r0], #4
 cmp r0, r1
 blt 2b
/* =========== 初始化 sp 完 ============ */
 bl clock_init
 bl console_init
 bl irq_init
 mov lr, pc
 ldr pc, _shell
3:
 b 3b
_shell:
 .word shell
bss_start:
 .word __bss_start
bss_end:
 .word __bss_end
.global exit
exit:
 ldr r2, =u_boot_reg
 ldmia r2!, {r4-r14}
 ldr r3, [r2]  /* 取出最后一个cpsr的值 */
 msr cpsr, r3  /* 恢复cpsr的值 */
 bx lr        /* 恢复pc的值   */ 
/* ========== 保留80byte的空间 ========= */
u_boot_reg:
 .space 4*20
 
 

//================================================
进入中断的处理函数
 
 .text
.global undefined_instruction
undefined_instruction:
        mov     sp, #0x33c00000
 @r0传参:
 @r0的值传给do_interrupt函数的第一个参数
        mov     r0, #1
        b       do_interrupt
.global software_interrupt
software_interrupt:
 stmfd sp!, {lr}
        mov     sp, #0x33c00000
        mov     r0, #2
        @读取出swi的中断号,主要过程如下:
        @需了解swi的功能:并了解执行swi的时候,它所做的一些事情是
 @由硬件完成的.
 @1. 取出执行swi时所保存的pc地址-4,就是swi指令的地址.
 @2. bic一行的指令是屏蔽掉swi本身指令码,取出数据保存在r1寄存器
 @3. r1的数据传给do_interrupt函数,作为其第二个参数.
 ldr r1, [lr, #-4]
 bic r1, #0xff000000
 b do_interrupt
 ldmfd sp!, {lr}
 movs pc, lr @mov带上s,将spsr的值自动恢复给cpsr
 
.global prefetch_abort
prefetch_abort:
        mov     sp, #0x33c00000
        mov     r0, #3
        b       do_interrupt
.global data_abort
data_abort:
        mov     sp, #0x33c00000
        mov     r0, #4
        b       do_interrupt
.global irq
irq:
        mov     sp, #0x33c00000
 stmfd sp!, {r0-r12, lr}
 @因为执行bl时会改变pc的地址,所以需要将
 @通用寄存器进栈保护,才能恢复到原来状态
 bl do_irq
 ldmfd sp!, {r0-r12, lr}
 subs  pc, lr, #4
.global fiq
fiq:
        mov     sp, #0x33c00000
        mov     r0, #6
        b       do_interrupt
 
阅读(1560) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~