控制/MCU
在处理器中,所谓中断,是一个过程,即CPU在正在执行程序过程中,遇到外部/内部紧急事件需要处理,暂时中止当前程序执行转而去
为事件服务,待服务完毕,再返回到暂停处(断点)继续执行原来的程序。为事件服务的程序称之为中断服务程序或中断处理程序。严格来说上述过程是针对硬件中断而言的,用软件方法也可以引起中断。硬件原因引起的中断过程中是不可测的,随机的,软件中断是可以人为控制的
断点:一个地址,程序在该处中断,转而取执行中断程序的地址。
中断源:引起中断的信号源。
异常优先级的概念
同时出现两个中断源,就会出现先处理哪个中断的问题。出现这种问题以后,这里就产生一个中断优先级的概念。
ARM处理器中有7种类型的异常,按照优先级从高到低的排列顺序如下:
1.复位异常(reset)
2.数据异常(data abort)
3.快速中断异常(fiq)
4.外部中断异常(irq)
5.预取异常(prefetch abort)
6.软件中断(swi)
7.未定义指令异常(undef)
硬中断 内部中断(不可),外部中断(可屏蔽),外部中断:外部中断一般是指由计算机外设发出的中断请求,如:键盘中断、打印机中断、定时器中断等。外部中断是可以屏蔽的中断,也就是说,利用中断控制器可以屏蔽这些外部设备的中断请求。内部中断:内部中断是指因硬件出错(如突然掉电、奇偶校验错等)或运算出错(除数为零、运算溢出、单步中断等)所引起的中断。内部中断是不可屏蔽的中断。
软中断(不可),软件中断其实并不是真正的中断,它们只是可被调用执行的一般程序
中断响应流程图
通用中断控制器generic interrupt control
中断号:每个中断源都被分配了一个独一无二的中断号(0-1019)
中断掩码:在汇编语言中进行中断前,需要对相应的中断状态字进行授权允许或屏蔽相关中断的操作。
GIC支持的三种中断类型
软件产生的中断SGI,软件生成的中断寄存器(ICDSGIR)。 每个SGI都可以定位多个处理器。 在里面分销商和有针对性的处理器中,SGI通过其中断的组合来唯一标识编号,ID0-ID15和发出处理器的处理器源ID(CPUID0-CPUID7)SGI。(SGI号 0-15)
私有的外设中断PPI,在特定模式下使用的中断Interrupt numbers ID16-ID31 are used for interrupts that are private to a CPU interface and are banked in theDistributor。(PPI号 0-15)
共享的外设中断SPI,外设产生的可以发送给一个或多个核心处理的中断源。Interrupt numbers ID32-ID1019 are used for SPIs.(SPI号 0-987)
中断源
GIC中断控制器框图
The main blocks of the GIC are:
AMBA slave interface AMBA从属接口
Distributor 分配器
CPU interface CPU接口
Clock and reset 时钟和重置
Enable and match signals 启用和匹配信号
GIC主要功能模块:分配器和CPU接口
分配器接收中断,并向相应的CPU接口提供最高优先级的中断。 一个
优先级较低的中断在成为最高优先级时转发到相应的CPU接口
待处理中断。
GIC支持160个中断,Total 160 interrupts including Software Generated Interrupts (SGIs[15:0], ID[15:0]), Private Peripheral Interrupts(PPIs[15:0], ID[31:16]) and Shared Peripheral Interrupts (SPIs[127:0], ID[159:32]) are supported. For SPI, you can
service a maximal 32 * 4 = 128 interrupt requests(SPI号)
分配器框架图
The Distributor provides a programming interface for:
Enabling the forwarding of interrupts to the CPU interfaces globally.
Enabling or disabling each interrupt.
Setting the priority level of each interrupt.
Setting the target processor list of each interrupt.
Setting each peripheral interrupt to be level-sensitive or edge-triggered.
Setting each interrupt as either secure or Non-secure if the GIC implements the Security Extensions.
Sending an SGI to one or more target processors.
启用全局中断向CPU接口的转发。
启用或禁用每个中断。
设置每个中断的优先级。
设置每个中断的目标处理器列表。
将每个外设中断设置为电平敏感或边沿触发。
如果GIC执行安全扩展,则将每个中断设置为安全或不安全。
将SGI发送到一个或多个目标处理器。
查看任意中断的状态
提供软件方式设置或清除任意中断的挂起状态
中断使用中断号进行标识,每个接口可以处理多达1020个中断
Interrupts from sources are identified using ID numbers. Each CPU interface can see up to 1020 interrupts. The
distributor supports up to 1244 interrupts because of banking of SPIs and PPIs.
CPU接口
Programming interface for:
Enabling the signaling of interrupt requests by the CPU interface.
Acknowledging an interrupt.
Indicating completion of the processing of an interrupt.
Setting an interrupt priority mask for the processor.
Defining the preemption policy for the processor.
Determining the highest priority pending interrupt for the processor.
编程接口
通过CPU接口发出中断请求的信号。
确认中断。
指示完成中断的处理。
为处理器设置一个中断优先级掩码。
为处理器定义抢占策略。
确定处理器的最高待处理中断。
中断状态转换图
中断状态
inactive(无效) 中断没有发生
pending(待处理) 中断发生,等待核心处理,待处理的中断都作为通过CPU接口发送到核心处理的候选者。
active(正在处理) 中断给了核心,目前正在进行中断处理
active and pending (处理和待处理)一个中断源正在被核心处理而GIC又接收到来自同一中断源的中断触发信号。
转换A1或A2,添加挂起状态
对于SGI:
在写入指定处理器为目标的ICDSGIR时发生转换。
只有在指定SGI的安全配置(适用于CPU接口)对应于ICDSGIR.SATT位值。如果GIC执行安全扩展和在Secure中写入ICDSGIR。
对于SPI或PPI,如果出现以下情况,则发生转换:
外设发出中断信号或
软件写入ICDISPR。
转换B1或B2,删除挂起状态
过渡不适用于SGI:
待处理的SGI应该通过活动状态进行转换或重置以删除其挂起状态。
处于活动状态的待处理SGI应该通过挂起状态进行转换,或者进行重置以删除挂起状态。
对于SPI或PPI,如果出现以下情况,则发生转换:
电平敏感的中断仅在输入信号有效时才处于等待状态,断言或由于触发了一个边沿触发的中断信号,或者写入一个中断,中断处于待处理状态
ICDISPR。该软件然后写入相应的ICDICPR。
过渡C.
如果中断被启用并且具有足够的优先级来向处理器发送信号,则软件转换发生从ICCIAR读取。
过渡D.
对于SGI,如果关联的SGI被启用并且分发器将其转发到CPU接口,则发生转换同时处理器读取ICCIAR以确认先前的SGI实例。是否
这种转变的发生,取决于ICCIAR的阅读时间与重新规定SGI的时间。
对于SPI或PPI:
转换发生在
中断使能。
从ICCIAR读取软件。该读取将激活状态添加到中断。
- 中断信号保持有效,用于电平敏感中断。这是因为外设没有中断中断直到处理器服务中断。
对于边沿触发中断,是否发生此转换取决于读取的时序ICCIAR相对于检测到重新中断的中断。否则会导致ICCIAR的读取
过渡C,可能之后是过渡A2。转换E1或E2,删除活动状态
当软件写入ICCEOIR时发生转换。
外设和中断控制器处理流程
按键状态
低电平(按下去状态)
高电平(弹起来状态)
下降沿(高电平向低电平跳变的过程)
上升沿(低电平向高电平跳变的过程)
寄存器描述
ICCICR_CPUn 0x0000 CPU interface control register 0x0000_0000 CPU接口控制寄存器(CPU接口内中断送到相应CPU)
ICCPMR_CPUn 0x0004 Interrupt priority mask register 0x0000_0000 中断优先级过滤寄存器(255所有中断都被相应,0不相应任何中断)
ICDISERm_CPUn 0x0100 Interrupt set-enable register (SGI,PPI) 0x0000_FFFF 中断使能寄存器(使能相应中断到分配器)
ICDIPTRm_CPUn 0x0800 Processor targets register (SGI[3:0]) 0x0101_0101 中断目标CPU配置寄存器(选择CPU接口)
ICDDCR 0x0000 Distributor control register 0x0000_0000 分配器控制器(打开分配器)
ICCIAR_CPUn 0x000C Interrupt acknowledge register 0x0000_03FF 中断响应寄存器
ICCEOIR_CPUn 0x0010 End of interrupt register Undefined 中断处理结束寄存器(清除CPU内部相应的中断号)
ICDICPRm_CPUn 0x0280 Interrupt pending-clear register (SGI,PPI) 0x0000_0000 中断状态清除寄存器(清除相应的中断标志位)
按键的寄存器配置
EXT_INT41_PEND 0x0F44 External interrupt EXT_INT41 pending register 0x0000_0000(配置按键的中断pending)
EXT_INT41_CON 0x0E04 External interrupt EXT_INT41 configuration register 0x0000_0000(配置按键的触发方式)
EXT_INT41_MASK 0x0F04 External interrupt EXT_INT41 mask register 0x0000_00FF(按键使能中断)
按键的触发方式
具体寄存器
ICDSER根据中断号选择对应的专门管理所有中断使能寄存器使能中断
ICDPTRm_CPUn,中断号为57-32=25,选ICDIPTR14
根据GIC Interrupt Table查出EINT[9]中断号为57,SP1号为57-32=25,根据下图,八位控制CPU的接口,这里我们的CPU只有四核,每个寄存器控制四个中断的CPU接口选择,SPI号为25,在SPI[27:24],这里我们的CPU接口为0,八位的值为0x00000001(选择哪个接口哪个接口置1),所以这里配置为ICDIPTR.ICDIPTR14= 0X1 《《 8
具体事例代码
/*
* main.c
*
* Created on: 2017-12-4
* Author: Administrator
*/
#include“exynos_4412.h”
voiddo_irq()
{
unsignedint irq_num;//获取中断号
irq_num = CPU0.ICCIAR& 0X3FF;
switch(irq_num)
{
case57:
printf(“i‘m key2 interrupter! interrupter id is %d\n”,irq_num);
GPF3.DAT= 0x1 《《 4;
EXT_INT41_PEND = 0X1 《《 1;//中断重启
ICDICPR.ICDICPR1= 0X1 《《 25;//清理相应的中断标志位
break;
case58:
printf(“i’m key3 interrupter! interrupter id is %d\n”,irq_num);
GPF3.DAT= 0x1 《《 5;
EXT_INT41_PEND = 0x1 《《 2; // 清除相应中断源
ICDICPR.ICDICPR1= 1 《《 26;
break;
default:
printf(“interrupter not exist\n”);
break;
}
CPU0.ICCEOIR= (CPU0.ICCEOIR& ~(0x3ff)) | irq_num;//清理相应的中断号
}
voidmydelay_ms(inttime) {
inti, j;
while(time--) {
for(i = 0; i 《 5; i++)
for(j = 0; j 《 514; j++)
;
}
}
voidperipheral_init()
{
GPF3.CON= GPF3.CON& (~(0xf 《《 16)) | 0x1 《《 16;//灯
GPF3.CON= GPF3.CON& (~(0xf 《《 20)) | 0x1 《《 20;
GPX1.CON= GPX1.CON& (~(0xf 《《 4)) | 0xF 《《 4;//引脚位外部中断
GPX1.CON= GPX1.CON& (~(0xf 《《 8)) | 0xF 《《 8;//引脚位外部中断
EXT_INT41_CON = EXT_INT41_CON & (~(0X3 《《 4)) | (0X2 《《 4);//下降沿触发
EXT_INT41_CON = EXT_INT41_CON & (~(0X3 《《 8)) | (0X2 《《 8);//下降沿触发
EXT_INT41_MASK = EXT_INT41_MASK & (~(0X1 《《 1)); //使能中断
EXT_INT41_MASK = EXT_INT41_MASK & (~(0X1 《《 2)); //使能中断
}
voidgic_init()
{
ICDDCR =1;//使能分配器
CPU0.ICCICR= 0X1;//使能CPU接口
CPU0.ICCPMR= 0XFF;//优先级最低,所有中断都会响应
ICDISER.ICDISER1= (0X1 《《 25) | (0x1 《《 26);
ICDIPTR.ICDIPTR14= (0X1 《《 8) | (0x1 《《 16); //中断送到相应CPU
}
intmain()
{
peripheral_init();
gic_init();
while(1)
{
printf(“working!\n”);
GPF3.DAT= ~(0x3 《《 4);
mydelay_ms(800);
}
};
全部0条评论
快来发表一下你的评论吧 !