在三天前学习按键驱动的时候,按键通过轮循的方式,一直在等待被按下,这时候系统不能够完成其它的操作,这明显是不科学的,可以使用外部中断解决这个问题。
reg.h
中断
在Tiny4412中中断分为三种 分别是软件通用中断(SGI),私有设备中断(PPI),共享设备中断(SPI)。
一共有160个中断号,中断表在Tiny4412手册的745页。前篇写的看门狗中断属于PPI,今天的实验所使用的是SPI。也可以称为外部中断。
前几天的按键驱动篇章我们已经找到按键KEY1对应的寄存器为GPX3_2。查看GPX3CON[2]的描述可知,将其置为0xf,为外部中断模式
对应的中断描述在EXT_INT43[2]中。
有关于EXT_INT43[2]的寄存器: EXT_INT43_CON[2] 选择中断触发方式、
中断开关:EXT_INT43_MASK[2]:
中断状态:EXT_INT43_PEND[2],特别注意的是,要清中断,将值赋值为1.
通过下图可知中断源是26,通过表格查找到中断号为64:
具体代码如下所示:
1 #include "regs.h" 2 3 int (*printf)(char *, ...) = 0xc3e114d8; 4 5 void init_ttb(unsigned long *ttb); 6 void enable_mmu(void); 7 void memcpy(unsigned char *dest, unsigned char *source, int len); 8 void do_irq(); 9 10 int main() 11 { 12 13 enable_mmu(); 14 *(unsigned long *)0x67000000 = do_irq; 15 unsigned long source = 0; 16 __asm__ __volatile__( 17 "ldr %0, =vector_start\n" 18 : "=r" (source) 19 ); 20 memcpy(0, source, 0x1000); 21 22 //step 1: set cpsr i bit 23 __asm__ __volatile__( 24 "mrs r0, cpsr\n" 25 "bic r0, r0, #0x80\n" 26 "msr cpsr, r0\n" 27 ::: "r0" 28 ); 29 30 //step 2: enable gic 31 ICCICR_CPU0 = 1;//终端总开关 32 ICCPMR_CPU0 = 0xff;//设置最低优先级 33 ICDDCR = 1; 34 35 //中断源为64 36 ICDIPR16_CPU0 &= ~0xff ;//设置本中断优先级 37 ICDIPTR16_CPU0 &= 0xff ;// 选择指定的cpu0进行终端处理 38 ICDIPTR16_CPU0 |= 1; // 选择指定的cpu0进行终端处理 39 ICDISER2_CPU0 = 1;//设置本中断开启 40 41 //step 3: set gpio 42 GPX3CON |= (0xf << 8);//使用外部中断模式 43 //step 4: set xeint26 44 EXT_INT43CON &= ~(0x7 << 8); 45 EXT_INT43CON |= ( 2 << 8);//设置中断方式 46 EXT_INT43MASK &= ~(1 << 2);//开中断 47 //step 5 48 printf("welcom back\n"); 49 } 50 51 void do_irq() 52 { 53 printf("key 1 ~~~ \n"); 54 /*清中断*/ 55 EXT_INT43PEND |= (0x1 << 2); 56 } 57 58 __asm__( 59 "vector_start:\n" 60 "b reset\n" 61 "b undef\n" 62 "b swi\n" 63 "b pre_abt\n" 64 "b data_abt\n" 65 ".word 0x0\n" 66 "b irq \n" 67 "b fiq\n" 68 "\n" 69 "reset:\n" 70 "undef:\n" 71 "mov sp, #0x66000000\n" 72 "stmfd sp!, {r0-r12, lr}\n" 73 "\n" 74 "mov r0, #0x67000000\n" 75 "ldr r1, [r0]\n" 76 "blx r1\n" 77 "\n" 78 "mov sp, #0x66000000\n" 79 "ldmea sp, {r0-r12, pc}^\n" 80 "swi:\n" 81 "mov sp, #0x66000000\n" 82 "stmfd sp!, {r0-r12, lr}\n" 83 "\n" 84 "mov r0, #0x67000000\n" 85 "ldr r1, [r0]\n" 86 "blx r1\n" 87 "\n" 88 "mov sp, #0x66000000\n" 89 "ldmea sp, {r0-r12, pc}^\n" 90 "\n" 91 "pre_abt:\n" 92 "data_abt:\n" 93 "mov sp, #0x66000000\n" 94 "sub lr, lr, #4\n" 95 "stmfd sp!, {r0-r12, lr}\n" 96 "\n" 97 "mov r0, #0x67000000\n" 98 "ldr r1, [r0]\n" 99 "blx r1\n" 100 "\n" 101 "mov sp, #0x66000000\n" 102 "ldmea sp, {r0-r12, pc}^\n" 103 "irq:\n" 104 "mov sp, #0x66000000\n" 105 "sub lr, lr, #4\n" 106 "stmfd sp!, {r0-r12, lr}\n" 107 108 "mov r0, #0x67000000\n" 109 "ldr r1, [r0]\n" 110 "blx r1\n" 111 112 "mov sp, #0x66000000\n" 113 "ldmea sp, {r0-r12, pc}^\n" 114 "fiq:\n" 115 116 ); 117 118 void init_ttb(unsigned long *ttb) 119 { 120 unsigned long va = 0; 121 unsigned long pa = 0; 122 123 //00000000~10000000 -> 60000000~64000000 124 for(va=0x00000000; va<0x10000000; va+=0x100000){ 125 pa = va + 0x60000000; 126 ttb[va >> 20] = pa | 2; 127 } 128 129 //10000000~14000000 -> 10000000~14000000 130 for(va=0x10000000; va<0x14000000; va+=0x100000){ 131 pa = va; 132 ttb[va >> 20] = pa | 2; 133 } 134 135 //40000000~80000000 -> 40000000~80000000 136 for(va=0x40000000; va<0x80000000; va+=0x100000){ 137 pa = va; 138 ttb[va >> 20] = pa | 2; 139 } 140 141 //30000000~40000000 -> 50000000~60000000 142 for(va=0x30000000; va<0x40000000; va+=0x100000){ 143 pa = va + 0x20000000; 144 ttb[va >> 20] = pa | 2; 145 } 146 } 147 148 void enable_mmu(void) 149 { 150 unsigned long ttb = 0x70000000; 151 init_ttb(ttb); 152 unsigned long mmu = 0; 153 mmu = 1 | (1 << 3) | (1 << 8); 154 __asm__ __volatile__( 155 "mov r0, #3\n" 156 "mcr p15, 0, r0, c3, c0, 0\n" 157 "mcr p15, 0, %0, c2, c0, 0\n" 158 "mcr p15, 0, %1, c1, c0, 0\n" 159 : 160 : "r" (ttb), "r" (mmu) 161 ); 162 } 163 164 void memcpy(unsigned char *dest, unsigned char *source, int len) 165 { 166 int i = 0; 167 for(i=0; i<len; i++) 168 dest[i] = source[i]; 169 }
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
#define gpiobase 0x11000000 #define GPM4CON (*(volatile unsigned long *)(gpiobase + 0x02E0)) #define GPM4DAT (*(volatile unsigned long *)(gpiobase + 0x02E4)) #define GPX3CON (*(volatile unsigned long *)(gpiobase + 0x0C60)) #define GPX3DAT (*(volatile unsigned long *)(gpiobase + 0x0C64)) #define ICC 0x10480000 #define ICCICR_CPU0 (*(volatile unsigned long *)(ICC + 0x0000)) #define ICCPMR_CPU0 (*(volatile unsigned long *)(ICC + 0x0004)) #define ICCBPR_CPU0 (*(volatile unsigned long *)(ICC + 0x0008)) #define ICCIAR_CPU0 (*(volatile unsigned long *)(ICC + 0x000C)) #define ICCEOIR_CPU0 (*(volatile unsigned long *)(ICC + 0x0010)) #define ICCRPR_CPU0 (*(volatile unsigned long *)(ICC + 0x0014)) #define ICCHPIR_CPU0 (*(volatile unsigned long *)(ICC + 0x0018)) #define ICCABPR_CPU0 (*(volatile unsigned long *)(ICC + 0x001C)) #define INTEG_EN_C_CPU0 (*(volatile unsigned long *)(ICC + 0x0040)) #define ICCIIDR (*(volatile unsigned long *)(ICC + 0x00FC)) #define ICD 0x10490000 #define ICDDCR (*(volatile unsigned long *)(ICD + 0x0000)) #define ICDICTR (*(volatile unsigned long *)(ICD + 0x0004)) #define ICDIIDR (*(volatile unsigned long *)(ICD + 0x0008)) #define ICDISR0_CPU0 (*(volatile unsigned long *)(ICD + 0x0080)) #define ICDISER0_CPU0 (*(volatile unsigned long *)(ICD + 0x0100)) #define ICDISER2_CPU0 (*(volatile unsigned long *)(ICD + 0x0108)) #define ICDICER0_CPU0 (*(volatile unsigned long *)(ICD + 0x0180)) #define ICDISPR0_CPU0 (*(volatile unsigned long *)(ICD + 0x0200)) #define ICDICPR0_CPU0 (*(volatile unsigned long *)(ICD + 0x0280)) #define ICDABR0_CPU0 (*(volatile unsigned long *)(ICD + 0x0300)) #define ICDIPR0_CPU0 (*(volatile unsigned long *)(ICD + 0x0400)) #define ICDIPR1_CPU0 (*(volatile unsigned long *)(ICD + 0x0404)) #define ICDIPR2_CPU0 (*(volatile unsigned long *)(ICD + 0x0408)) #define ICDIPR3_CPU0 (*(volatile unsigned long *)(ICD + 0x040C)) #define ICDIPR4_CPU0 (*(volatile unsigned long *)(ICD + 0x0410)) #define ICDIPR5_CPU0 (*(volatile unsigned long *)(ICD + 0x0414)) #define ICDIPR6_CPU0 (*(volatile unsigned long *)(ICD + 0x0418)) #define ICDIPR7_CPU0 (*(volatile unsigned long *)(ICD + 0x041C)) #define ICDIPR18_CPU0 (*(volatile unsigned long *)(ICD + 0x0448)) #define ICDIPR16_CPU0 (*(volatile unsigned long *)(ICD + 0x0440)) #define ICDIPTR0_CPU0 (*(volatile unsigned long *)(ICD + 0x0800)) #define ICDIPTR1_CPU0 (*(volatile unsigned long *)(ICD + 0x0804)) #define ICDIPTR18_CPU0 (*(volatile unsigned long *)(ICD + 0x0848)) #define ICDIPTR16_CPU0 (*(volatile unsigned long *)(ICD + 0x0840)) #define ICDSGIR (*(volatile unsigned long *)(ICD + 0x0F00)) #define WTCON (*(volatile unsigned long *)0x10060000) #define WTDAT (*(volatile unsigned long *)0x10060004) #define WTCNT (*(volatile unsigned long *)0x10060008) #define WTCLRINT (*(volatile unsigned long *)0x1006000C) #define EXT_INT43CON (*(volatile unsigned long *)0x11000E0C) #define EXT_INT43MASK (*(volatile unsigned long *)0x11000F0C) #define EXT_INT43PEND (*(volatile unsigned long *)0x11000F4C)
最后将看门狗中断和按键中断结合起来:实现按下KEY1后LED灯闪烁,在按下后停止闪烁。
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
1 #include "regs.h" 2 3 int (*printf)(char *, ...) = 0xc3e114d8; 4 5 void init_ttb(unsigned long *ttb); 6 void enable_mmu(void); 7 void memcpy(unsigned char *dest, unsigned char *source, int len); 8 void do_irq(); 9 void led_on(); 10 void led_off(); 11 void wdt_on(); 12 void wdt_off(); 13 14 int main() 15 { 16 enable_mmu(); 17 18 *(unsigned long *)0x67000000 = do_irq; 19 unsigned long source = 0; 20 __asm__ __volatile__( 21 "ldr %0, =vector_start\n" 22 : "=r" (source) 23 ); 24 memcpy(0, source, 0x1000); 25 26 //step 1: set cpsr i bit 27 __asm__ __volatile__( 28 "mrs r0, cpsr\n" 29 "bic r0, r0, #0x80\n" 30 "msr cpsr, r0\n" 31 ::: "r0" 32 ); 33 34 //step 2: enable gic 35 ICCICR_CPU0 = 1; 36 ICCPMR_CPU0 = 0xff; 37 ICDDCR = 1; 38 39 //64 40 ICDIPR16_CPU0 &= ~0xff; 41 ICDIPTR16_CPU0 &= ~0xff; 42 ICDIPTR16_CPU0 |= 1; 43 ICDISER2_CPU0 = 1; 44 45 ICDIPR18_CPU0 &= ~(0xff << 24); 46 ICDIPTR18_CPU0 &= ~(0xff << 24); 47 ICDIPTR18_CPU0 |= (1 << 24); 48 ICDISER2_CPU0 = (1 << 11); 49 50 //step 3: set gpio 51 GPX3CON |= (0xf << 8); 52 53 //step 4: set xeint26 54 EXT_INT43CON &= ~(0x7 << 8); 55 EXT_INT43CON |= (2 << 8); 56 EXT_INT43MASK &= ~(1 << 2); 57 58 //step 5: key down 59 } 60 61 void do_irq() 62 { 63 unsigned long data = ICCIAR_CPU0; 64 unsigned long irq = data & 0x3ff; 65 ICCEOIR_CPU0 = irq; 66 67 if(irq == 64){ 68 if(EXT_INT43PEND & (1 << 2)){ 69 EXT_INT43PEND |= (1 << 2); 70 printf("key 1 down\n"); 71 static int flag = 1; 72 if(flag){ 73 wdt_on(); 74 flag = 0; 75 } 76 else{ 77 wdt_off(); 78 led_off(); 79 flag = 1; 80 } 81 } 82 } 83 if(irq == 75){ 84 WTCLRINT = 1005; 85 printf("wang wang wang\n"); 86 static int flag = 1; 87 if(flag){ 88 flag = 0; 89 led_on(); 90 } 91 else{ 92 led_off(); 93 flag = 1; 94 } 95 } 96 } 97 98 __asm__( 99 "vector_start:\n" 100 " b reset\n" 101 " b undef\n" 102 " b swi\n" 103 " b pre_abt\n" 104 " b data_abt\n" 105 " .word 0x0\n" 106 " b irq \n" 107 " b fiq\n" 108 "\n" 109 "reset:\n" 110 "undef:\n" 111 " mov sp, #0x66000000\n" 112 " stmfd sp!, {r0-r12, lr}\n" 113 " \n" 114 " mov r0, #0x67000000\n" 115 " ldr r1, [r0]\n" 116 " blx r1\n" 117 " \n" 118 " mov sp, #0x66000000\n" 119 " ldmea sp, {r0-r12, pc}^\n" 120 "swi:\n" 121 " mov sp, #0x66000000\n" 122 " stmfd sp!, {r0-r12, lr}\n" 123 " \n" 124 " mov r0, #0x67000000\n" 125 " ldr r1, [r0]\n" 126 " blx r1\n" 127 " \n" 128 " mov sp, #0x66000000\n" 129 " ldmea sp, {r0-r12, pc}^\n" 130 "\n" 131 "pre_abt:\n" 132 "data_abt:\n" 133 " mov sp, #0x66000000\n" 134 " sub lr, lr, #4\n" 135 " stmfd sp!, {r0-r12, lr}\n" 136 " \n" 137 " mov r0, #0x67000000\n" 138 " ldr r1, [r0]\n" 139 " blx r1\n" 140 " \n" 141 " mov sp, #0x66000000\n" 142 " ldmea sp, {r0-r12, pc}^\n" 143 "irq:\n" 144 " mov sp, #0x66000000\n" 145 " sub lr, lr, #4\n" 146 " stmfd sp!, {r0-r12, lr}\n" 147 148 " mov r0, #0x67000000\n" 149 " ldr r1, [r0]\n" 150 " blx r1\n" 151 152 " mov sp, #0x66000000\n" 153 " ldmea sp, {r0-r12, pc}^\n" 154 "fiq:\n" 155 156 ); 157 158 void init_ttb(unsigned long *ttb) 159 { 160 unsigned long va = 0; 161 unsigned long pa = 0; 162 163 for(va=0x00000000; va<0x10000000; va+=0x100000){ 164 pa = va + 0x60000000; 165 ttb[va >> 20] = pa | 2; 166 } 167 168 //10000000~14000000 -> 10000000~14000000 169 for(va=0x10000000; va<0x14000000; va+=0x100000){ 170 pa = va; 171 ttb[va >> 20] = pa | 2; 172 } 173 174 //40000000~80000000 -> 40000000~80000000 175 for(va=0x40000000; va<0x80000000; va+=0x100000){ 176 pa = va; 177 ttb[va >> 20] = pa | 2; 178 } 179 180 //30000000~40000000 -> 50000000~60000000 181 for(va=0x30000000; va<0x40000000; va+=0x100000){ 182 pa = va + 0x20000000; 183 ttb[va >> 20] = pa | 2; 184 } 185 } 186 187 void enable_mmu(void) 188 { 189 unsigned long ttb = 0x70000000; 190 init_ttb(ttb); 191 unsigned long mmu = 0; 192 mmu = 1 | (1 << 3) | (1 << 8); 193 __asm__ __volatile__( 194 "mov r0, #3\n" 195 "mcr p15, 0, r0, c3, c0, 0\n" 196 "mcr p15, 0, %0, c2, c0, 0\n" 197 "mcr p15, 0, %1, c1, c0, 0\n" 198 : 199 : "r" (ttb), "r" (mmu) 200 ); 201 } 202 203 void memcpy(unsigned char *dest, unsigned char *source, int len) 204 { 205 int i = 0; 206 for(i=0; i<len; i++) 207 dest[i] = source[i]; 208 } 209 210 void led_on() 211 { 212 GPM4CON = 0x1111; 213 GPM4DAT = 0; 214 } 215 216 void led_off() 217 { 218 GPM4CON = 0x1111; 219 GPM4DAT = 0xf; 220 } 221 222 void wdt_on() 223 { 224 WTCON = 0 | (1 << 2) | (2 << 3) | (1 << 5) | (50 << 8); 225 WTCNT = 0x8000; 226 WTDAT = 0x8000; 227 } 228 229 void wdt_off() 230 { 231 WTCON = 0; 232 }