第三十八天:Tiny4412驱动开发之外部中断

  在三天前学习按键驱动的时候,按键通过轮循的方式,一直在等待被按下,这时候系统不能够完成其它的操作,这明显是不科学的,可以使用外部中断解决这个问题。

  在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] 选择中断触发方式、

  第三十八天:Tiny4412驱动开发之外部中断_第1张图片

  中断开关: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)
168         dest[i] = source[i];
169 }

 

 

#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) 
reg.h

 

 

 最后将看门狗中断和按键中断结合起来:实现按下KEY1后LED灯闪烁,在按下后停止闪烁。

 

  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)
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 }
中断

 

 

 

  

 

你可能感兴趣的:(Linux)