jz2440平台中断测试及分析

来源:互联网 发布:u盘制作linux启动盘 编辑:程序博客网 时间:2024/05/10 06:02

head.S文件及源码分析:

.extern main
.text
.global _start
_start:
 b Reset
HandleUndef: @0x04未定义指令中止模式的向量地址
 b HandleUndef
HandleSWI: @ 0x08: 管理模式的向量地址,通过SWI指令进入此模式
    b   HandleSWI
HandlePrefetchAbort:@ 0x0c: 指令预取终止导致的异常的向量地址
    b   HandlePrefetchAbort
HandleDataAbort:@ 0x10: 数据访问终止导致的异常的向量地址
    b   HandleDataAbort 
HandleNotUsed: @ 0x14: 保留
    b   HandleNotUsed
 b HandleIRQ @ 0x18: 中断模式的向量地址
HandleFIQ: @ 0x1c: 快中断模式的向量地址
    b   HandleFIQ
Reset:
 ldr sp,=4096
 bl disable_watch_dog
 msr cpsr_c,#0xd2
 ldr sp,=3072
 msr cpsr_c,#0xd3
 ldr sp,=4096
 bl init_led
 bl init_irq
 msr cpsr_c,#0x53
 ldr lr,=halt_loop
 ldr pc,=main
halt_loop:
 b halt_loop

HandleIRQ:
 sub lr,lr,#4 @计算返回去的地址
 stmdb sp!, {r0-r12,lr}  @arm中stm指令 用于将寄存器列表所指示的多个寄存器中的值存入由基址寄存器指示的一片@连续存储器中。db表示每次传送前地址减 。这条指令就将r0-r12和lr寄存器中的数值压入栈(中断模式下的sp)中

@”!“表示数据压入栈后,基址寄存器的值更新。
 ldr lr,=int_return @给lr寄存器赋值int_return段的地址,是的下面调用中断服务函数的适合 返回地址是int_return函数
 ldr pc,=EINT_Handle
int_return:
 ldmia sp!,{r0-r12,pc}^ @arm中ldm指令用于从基址寄存器所指示的一片连续存储器中读取数据到寄存器列表所指示@的多个寄存器中  此条指令是将先前压入栈的寄存器的数据传入寄存器中,pc寄存器的值就是中断模式的向量地

@址。供下次中断使用。“^”表示还将SPSR复制到CPSR,同时还表示传入和传出的是用户模式下的寄存器而不是当@前模式下的寄存器。
 


init.c文件及分析:

#include"s3c2440.h"

void disable_watch_dog()
{
 WTCON=0;
}

void init_led()
{
 GPFCON &=~(GPF4_msk|GPF5_msk|GPF6_msk);
 GPFCON |=GPF4_out|GPF5_out|GPF6_out;
}

void init_irq()
{
 GPFCON &=~(GPF0_msk|GPF2_msk);
 GPFCON |=GPF0_int|GPF2_int;
 
 GPGCON &=~(GPG3_msk);
 GPGCON |=GPG3_int;
 
 EINTMASK &=~(1<<11);//外部中断屏蔽寄存器 写1清零 只有EINT11
 
 SRCPND |=(1<<0)|(1<<2)|(1<<5);//中断源挂起寄存器写1清零
 
 INTMOD &=~((0<<0)|(0<<2)|(0<<5));//中断模式寄存器 中断模式
 
    PRIORITY = (PRIORITY & ((~0x01) | (0x3<<7))) | (0x0 << 7) ;//将ARB_MODE0设置为0,及不反转

 INTPND=0xFFFFFFFF;//中断挂起寄存器写1清零
 
    INTMSK   &= (~(1<<0)) & (~(1<<2)) & (~(1<<5));//写零清零

}

int.c文件及分析:

#include"s3c2440.h"
void EINT_Handle()
{
 unsigned long oft=INTOFFSET;//中断偏移寄存器 值表示对应的中断号
    switch( oft )
    {
        // S2被按下
        case 0:
        {  
            GPFDAT |= (0x7<<4);   // 所有LED熄灭
            GPFDAT &= ~(1<<4);      // LED1点亮
            break;
        }
       
        // S3被按下
        case 2:
        {  
            GPFDAT |= (0x7<<4);   // 所有LED熄灭
            GPFDAT &= ~(1<<5);      // LED2点亮
            break;
        }

        // K4被按下
        case 5:
        {  
            GPFDAT |= (0x7<<4);   // 所有LED熄灭
            GPFDAT &= ~(1<<6);      // LED4点亮               
            break;
        }

        default:
            break;
    }
 if(oft==5)
 {
  EINTPEND=(1<<11);  //写1清除外部中断挂起寄存器,在该例只有EINT11是的
 }
 SRCPND=1<<oft;//写1 清除中断源挂起寄存器
 INTPND=1<<oft;//写1清除中断挂起寄存器
}
main文件及分析:

int main()
{
 while(1);
 return 0;
}//是一个死循环

Makefile文件及分析:

int.bin: head.S init.c int.c main.c
 arm-linux-gcc -c -o head.o head.S //-c表示编译不连接  -o表示生成head.o文件
 arm-linux-gcc -c -o init.o init.c
 arm-linux-gcc -c -o int.o int.c
 arm-linux-gcc -c -o main.o main.c
 arm-linux-ld -Ttext 0x00000000 head.o init.o int.o main.o -o int_elf//指定代码段起始地址为0地址
 arm-linux-objcopy -O binary -S int_elf int.bin //-O binary使用二级制格式输出文件 -S不从源文件复制重定位信息和符号到目标文件
 arm-linux-objdump -D -m arm int_elf > int.dis //-D 进行反汇编-m arm 指定反汇编所指定的架构为arm 就会生成arm下的汇编
clean:
 rm -f int.bin int_elf int.dis *.o  


0 0
原创粉丝点击