1. 程式人生 > >簡單外中斷實驗(最近又要搞arm相關的東西,複習一下中斷)

簡單外中斷實驗(最近又要搞arm相關的東西,複習一下中斷)

程式燒寫在norflash上面

Makefile

mem_controler.bin : start.s function.c
	arm-linux-gcc -g -c -o start.o start.s
	arm-linux-gcc -g -c -o function.o function.c
	arm-linux-ld -Ttext 0x30000000 -g start.o function.o -o interrupt.elf
	arm-linux-objcopy -O binary -S interrupt.elf interrupt.bin
	arm-linux-objdump -D -m arm interrupt.elf > interrupt.dis
clean : 
	rm -f *.o *.bin *.dis


start.s

.text
.global _start
_start:
	b		reset
	b		.
	b		.
	b		.
	b		.
	b		.
	b		handle_irq
	b		.

reset:
	@shut down the watchdog
	ldr		r0, =0x53000000
	ldr		r1, =0x00000000
	str		r1, [r0]

	@init the stack address
	ldr		r1, =4096
	ldr		r0, =0x40000000
	add		sp, r1, r0

	bl		init_led
	bl		init_sdram

	@reset the stack pointer
	ldr		sp, =0x34000000 @change stack to the end of sdram
	msr		cpsr_c, #0xd2
	ldr		sp, =0x33F00000 @change the stack pointer of irq mode
	msr		cpsr_c, #0xd3 @change cpu back to svc mode


	bl		copy_code2sdram @copy 8KB data from norflash to sdram
	ldr		pc, =on_sdram
on_sdram:
	bl		init_interrupt
	msr		cpsr_c, #0x53 @clear the irq disable bit in cpsr

	bl		main
halt_loop:
	b		halt_loop


handle_irq:
	sub		lr, lr, #4 @set the address(int main function) to return when handle_irq ends
	stmdb	sp!, {r0-r12, lr} 	@save the universal registers and lr_irq to the stack of irq mode
	bl		handle_irq_func		@branch to the irq handleing function achieved in function.c 
	ldmia	sp!, {r0-r12, pc}^	@resume the universal registers and save lr to pc while copying spsr to cpsr

function.c
//gpb registers
#define		GPBCON		(*((volatile unsigned long *)0x56000010))	
#define		GPBDAT		(*((volatile unsigned long *)0x56000014))

//mem controler registers
#define		BWSCON		(*((volatile unsigned long *)0x48000000))
#define		BANKCON0	(*((volatile unsigned long *)0x48000004))
#define		BANKCON1	(*((volatile unsigned long *)0x48000008))
#define		BANKCON2	(*((volatile unsigned long *)0x4800000C))
#define		BANKCON3	(*((volatile unsigned long *)0x48000010))
#define		BANKCON4	(*((volatile unsigned long *)0x48000014))
#define		BANKCON5	(*((volatile unsigned long *)0x48000018))
#define		BANKCON6	(*((volatile unsigned long *)0x4800001C))
#define		BANKCON7	(*((volatile unsigned long *)0x48000020))
#define		REFRESH		(*((volatile unsigned long *)0x48000024))
#define		BANKSIZE	(*((volatile unsigned long *)0x48000028))
#define		MRSRB6		(*((volatile unsigned long *)0x4800002C))
#define		MRSRB7		(*((volatile unsigned long *)0x48000030))

//gpg registers
#define		GPGCON		(*((volatile unsigned long *)0x56000060))

//interrupt related registers
#define		EINTMASK	(*((volatile unsigned long *)0x560000A4))
#define		INTMSK		(*((volatile unsigned long *)0x4A000008))
#define		INTMOD		(*((volatile unsigned long *)0x4A000004))
#define		INTOFFSET	(*((volatile unsigned long *)0x4A000014))
#define		SRCPND		(*((volatile unsigned long *)0x4A000000))
#define		INTPND		(*((volatile unsigned long *)0x4A000010))
#define		EINTPEND	(*((volatile unsigned long *)0x560000A8))
#define		EXTINT1		(*((volatile unsigned long*)(0x5600008c)))
#define		EXTINT2		(*((volatile unsigned long*)(0x56000090)))




