簡單外中斷實驗(最近又要搞arm相關的東西,複習一下中斷)
阿新 • • 發佈:2018-12-31
程式燒寫在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; }