mini2440 按键中断点亮led灯裸机代码

原创文章,转载请注明: 转载自勤奋的小青蛙
本文链接地址: mini2440 按键中断点亮led灯裸机代码

先把代码贴上,后续再去进行详细介绍,总共需要这么几个文件:

head.S, init.c, interrupt.c, main.c, Makefile

详情可以从这个地方下载:

mini2440 按键中断点亮led灯裸机代码http://www.jyguagua.com/bbs/forum.php?mod=viewthread&tid=184&fromuid=1

head.S内容:

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

.extern main
.text
.global _start
_start:
@*******************************
@这段代码只核心写中断向量
@*******************************

	b Reset

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

@定义软中断的向量地址
HandleSWI:
	b	HandleSWI

@定义欲取址中断异常向量地址
HandlePrefectchAbort:
	b	HandlePrefectchAbort

@定义数据中止异常
HandleDataAbort:
	b	HandleDataAbort

@定义保留向量地址
HandleNotUsed:
	b	HandleNotUsed

@定义中断的向量地址
	b	HandleIRQ

@定义快中断的向量地址
HandleFIQ:
	b	HandleFIQ

@reset的处理函数
Reset:
	ldr	sp, =4096 @先设置栈指针,以下都是C语言需要设置栈指针
	bl	disable_watch_dog @跳到init.c文件去执行

	msr	cpsr_c, #0xd2 @进入中断模式
	ldr	sp, =3072 @中断模式的栈指针定义

	msr	cpsr_c, #0xdf @进入系统模式
	ldr	sp, =4096 @设置系统模式的栈指针

	bl	init_led @初始化led,使其均输出状态而且熄灭,在init.c
	bl 	init_irq @调用init.c中的init_irq函数,初始化中断各个寄存器配置
	msr	cpsr_c, #0x5f @开启IRQ中断

	ldr	lr, =halt_loop @设置返回地址
	ldr	pc, =main @跳到main函数执行

halt_loop:
	b	halt_loop

HandleIRQ:
	sub	lr, lr, #4 @计算中断的返回地址
	stmdb	sp!, {r0-r12, lr} @保存使用到的寄存器

	ldr	lr, =int_return
	ldr	pc, =EINT_Handle @调用中断处理函数

int_return:
	ldmia	sp!, {r0-r12, pc}^

init.c 内容:

/*初始化GPIO引脚为外部中断
 * GPIO引脚用作外部中断,默认为低电平触发,IRQ方式
 * */
#define	WTCON (*(unsigned long *)0x53000000)
#define GPGCON (*(unsigned long *)0x56000060)
#define EINTMASK (*(unsigned long *)0x560000a4)
#define INTMSK (*(unsigned long *)0X4A000008)

/*led寄存器*/
#define GPBCON (*(unsigned long *)0x56000010)
#define GPBDAT (*(unsigned long *)0x56000014)
#define GPBUP (*(unsigned long *)0x56000018)

void disable_watch_dog(void)
{
	//关闭看门狗
	WTCON = 0;
}

void init_led(void)
{
	//设置led引脚为输出引脚,初始化都熄灭而且上拉电阻disable
	GPBCON = (1 << 10) | (1 << 12) | (1 << 14) | (1 << 16);	
	GPBDAT |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);
	GPBUP |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);	
}

void init_irq()
{
	GPGCON = (10) | (10 << 6) | (10 << 10) | (10 << 12); //设置EINT8, 11, 13, 14
	INTMSK &= (~(1 << 5)); //开启总中断屏蔽
	EINTMASK &= (~(1 << 8)) &  (~(1 << 11)) & (~(1 << 13)) & (~(1 << 14)); //开启对应的外部中断
}

interrupt.c内容:

#define INTOFFSET (*(unsigned long *)0x4A000014)
#define EINTPEND (*(unsigned long *)0x560000a8)
#define GPBCON (*(unsigned long *)0x56000010)
#define GPBDAT (*(unsigned long *)0x56000014)
#define GPBUP (*(unsigned long *)0x56000018)
#define INTPND (*(unsigned long *)0X4A000010)
#define SRCPND (*(unsigned long *)0X4A000000)

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

	switch (oft)
	{
		case 5:
		{
			GPBDAT |= (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8);			
			//判断到底是哪个按键按下的
			val = EINTPEND;

			if (val & (1 << 8)) {
			//点亮第一个灯	
				GPBDAT &= ~(1 << 5);
			} 
			if (val & (1 << 11)) {
			//点亮第二个灯	
				GPBDAT &= ~(1 << 6);
			}
			if (val & (1 << 13)) {
			//点亮第三个灯	
				GPBDAT &= ~(1 << 7);
			}
			if (val & (1 << 14)) {
			//点亮第四个灯	
				GPBDAT &= ~(1 << 8);
			}
			break;
		}
		default:
			break;
	}

	//清除中断
	if (oft == 5) {
		EINTPEND = (1 << 8) | (1 << 11) | (1 << 13) | (1 << 14);	
	}
	SRCPND = 1 << oft;
	INTPND = 1 << oft;

}

main.c内容如下:

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

Makefile的内容如下:

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

int.bin: $(objs)
	arm-linux-ld -Ttext 0x00000000 -o int_elf $^
	arm-linux-objcopy -O binary -S int_elf $@
	arm-linux-objdump -D -m arm int_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_elf int.dis *.o
原创文章,转载请注明: 转载自勤奋的小青蛙
本文链接地址: mini2440 按键中断点亮led灯裸机代码

文章的脚注信息由WordPress的wp-posturl插件自动生成



|2|left
打赏

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: