文章目录
- 轮询与中断
- 1 CPU与硬件的交互方式
- 2轮询方式实现按键检测
- 3 GPIO 中断
- 3.1 GPX1_1中断相关寄存器配置
- 3.1.1首先设置GPX1_1中断模式(GPX1CON)
- 3.1.2 其次配置GPX1_1中断产生模式为下降沿触发(EXT_INT41CON)
- 3.1.3 然后打开GPX1_1中断(EXT_INT41_MASK 写1关闭 写0开启)
- 清除中断标志位
- 3.1.1代码
- 3.2 中断控制器
- 3.2.1 相关寄存器的配置
- 3.3.2 中断控制器配置代码
- 3.1 GPX1_1中断相关寄存器配置
- 4 中断处理
- 4.1 中断处理框架的搭建
-
- 4.1.1LR 寄存器(链接寄存器)执行跳转指令的原理
- 4.1.2 在中断向量表FRQ中添加中断处理跳转指令
- 4.1.2 irq_handler的编写
- 4.1.3 中断处理程序的编写
-
- 4.2代码
- 4.1 中断处理框架的搭建
轮询与中断 1 CPU与硬件的交互方式 2轮询方式实现按键检测
这里采用4412开发板上的按键2 当其按下,就向串口发送 “key2 poress”
通过上面原理图可知,KEY2连接到板子的GPX1_1上。
由上面原理图可知,当按键K2未被按下时GPX1_1此时的电平时是高电平,被按下时电平是低电平。
可以通过读GPX1_1的电平检测按键是否按下(GPX1_1设置成输入模式)。
#include "exynos_4412.h"
int main()
{
GPX1.CON =GPX1.CON &(~(0xFF)) |(0x00<<4);
while(1)
{
if(!GPX1.DAT & (1<<1))
{
printf("Key2 Pressedn");
while(!GPX1.DAT & (1<<1));
}
else
{
}
}
return 0;
}
3 GPIO 中断
GPIO中断方式实现按键检测(检测到按键按下就向UART2发送Key2 Pressed)
4412开发板上的KEY2连接在GPX1_1上
3.1.1首先设置GPX1_1中断模式(GPX1CON)
配置GPX1CON的[7:4]为0xF
3.1.2 其次配置GPX1_1中断产生模式为下降沿触发(EXT_INT41CON)
配置EXT_INT41CON的[6:4]为0x2
3.1.3 然后打开GPX1_1中断(EXT_INT41_MASK 写1关闭 写0开启)
配置EXT_INT41_MASK 的[1]为0x0
最后挂起GPX1_1中断(EXT_INT41_PEND,一般不用配置,默认开启,但是要在中断处理程序里清除中断标志位)
3.1.4 清除中断标志位
这一个寄存器用于清除中断标志位,注意写1清零
这一个寄存器用于通知中断控制器CPU已经处理完中断(把产生中断的ID写到这个寄存器里)
3.1.5 代码
#include "exynos_4412.h"
void GPIO_INT_INIT(void)
{
GPX1.CON=GPX1.CON |(0xF<<4);
EXT_INT41_CON = EXT_INT41_CON &(~(0x7<<4)) |(0x2<<4);
EXT_INT41_MASK = EXT_INT41_MASK &(~(1<<1));
}
int main()
{
//初始化KEY2中断模式初始化
GPIO_INT_INIT();
return 0;
}
3.2 中断控制器
4412总共能产生160个中断,中断控制器为每一个中断都分配了一个唯一的ID,便于管理。
由上面的原理图可知KYE2的中断时外部中断9.
查芯片手册外部中断9的ID是57,先记住这个ID后面会用到
3.2.1 相关寄存器的配置
这一个寄存器用于使能或者禁止总中断。
这一寄存器用于使能或者禁止控制所有中断的具体那个中断,总共有160个中断,每个寄存器32位,所以需要5个寄存器。
由于KEY的外部中断ID是57,由上图可知,它由第二个寄存器的第25位控制使能与禁止。
ICDIPTR_CPU
这一个寄存器用于控制中断信号交给那个cpu处理(4412是4核处理器,所以只有低四位有用)
由于有160个中断信号,每一个中断信号我们都可以为它选择一个CPU ,每一个中断信号都有一个8位的空间用于控制它交给那个CPU处理,所以总共需要 160*8/32=40个寄存器。下面是对应关系
假设我们要让6号中断交给CPU2处理,那就要往第二个寄存器(基地址+0x804)的16到23位写0000 0010
所以57号中断为偏移量为838的寄存器来控制。由于我们一般会在4412上装一个操作系统,这些工作操作系统都会帮我们处理,所以我们在这里用默认的CPU0来处理中断信号。
这一寄存器用来使能中断信号能否通过CPU到达处理器。使用那个CPU就要使能那个通道(4个)
这一个寄存器的[9:0]位用于记录是谁产生的中断。
3.3.2 中断控制器配置代码
void INI_init(void)
{
ICDDCR = ICDDCR |1;
ICDISER.ICDISER1 = ICDISER.ICDISER1 | (1<<25);
ICDIPTR.ICDIPTR14 = ICDIPTR.ICDIPTR14 & (~(0xFF<<8)) |(0x01<<8);
CPU0.ICCICR =CPU0.ICCICR | 1;
}
4 中断处理
4.1 中断处理框架的搭建
4.1.1LR 寄存器(链接寄存器)执行跳转指令的原理
总之,当产生IRQ中断时LR寄存器保存的地址是不正确的,需要人为修正(再减4)
4.1.2 在中断向量表FRQ中添加中断处理跳转指令
_start: b reset b. b. b. b. b. b irq_handler b
4.1.3 irq_handler的编写
irq_handler :
sub lr ,lr,#4
stmfd sp! ,{r0-r12,lr}
//处理异常
bl do_irq
GPX1.CON=GPX1.CON |(0xF<<4);
EXT_INT41_CON = EXT_INT41_CON &(~(0x7<<4)) |(0x2<<4);
EXT_INT41_MASK = EXT_INT41_MASK &(~(1<<1));
}
void INI_init(void)
{
ICDDCR = ICDDCR |1;
ICDISER.ICDISER1 = ICDISER.ICDISER1 | (1<<25);
ICDIPTR.ICDIPTR14 = ICDIPTR.ICDIPTR14 & (~(0xFF<<8)) |(0x01<<8);
CPU0.ICCICR =CPU0.ICCICR | 1;
}
void LED_init(void)
{
GPX2.CON=GPX2.CON &(~(0xF<<28)) |(0x1<<28);
}
void Delay(int time)
{
while(time--);
}
int main()
{
//初始化KEY2中断模式初始化
GPIO_INT_INIT();
//中断控制器初始化
INI_init();
//led初始化
LED_init();
while(1)
{
GPX2.DAT=GPX2.DAT & (~(1<<7));
Delay(1000000);
GPX2.DAT=GPX2.DAT | (1<<7);
Delay(1000000);
}
return 0;
}



