历史上的今天
今天是:2024年12月22日(星期日)
2021年12月22日 | Tiny4412之外部中断
2021-12-22 来源:eefocus
一:外部中断
在之前我们学习按键驱动的时候,我们检测按键有没有按下是通过轮循的方式(也就是我们说的死循环),这样虽然可以检测实现按键,但太浪费系统资源了,不论我们按键中断有没有发生,cpu都要一直进行检测;这样操作系统就不能做其他事情了,因此这样肯定是不可取得,因此我们可以通过外部中断解决它;
要处理一个中断,我们需要了解模式,而了解模式,有需要了解mmu;在学习这些之后我们就可以返回来处理我们按键驱动的时候留下的问题了;
通过之前的按前驱动我们已经了解了按前驱动在板子上的位置以及按键的电路图以及他的引脚作用,下面我们就如何实现这个程序的步骤:
我们知道控制按键的寄存器为:


外部中断对应的是:
0xf = EXT_INT43[2]
在EXT_INT43[2]中我们选择边沿触发方式:

通过key在核心板的引脚图我们可以知道外部中断源为26,中断号为64


需要我们配置的寄存器:
(1) EXT_INT43PEND (2)EXT_INT43MASK (3)EXT_INT43CON
需要注意的是:中断状态:EXT_INT43_PEND[2],特别注意的是,要清中断,将值赋值为1.
实现一个外部中断大致需要五步:
(1)cpu允许中断
(2)启用GIC
(3)配置外部中断寄存器(xeint)
(4)配置gpio(General Purpose Input Output (通用输入/输出)简称为GPIO,每个GPIO端口可通过软件分别配置成输入或输出)
(5)外部中断源
下面是实现的具体代码:
1 #ifndef __BUNFLY_H
2 #define __BUNFLY_H
3
4 #define ICCICR_CPU0 (*(volatile unsigned long *)0x10480000)
5 #define ICCPMR_CPU0 (*(volatile unsigned long *)0x10480004)
6 #define ICDDCR (*(volatile unsigned long *)0x10490000)
7 #define ICDIPR0_CPU0 (*(volatile unsigned long *)0x10490400)
8 #define ICDIPTR0_CPU0 (*(volatile unsigned long *)0x10490800)
9 #define ICDISER0_CPU0 (*(volatile unsigned long *)0x10490100)
10 #define ICDSGIR (*(volatile unsigned long *)0x10490f00)
11 #define ICCEOIR_CPU0 (*(volatile unsigned long *)0x10480010)
12 #define ICCIAR_CPU0 (*(volatile unsigned long *)0x1048000c)
13 #define ICDIPR2_CPU0 (*(volatile unsigned long *)0x10490408)
14 #define ICDIPTR2_CPU0 (*(volatile unsigned long *)0x10490808)
15 #define ICDIPR3_CPU0 (*(volatile unsigned long *)0x1049040c)
16 #define ICDIPTR3_CPU0 (*(volatile unsigned long *)0x1049080c)
17 #define ICDIPR16_CPU0 (*(volatile unsigned long *)0x10490440)
18 #define ICDIPTR16_CPU0 (*(volatile unsigned long *)0x10490840)
19 #define ICDIPR18_CPU0 (*(volatile unsigned long *)0x10490448)
20 #define ICDIPTR18_CPU0 (*(volatile unsigned long *)0x10490848)
21 #define ICDISER2_CPU0 (*(volatile unsigned long *)0x10490108)
22
23 #define WTCON (*(volatile unsigned long *)0x10060000)
24 #define WTDAT (*(volatile unsigned long *)0x10060004)
25 #define WTCNT (*(volatile unsigned long *)0x10060008)
26 #define WTCLRINT (*(volatile unsigned long *)0x1006000C)
27
28 #define EXT_INT43_CON (*(volatile unsigned long *)0x11000e0c)
29 #define EXT_INT43_MASK (*(volatile unsigned long *)0x11000f0c)
30 #define EXT_INT43_PEND (*(volatile unsigned long *)0x11000f4c)
31 #define GPX3CON (*(volatile unsigned long *)0x11000c60)
32
33 #define GPM4CON (*(volatile unsigned long *)0x110002e0)
34 #define GPM4DAT (*(volatile unsigned long *)0x110002e4)
35
36 #endif //__BUNFLY_H
1 #include "bunfly.h"
2
3 int (*printf)(char *, ...) = 0xc3e114d8;
4 void enable_mmu();
5 void init_table(unsigned long *addr);
6 void memcpy(unsigned char *dest, unsigned char *src, int len);
7 extern unsigned long vector_start;
8 void do_irq();
9
10 int main()
11 {
12 memcpy(0x70000000, vector_start, 0x10000);
13 enable_mmu();
14
15 *(unsigned long *)0x47000000 = do_irq;
16
17 //step 1: cpu permit interrupt
18 __asm__ __volatile__ (
19 "mrs r0, cpsrn"
20 "bic r0, r0, #0x80n"
21 "msr cpsr, r0n"
22 ::: "r0"
23 );
24
25 //step 2: GIC (cgi) enable
26 ICCICR_CPU0 = 1;//总开关
27 ICCPMR_CPU0 = 0xff;//总优先级(门槛)
28 ICDDCR = 1; //本中断开关
29
30 ICDIPR16_CPU0 = (0 << 0); //本中断优先级
31 ICDIPTR16_CPU0 = (1 << 0); //目标cpu
32 ICDISER2_CPU0 = (1 << 0); //启用本中断
33
34 //step 3: Xeint
35 EXT_INT43_CON = (4 << 8);//Triggers Both edge (设置为边沿触发)
36 EXT_INT43_MASK = 0; //开启中断
37
38 //step 4: set gpio
39 GPX3CON = (0xf << 8); //0xF = EXT_INT43[2] (gpio配置为外部中断)
40
41 //step 5: interrupt source
42
43 printf("welcome backn");
44 }
45
46 void do_irq()
47 {
48 unsigned long data = ICCIAR_CPU0;
49 int irq = data & 0x3ff; //获得中断号
50 int cpu = (data >> 10) & 0x7; //获得目标cpu
51 ICCEOIR_CPU0 = irq | (cpu << 10); //清除中断
52 EXT_INT43_PEND |= (1 << 2); //清中断
53 printf("key 1 down, cpu is %d, irq is %dn", cpu, irq);
54 }
55
56 void enable_mmu()
57 {
58 unsigned long addr = 0x50000000;
59 init_table(addr);
60 unsigned long mmu = 0;
61 mmu = 1 | (1 << 1) | (1 << 3) | (1 << 8);
62
63 __asm__ __volatile__ (
64 "mov r0, #3n"
65 "MCR p15, 0, r0, c3, c0, 0n"
66 "MCR p15, 0, %0, c2, c0, 0n"
67 "MCR p15, 0, %1, c1, c0, 0n"
68 :
69 : "r" (addr), "r" (mmu)
70 :
71 );
72 }
73
74 void init_table(unsigned long *addr)
75 {
76 unsigned long va = 0;
77 unsigned long phys = 0;
78
79 for(va = 0x40000000; va < 0x80000000; va+=0x100000)
80 {
81 phys = va;
82 addr[va >> 20] = phys | 2;
83 }
84
85 for(va = 0x10000000; va < 0x14000000; va+=0x100000)
86 {
87 phys = va;
88 addr[va >> 20] = phys | 2;
89 }
90
91 for(va = 0x0; va < 0x10000000; va+=0x100000)
92 {
93 phys = va + 0x70000000;
94 addr[va >> 20] = phys | 2;
95 }
96 }
97
98 __asm__ (
99 "vector:n"
100 " b resetn"
101 " b undefinedn"
102 " b swin"
103 " b pre_abtn"
104 " b data_abtn"
105 " .word 0x0n"
106 " b irqn"
107 " b fiqn"
108
109 "reset:n"
110 "undefined:n"
111 " mov sp, #0x47000000n"
112 " stmdb sp!, {r0-r12, lr}n"
113
114 "ldr r3, =0x47000004n"
115 "ldr r2, [r3]n"
116 "blx r2n"
117
118 " mov sp, #0x47000000n"
119 " ldmdb sp, {r0-r12, pc}^n"
120 "swi:n"
121 " mov sp, #0x47000000n"
122 " stmdb sp!, {r0-r12, lr}n"
123
124 " mov sp, #0x47000000n"
125 " ldmdb sp, {r0-r12, pc}^n"
126 "pre_abt:n"
127 "data_abt:n"
128 " mov sp, #0x47000000n"
129 " sub lr, lr, #4n"
130 " stmdb sp!, {r0-r12, lr}n"
131
132 "ldr r3, =0x47000008n"
133 "ldr r2, [r3]n"
134 "blx r2n"
135
136 " mov sp, #0x47000000n"
137 " ldmdb sp, {r0-r12, pc}^n"
138 "irq:n"
139 " mov sp, #0x47000000n"
140 " sub lr, lr, #4n"
141 " stmdb sp!, {r0-r12, lr}n"
142
143 "mov r3, #0x47000000n"
144 "ldr r2, [r3]n"
145 "blx r2n"
146
147 " mov sp, #0x47000000n"
148 " ldmdb sp, {r0-r12, pc}^n"
149 "fiq:n"
150
151 ".global vector_startn"
152 "vector_start:n"
153 ".word vectorn"
154 );
155
156 void memcpy(unsigned char *dest, unsigned char *src, int len)
157 {
158 int i = 0;
159 for(i = 0; i < len; i++)
160 dest[i] = src[i];
161 }
下面我们通过外部中断(KEY1)控制watchdog,在通过watchdog控制led灯,当key1按下时,led灯开始闪烁,再次按下停止闪烁:
下面贴出代码:
1 #ifndef __BUNFLY_H
2 #define __BUNFLY_H
3
4 #define ICCICR_CPU0 (*(volatile unsigned long *)0x10480000)
5 #define ICCPMR_CPU0 (*(volatile unsigned long *)0x10480004)
下一篇:Tiny4412中断之看门狗
史海拾趣
|
开关电源变压器铁芯磁滞回线测量-part2开关电源原理与设计(连载60) 从原理上来说,只有RC积分电路输出电压的特性与磁场强度取样电路输出电压的特性(速率)基本一致的时候,磁滞回线的显示失真才会最小。那么u1电压的变化特性与u2电压的变化特性是否基本一致呢?为了简单和便于分析,这里我们把输入电压看成是交流脉 ...… 查看全部问答> |
|
#include void __irq IRQ_TIMER0(void) { T0IR = 0X01; VICVectAddr = 0X00; } int main(void) { VICIntSelect = 0X0 ...… 查看全部问答> |
|
wince 5.0 3G如何拨号上网?和GPRS拨号上网有区别吗? wince 5.0 3G如何拨号上网?和GPRS拨号上网有区别吗?以前在WINCE 5.0是通过GPRS拨号上网的。现在要改为3G了,但是拨号拨不上去?怎么回事?高手指点啊。… 查看全部问答> |
|
编译的时候出现: “/cygdrive/d/EmbestIDE/Build/xgcc-arm-elf/bin/arm-elf-ld:.\\ldscript.ld:3: parse error” 然后双击它找错误就会提示: “E:\\cygdrive\\d\\EmbestIDE\\Build\\xgcc-arm-elf\\bin\\arm-elf-ld:.\\ldscript.ld:3中包含 ...… 查看全部问答> |
|
本帖最后由 paulhyde 于 2014-9-15 03:20 编辑 图中的三极管用来定时放电,电路中可以不焊接, 我还有一个疑惑,就是两个27K电阻是用来作为电压补偿的,但是我在测试时没有27K电阻发现去掉电阻没有什么关系,求解释 … 查看全部问答> |
|
请问:(stm32),tim_period& TIM_PrescalerConfig的区别与应用,如何理解?? TIM_Period 设置了在下一个更新事件装入活动的自动重装载寄存器周期的值。它的取值必须在0x0000和 0xffff之间。 TIM_Prescaler 设置了用来作为TIMx时钟频率除数的预分频值。它的取值必须在0x0000和0xFFFF之间。 但是 ...… 查看全部问答> |
|
程序内容:Launchpad首先发送“2JEnter text:”字符串到PC,PC收到数据后可以发送任意数据,Luanchpad收到数据后即可返回同样的数据给PC。 上周学习了如何导入存在的工程文件,依照同样方法导入UART-Echo的工程文件C:\\ti\\TivaWare_C_Series-1.1\ ...… 查看全部问答> |