void init_sdram(){
	BWSCON		= 0x22011110;
	BANKCON0	= 0x00000700;
	BANKCON1	= 0x00000700;
	BANKCON2	= 0x00000700;
	BANKCON3	= 0x00000700;
	BANKCON4	= 0x00000700;
	BANKCON5	= 0x00000700;
	BANKCON6	= 0x00018005;
	BANKCON7	= 0x00018005;
	REFRESH		= 0x008C07A3;
	BANKSIZE	= 0x000000B1;
	MRSRB6		= 0x00000030;
	MRSRB7		= 0x00000030;
}


void init_interrupt(){
	//set the gpio pins of the six keys to interrupt mode 
	GPGCON = (1<<(0*2+1) | 1<<(3*2+1) | 1<<(5*2+1) | 1<<(6*2+1) | 1<<(7*2+1) | 1<<(11*2+1));

	//set EINTMASK register to enable external interrupt
	EINTMASK &= (~(1<<8 | 1<<11 | 1<<13 | 1<<14 | 1<<15 | 1<<19));

	//set INTMSK register to inable eint8_23
	INTMSK &= (~(1<<5));

	//set INTMOD register to set int8_23 to irq mode
	INTMOD &= (~(1<<5));
}


void blink(void);
void handle_key(){
	int eint_v;

	eint_v = EINTPEND;

	if(eint_v & (1<<8)){
		display_led(1);
		EINTPEND = 1<<8;
		return;		
	}

	if(eint_v & (1<<11)){
		display_led(2);
		EINTPEND = 1<<11;
		return;		
	}

	if(eint_v & (1<<13)){
		display_led(3);
		EINTPEND = 1<<13;
		return;		
	}

	if(eint_v & (1<<14)){
		display_led(4);
		EINTPEND = 1<<14;
		return;		
	}

	if(eint_v & (1<<15)){
		display_led(5);
		EINTPEND = 1<<15;
		return;		
	}

	if(eint_v & (1<<19)){
		display_led(6);
		EINTPEND = 1<<19;
		return;		
	}
}


void handle_irq_func(){
	int offset_v;
	offset_v = INTOFFSET;

	switch(offset_v){
	case 5:
		handle_key();
		break;
	default:
		break;
	}

	//clear the interrupt
	SRCPND = 1<<offset_v;
	INTPND = 1<<offset_v;
}

void delay(int n){
	int i, j;
	for(i=0; i<n; i++){
		for(j=0; j<1000; j++){}
	}
}

void blink(){
	GPBDAT = 0xffffffff;
	GPBDAT = 0x00000000;
	delay(10);
	GPBDAT = 0xffffffff;
	delay(10);
}

void display_led1(){
	GPBDAT = ~(1<<5);
	delay(1);
}

void display_led2(){
	GPBDAT = ~(3<<5);
	delay(1);
}

void display_led3(){
	GPBDAT = ~(7<<5);
	delay(1);
}

void display_led4(){
	GPBDAT = ~(15<<5);
	delay(1);
}

void display_led(int n){
	GPBDAT = ~(n<<5);
}


void copy_code2sdram(){
	int size, i;
	unsigned char *src, *des;
	size = 8*1024;

	des = (unsigned char*)(0x30000000);
	src = (unsigned char *)(0x00000000);
	for(i=0; i<size; i++){
		*(des++) = *(src++);
	}
}

void init_led(){
	GPBCON = 0x00015400;
	GPBDAT &= ~(0x0f<<5);
}

/*
int main(void){
	int i;

	GPBCON = 0x00015400;
	i = 0;
	while(1){
		GPBDAT = ~(1<<(i+5));
		delay(1);
		i = (i+1)%4;
	}
	return 0;
}
*/

int main(void){
	while(1){
		//wait for external interrupt
	}
	return 0;
}