新闻中心

EEPW首页>嵌入式系统>设计应用> 根据韦东山修改的mini2440中断的裸机代码

根据韦东山修改的mini2440中断的裸机代码

作者: 时间:2016-11-21 来源:网络 收藏
这是根据韦东山的关于中断的代码改成在mini2440板子上可以运行的代码。
以下是5个文件的所有内容:
@是注释符!!

head.S文件内容:


@**************************************************************************
@File:head.S
@功能:初始化,设置中断模式、系统模式的栈,设置好中断处理函数
@**************************************************************************

.externmain
.text
.global_start
_start:
@**************************************************************************
@中断向量,本程序中,除Reset和HandleIRQ外,其他异常都没有使用
@**************************************************************************
@0x00地址处的指令为"b Reset",在系统复位后,这条指令将跳去执行标号"Reset"开始的代码
bReset

@0x04:未定义指令终止模式的向量地址
HandleUndef:
bHandleUndef

@0x08:管理模式的向量地址,通过SWI指令进入此模式
HandleSWI:
bHandleSWI

@0x0c:指令预取终止导致的异常的向量地址
HandlePrefetchAbort:
bHandlePrefetchAbort

@0x10:数据访问终止导致的异常的向量地址
HandleDataAbort:
bHandleDataAbort

@0x14:保留
HandleNotUsed:
bHandleNotUsed

@0x18:中断模式的向量地址
bHandleIRQ

@0x1c:快中断模式的向量地址
HandleFIQ:
bHandleFIQ

Reset:
ldrsp,=4096
@设置栈指针,以下都是C函数,调用前需要设好栈。栈是用@来保存C函数的变量和返回地址
bldisable_watch_dog@关闭WATCHDOG,否则CPU会不断重启

msrcpsr_c,#0xd2@进入中断模式
ldrsp,=3072@设置中断模式的栈指针,这里的sp寄存器是sp_irq

msrcpsr_c,#0xdf@进入系统模式
ldrsp,=4096@设置系统模式的栈指针,这里的sp寄存器是sp_sys
@其实复位之后,CPU就处于系统模式
@前面的"ldrsp,=4096"完成同样的功能,此句可省略

blinit_led@初始化LED的GPIO管脚,在init.c中
blinit_irq@调用中断初始化函数,在init.c中
msrcpsr_c,#0x5f@设置I-bit=0,开IRQ中断

ldrlr,=halt_loop@设置返回地址
ldrpc,=main@调用main函数,main函数是个不做任何事的无限循环。当按下按键时,这个循环被打断,CPU进入
@中断模式,执行“b HandleIRQ”的指令
halt_loop:
bhalt_loop

HandleIRQ:@HandleIRQ开始的代码用于处理中断
sublr,lr,#4@计算中断处理完毕后的返回地址
stmdbsp!,{r0-r12,lr}@保存使用到的寄存器
@注意,此时的sp是中断模式的sp
@初始值是上面设置的3072

ldrlr,=int_return@设置调用ISR即EINT_Handle函数后的返回地址
ldrpc,=EINT_Handle@调用中断服务函数,在interrupt.c中

int_return:
ldmiasp!,{r0-r12,pc}^@中断返回,^表示将spsr的值复制到cpsr


init.c文件内容:








#defineEINTMASK(*(volatile unsigned long*)0x560000a4)//外部中断屏蔽寄存器
#defineINTMSK(*(volatile unsigned long*)0x4a000008)


#defineGPBCON(*(volatile unsigned long*)0x56000010)
#defineGPBDAT (*(volatile unsigned long*)0x56000014)

#define GPB5_out(1<<(5*2))
#defineGPB6_out(1<<(6*2))
#defineGPB7_out(1<<(7*2))
#defineGPB8_out(1<<(8*2))


#defineGPGCON(*(volatile unsigned long*)0x56000060)
#defineGPGDAT (*(volatile unsigned long*)0x56000064)

#defineGPG0_eint(2<<(0*2))//K1,EINT8
#defineGPG3_eint(2<<(3*2))//K2,EINT11
#defineGPG5_eint(2<<(5*2))//K3,EINT13
#defineGPG6_eint(2<<(6*2))//K4,EINT14



#defineWTCON(*(volatile unsigned long*)0x53000000)

void disable_watch_dog(void)
{
WTCON=0;
}

void init_led(void)
{
GPBCON=GPB5_out|GPB6_out|GPB7_out|GPB8_out;
GPBDAT|=(0x0f<<5);//所有LED熄灭,如果没有这一句,LED灯默认是全亮的
}



void init_irq()
{
GPGCON=GPG0_eint|GPG3_eint|GPG5_eint|GPG6_eint;

//对于EINT8,EINT11,EINT13,EINT14,需要在EINTMASK寄存器使能它们
EINTMASK&=(~(1<<8))&(~(1<<11))&(~(1<<13))&(~(1<<14));
//这4个外部中断的优先级是相同的,EINT8_23都接仲裁器的REQ1引脚
//所以不用像韦东山程序里那样再设置优先级了

//EINT8,EINT11,EINT13,EINT14使能
INTMSK&=(~(1<<5));
}



interrupt.c文件内容:


#defineGPBDAT(*(volatile unsigned long*)0x56000014)
#define INTOFFSET(*(volatile unsigned long*)0x4A000014)
#defineEINTPEND(*(volatile unsigned long*)0x560000a8)
#defineSRCPND(*(volatile unsigned long*)0x4a000000)
#defineINTPND(*(volatile unsigned long*)0x4a000010)

void EINT_Handle()
{
unsigned long oft=INTOFFSET;
unsigned long val;


GPBDAT|=(0x0f<<5);//所有LED熄灭,如果没有这一句,那么会出现一个结果,就是将程序下到板子里运行时,
//4个LED灯都是灭的,因为在init.c函数里设置它为全灭。然后你按下K1,LED1亮了,
//再按下K2,LED2亮了,但是LED1却没熄灭,知道你按到K4,4个LED全亮,再按就没变化了
//加上这一句就不一样了,每按一个键,只亮相应的灯,这也说明中断的执行情况
val=EINTPEND;//EINT寄存器,它的位x为1时,表示EINT已经发生(x为4——23)。
if(val&(1<<8))//K1被按下,LED1被点亮
GPBDAT&=~(1<<5);

if(val&(1<<11))//K2被按下,LED2被点亮
GPBDAT&=~(1<<6);

if(val&(1<<13))//K3被按下,LED3被点亮
GPBDAT&=~(1<<7);

if(val&(1<<14))//K4被按下,LED4被点亮
GPBDAT&=~(1<<8);
//清除中断
if(oft==5)
EINTPEND=(1<<8)|(1<<11)|(1<<13)|(1<<14);//清除EINTPEND寄存器,往某位写入1即可清楚此位
SRCPND=1< //清除SRCPND寄存器,往某位写入1即可清楚此位
INTPND=1< //清除INTPND寄存器,往某位写入1即可清楚此位
//注意:清除顺序很重要:先是EINTPEND,然后是SRCPND,最后是INTPND
}



main.c文件内容:



int main()
{
while(1);
return0;
}

Makfile文件内容:

objs:=head.oinit.ointerrupt.omain.o

int.bin:$(objs)
arm-linux-ld-Ttext0x00000000-oint_elf$^
arm-linux-objcopy-Obinary-Sint_elf$@
arm-linux-objdump-D-marmint_elf> int.dis

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

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

clean:
rm-f int.bin int_elfint.dis*.o


评论


技术专区

关闭