微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 根据韦东山修改的mini2440中断的裸机代码

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

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

head.S文件内容:


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

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

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

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

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

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

@0x14:保留
HandleNotUsed:
b HandleNotUsed

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

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

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

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

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

bl init_led @初始化LED的GPIO管脚,在init.c中
bl init_irq @调用中断初始化函数,在init.c中
msr cpsr_c,#0x5f @设置I-bit=0,开IRQ中断

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

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

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

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


init.c文件内容:








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


#define GPBCON (*(volatile unsigned long*)0x56000010)
#define GPBDAT (*(volatile unsigned long*)0x56000014)

#define GPB5_out (1<(5*2))
#define GPB6_out (1<(6*2))
#define GPB7_out (1<(7*2))
#define GPB8_out (1<(8*2))


#define GPGCON (*(volatile unsigned long*)0x56000060)
#define GPGDAT (*(volatile unsigned long*)0x56000064)

#define GPG0_eint (2<(0*2)) //K1,EINT8
#define GPG3_eint (2<(3*2)) //K2,EINT11
#define GPG5_eint (2<(5*2)) //K3,EINT13
#define GPG6_eint (2<(6*2)) //K4,EINT14



#define WTCON (*(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文件内容:


#define GPBDAT (*(volatile unsigned long*)0x56000014)
#define INTOFFSET (*(volatile unsigned long*)0x4A000014)
#define EINTPEND (*(volatile unsigned long*)0x560000a8)
#define SRCPND (*(volatile unsigned long*)0x4a000000)
#define INTPND (*(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);
return 0;
}

Makfile文件内容:

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

int.bin:$(objs)
上一篇:关于ADR指令的理解
下一篇:2440中断解析

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top