中断裸机程序

硬件平台:JZ2440

 

head.s        -->  启动文件,设置异常向量表

init.c           -->  初始化中断

interrupt.c  --> 中断处理程序

s3c2440.h  --> 寄存器映射

 

head.s 源码:

.extern main
.text
.global _start
_start:

@ 异常向量表

@ 0x00  复位
b Reset

@ 0x04  指令未定义
Undefine_instruct:
b Undefine_instruct

@ 0x08  软件中断
Software_interrupt:
b Software_interrupt

@ 0x0c  预取指中断
Prefetch_abort:
b Prefetch_abort

@ 0x10  数据访问中断
Data_abort:
b Data_abort

@ 0x14 保留

@ 0x18 外部访问中断
b Handle_irq

@ 0x1c  快速中断
Fiq:
b Fiq

Reset:
    ldr sp,=4096        @ 复位自动进入超级用户模式
    bl disable_watch_dog

    msr cpsr_c,#0xd2    @ 进入中断模式
    ldr sp,=3072

    msr cpsr_c,#0xd3    @ 进入超级用户模式
    ldr sp,=4096
    bl led_init         
    bl interrupt_init

    msr cpsr_c,#0x5f   @ 开中断,并进入系统模式
    ldr lr,=loop_main
    ldr pc,=main
loop_main:
         b loop_main

Handle_irq:
    sub lr,lr,#4
    stmdb sp!,{r0-r12,lr}

    ldr lr,=eint_return
    ldr pc,=eint_interrupt
eint_return:
    ldmia sp!,{r0-r12,pc}^

 

init.c源码:

#include"s3c2440.h"
/*
 * LED1,LED2,LED4对应GPF4、GPF5、GPF6
 */
#define    GPF4_out    (1<<(4*2))
#define    GPF5_out    (1<<(5*2))
#define    GPF6_out    (1<<(6*2))

#define    GPF4_msk    (3<<(4*2))
#define    GPF5_msk    (3<<(5*2))
#define    GPF6_msk    (3<<(6*2))

/*
 * S2,S3,S4对应GPF0、GPF2、GPG3
 */
#define GPF0_eint     (0x2<<(0*2))
#define GPF2_eint     (0x2<<(2*2))
#define GPG3_eint     (0x2<<(3*2))

#define GPF0_msk    (3<<(0*2))
#define GPF2_msk    (3<<(2*2))
#define GPG3_msk    (3<<(3*2)) 


void disable_watch_dog(void)
{
    WTCON = 0;
}

void led_init(void)
{
     // LED1,LED2,LED4对应的3根引脚设为输出
    GPFCON &= ~(GPF4_msk | GPF5_msk | GPF6_msk);
    GPFCON |= GPF4_out | GPF5_out | GPF6_out;
}

void interrupt_init(void)
{
       // S2,S3对应的2根引脚设为中断引脚 EINT0,ENT2
    GPFCON &= ~(GPF0_msk | GPF2_msk);
    GPFCON |= GPF0_eint | GPF2_eint;

    // S4对应的引脚设为中断引脚EINT11
    GPGCON &= ~GPG3_msk;
    GPGCON |= GPG3_eint;

    EINTMASK &= (~(1<<11));
    INTMSK &= (~(1<<0))&(~(1<<2))&(~(1<<5));
    PRIORITY = (PRIORITY&((~0x01) | (0x3 << 7))) | (0x0 << 7);
}

 

interrupt.c 源码:

#include"s3c2440.h"

void eint_interrupt(void)
{
    unsigned long offset = INTOFFSET;

    switch (offset)
    {
        case 0:
        {
             GPFDAT |= (0x7<<4);
            GPFDAT &= ~(1<<4);
            break;
        }

        case 2:
        {
             GPFDAT |= (0x7<<4);
            GPFDAT &= ~(1<<5);
            break;
        }

        case 5:
        {
             GPFDAT |= (0x7<<4);
            GPFDAT &= ~(1 << 6);
            break;
        }
        defult:break;
    }

    if (offset == 5) EINTPEND = (1 << 11);
    SRCPND = 1 << offset;
    INTPND = 1 << offset;
}

 

main.c 源码:

int main(void)
{
    while (1);
    return 0;
}

 

s3c2440.h 源码:

#ifndef _S3C2440_H_
#define _S3C2440_H_


//看门狗
#define WTCON    (*(unsigned long *)0x53000000)

//GPIO
#define GPFCON   (*(unsigned long *)0x56000050)
#define GPFDAT   (*(unsigned long *)0x56000054)
#define GPFUP    (*(unsigned long *)0x56000058)
#define GPGCON   (*(unsigned long *)0x56000060)
#define GPGDAT   (*(unsigned long *)0x56000064)
#define GPGUP    (*(unsigned long *)0x56000068)

//interrupt
#define INTMSK   (*(unsigned long *)0x4a000008)
#define PRIORITY (*(unsigned long *)0x4a00000c)
#define SRCPND   (*(unsigned long *)0x4a000000)
#define INTPND   (*(unsigned long *)0x4a000010)
#define INTOFFSET (*(unsigned long *)0x4a000014)

#define EINTMASK (*(unsigned long *)0x560000a4)
#define EINTPEND (*(unsigned long *)0x560000a8)



#endif

 

编译的Makefile:

objs:=head.o init.o main.o interrupt.o

interrupt.bin:$(objs)
    arm-linux-ld -Ttext 0x00000000 -o interrupt_elf  $^
    arm-linux-objcopy -O binary -S interrupt_elf $@
    arm-linux-objdump -D -m arm interrupt_elf > interrupt.dis

%.o:%.c
    arm-linux-gcc -o $@ -c $<

%.o:%.s
    arm-linux-gcc -o $@ -c $<

clean:
    rm -f *.o *.dis *.bin interrupt_elf

 

posted @ 2019-02-20 17:06  张不源  Views(210)  Comments(0Edit  收藏  举报