乐趣区

关于openharmony:浅谈OpenHarmony-LiteOSA内核之基础硬件中断控制器GIC400

一、前言

OpenAtom OpenHarmony(以下简称“OpenHarmony”)采纳多内核架构,反对 Linux 内核的规范零碎、LiteOS- A 的小型零碎、LiteOS- M 的轻量零碎。

其中 LiteOS- A 要求设施具备肯定的解决能力,比照 LiteOS-M,LiteOS- A 反对以下个性:
(1)MMU 反对:通过 MMU 反对内核态和用户态拆散,反对虚构单元;
(2)反对独立过程:调度对象别离为过程、线程;
(3)反对文件系统:包含虚构文件和块设施等;
(4)反对更简单的 IPC:包含 LiteIPC 等;
(5)反对多核调度:反对双核 MCU,反对双核调度;
(6)反对 POSIX3 接口:为 APP 开发提供更多帮忙。

LiteOS- A 内核个性都是建设在 CPU 硬件的根底上,而中断控制器在反对 LiteOS- A 内核的 CPU 中施展着微小的作用:它治理和管制可屏蔽中断并对可屏蔽中断进行优先权断定,缩小 CPU 的负载,使得 CPU 更加专一于计算。

在嵌入式畛域,ARM 公司提供的芯片目前是市场的支流,OpenHarmony LiteOS- M 内核目前反对的 ARM 公司的 Cortex- M 系列的芯片,而 LiteOS- A 内核反对的则是 ARM 公司性能更弱小的 Cortex-A/ R 系列的芯片,GIC 是 ARM 公司给 Cortex-A/ R 系列芯片提供的一个中断控制器,在移植 OpenHarmony LiteOS- A 内核到特定板子的实际中,咱们遇到了很多 GIC 中断控制器相干的技术问题,所以须要深刻理解 ARM 体系架构下 GIC 中断控制器的原理和应用办法,特此总结并共享给各位网友。

二、GIC 控制器概述

1、GIC 简介
GIC 是 ARM 公司给 Cortex-A/ R 核提供的一个中断控制器,相似 Cortex- M 中的 NVIC。目前 GIC 有 4 个版本:V1~V4:V1 是最老的版本,曾经被废除了;V2~V4 目前正在被大量地应用。

GIC V2 是给 ARMv7- A 架构应用的,比方 Cortex-A5,Cortex-A7、Cortex-A9、Cortex-A15 等,V3 和 V4 是给 ARMv8-A/ R 架构应用的,也就是 64 位芯片应用的。GIC V2 最多反对 8 个核。ARM 会依据 GIC 版本的不同研发出不同的 IP 核,半导体厂商间接购买对应的 IP 核即可,比方 ARM 针对 GIC V2 就开发出了 GIC400 中断控制器 IP 核。留神,具体产品是 GIC400,设计规范是 V2。当 GIC 接管到内部中断信号当前汇报给 ARM 内核,然而 ARM 内核只提供四个信号给 GIC 来汇报中断状况:VFIQ、VIRQ、FIQ 和 IRQ,他们之间的关系如图所示:

在图中,GIC 接管泛滥的内部中断,并对其进行解决,最终只通过四个信号报给 ARM 内核,这四个信号的含意如下:
● VFIQ: 虚构疾速 FIQ
● VIRQ: 虚构内部 IRQ
● FIQ:  疾速中断 IRQ
● IRQ:  内部中断 IRQ

2、GIC 整体实现

下图左侧局部是中断源,两头局部是 GIC 控制器,最右侧是中断控制器向处理器内核发送中断信息。咱们重点要看的是两头的 GIC 局部,GIC 将泛滥的中断源分为三类:①SPI(Shared Peripheral Interrupt),共享中断,即所有 Core 共享的中断,内部中断都属于 SPI 中断。比方按键中断、串口中断等,这些中断所有的 Core 都能够解决,不限定特定 Core。

在图中,每个 SPI 设计是共享的,在 SMP 零碎中每个 SPI 都须要连贯一个线到各个 CPU 中。
②PPI(Private Peripheral Interrupt),公有中断,GIC 是反对多核的,每个核有本人独有的中断,须要指定的外围解决。

在图中,每个 CPU 都有属于本人的 PPIs,对应关系是 1 对 1。
 ③SGI(Software-generated Interrupt),软件中断,由软件触发引起的中断,通过向寄存器 GICD_SGIR 写入数据来触发,零碎应用 SGI 中断来实现多核之间的通信。

在图中,SGI 是软件(软件运行在 CPU 上)触发,所以 SGI 中断源头是各个 CPU 上的利用,另外 SGI 和 PPI 一样,每个 CPU 都有属于本人的 SGI,所以必须指定 CPU。

3、中断 ID

中断源有很多,为了辨别不同的中断源要给它们调配惟一 ID,也就是中断 ID。每一个 CPU 最多反对 1020 个中断 ID,中断 ID 号为 ID0~ID1019。1020 个 ID 蕴含了 PPI、SPI 和 SGI,那么这三类中断是如何调配这 1020 个中断 ID 的呢?调配如下:
● ID0~ID15:这 16 个 ID 调配给 SGI
● ID16~ID31:这 16 个 ID 调配给 PP
● ID32~ID1019:这 988 个 ID 调配给 SPI,像 GPIO 中断、串口中断等这些内部中断

至于具体到某个 ID 对应哪个中断,那就由半导体厂商依据理论状况去定义。比方 I.MX6U 的总共应用了 128 个中断 ID,加上后面属于 PPI 和 SGI 的 32 个 ID,I.MX6U 的中断源共有 128+32=160 个。

4、GIC 逻辑模块

GIC 架构分为了两个逻辑块:Distributor 和 CPU Interface,也就是散发器端和 CPU 接口端。Distributor(散发器端):参考 GIC 整体实现的图,此逻辑块负责解决各个中断事件的散发问题,确定中断事件应该发送到哪个 CPU Interface 下来。散发器收集所有的中断源,能够管制每个中断的优先级,它总是将优先级最高的中断事件发送到 CPU 接口端。散发器端要做的次要工作如下:
① 全局中断使能管制
② 管制每一个中断的使能或者敞开
③ 设置每个中断的优先级
④ 设置每个中断的指标处理器列表
⑤ 设置每个内部中断的触发模式:电平触发或边际触发
⑥ 设置每个中断属于组 0 还是组 1,此设置波及到另外一个畛域平安畛域

CPU Interface(CPU 接口端):CPU 接口端和 CPU Core 相连接,因而每个 CPU Core 都能够在 GIC 中找到一个与之对应的 CPU Interface。CPU 接口端是散发器和 CPU Core 之间的桥梁,CPU 接口端次要工作如下:
① 使能或者敞开发送到 CPU Core 的中断请求信号
② 应答中断
③ 告诉中断解决实现
④ 设置优先级掩码,通过掩码来设置哪些中断不须要上报给 CPU Core
⑤ 定义抢占策略
⑥ 当多个中断到来的时候,抉择优先级最高的中断告诉给 CPU Core

三、GIC400 原理

1、整体框架图
GIC-400 实现了以下的中断类型:
● 16 个软件产生的中断(SGI)
● 每个处理器有 6 个内部公有外设中断(PPI)
● 每个处理器有 1 个外部 PP
● 可配置的共享外设中断(SPI)的数量

GIC-400 的 BD 如下图所示,GIC-400 从中断输出信号中检测 PPI 和 SPI。每个处理器的每个 PPI 中断 ID 都有一个信号。每个 SPI 中断 ID 只有一个输出信号,与 SoC 中处理器的数量无关。SGI 没有输出信号,在 GIC-400 中应用 AXI 编程接口生成。

2、输出信号

上图中右边就是来自外设的 interrupt source 输出信号。分成两种类型,别离是 PPI(Private Peripheral Interrupt)和 SPI(Shared Peripheral Interrupt)。PPI 中断信号是 CPU 公有的,每个 CPU 都有其特定的 PPI 信号线。而 SPI 是所有 CPU 之间共享的。通过寄存器 GICD_TYPER 能够配置 SPI 的个数(最多 480 个)。GIC-400 反对多少个 SPI 中断,其输出信号线就有多少个 SPI interrupt request signal。同样的,通过寄存器 GICD_TYPER 也能够配置 CPU interface 的个数(最多 8 个),GIC-400 反对多少个 CPU interface,其输出信号线就提供多少组 PPI 中断信号线。一组 PPI 中断信号线包含 6 个理论的 signal:

(1)nLEGACYIRQ 信号线。对应 interrupt ID 31,在 bypass mode 下(这里的 bypass 是指 bypass GIC functionality,间接连贯到某个 processor 上),nLEGACYIRQ 能够间接连到对应 CPU 的 nIRQCPU 信号线上。在这样的设置下,该 CPU 不参加其余属于该 CPU 的 PPI 以及 SPI 中断的响应,而是特地为这一根中断线服务。

(2)nCNTPNSIRQ 信号线。来自 Non-secure physical timer 的中断事件,对应 interrupt ID 30。
(3)nCNTPSIRQ 信号线。来自 secure physical timer 的中断事件,对应 interrupt ID 29。
(4)nLEGACYFIQ 信号线。对应 interrupt ID 28。概念与 nLEGACYIRQ 信号线雷同。
(5)nCNTVIRQ 信号线。对应 interrupt ID 27。Virtual Timer Event,和虚拟化相干,这里不予形容。
(6)nCNTHPIRQ 信号线。对应 interrupt ID 26。Hypervisor Timer Event,和虚拟化相干,这里不予形容。

3、输入信号

所谓输入信号,就是 GIC 和各个 CPU 间接的接口,这些接口包含:
(a)触发 CPU 中断的信号。nIRQCPU 和 nFIQCPU 信号线,次要用来触发 ARM  CPU 进入 IRQ mode 和 FIQ mode。
(b)Wake up 信号。nFIQOUT 和 nIRQOUT 信号线,帮助 ARM CPU 的电源治理模块,用来唤醒 CPU。
(c)AXI slave interface signals。AXI(Advanced eXtensible Interface)是一种总线协定,属于 AMBA 标准的一部分。通过这些信号线,ARM CPU 能够和 GIC 硬件 block 进行通信(例如寄存器拜访)。

4、触发门路

上面总结下 SGI、PPI、SPI 三种类型中断的触发门路:
SGI(ID0-ID15):是由 CPU 外部软件触发,所以从 CPU CORE–>CPU interface–>Distributor–>CPU Interface–>CPU CORE。

PPI(ID16-ID31):是由内部器件触发,从 Peripheral–>Distributor–>CPU interface–>CPU  CORE。

SPI(ID32-ID1019):也是内部器件触发,从 Peripheral–>Distributor–>CPU interface–>CPU  CORE。

5、中断状态迁徙图

对于每一个中断而言,有以下 4 个状态:
inactive:中断处于有效状态。
pending:中断处于无效状态,然而 cpu 没有响应该中断。
active:cpu 在响应该中断。
active and pending:cpu 在响应该中断,然而该中断源又发送中断过去。
PS:对于电平触发的中断而言,一个中断的解决阶段也会有 active and pending 的阶段,这是比拟非凡的。

上面是官网提供中断迁徙的条件和场景阐明,要留神的是文中 either 示意转移条件满足其一即可:

四、GIC400 寄存器

1、GIC-400 寄存器地图
所有 GIC-400 寄存器都有短名称。在这些名称中,前三个字符是 GIC,第四个字符示意 GIC-400 的功能块:
● GICD_     分配器
● GICC_     中央处理器接口
● GICH_     虚构接口管制块
● GICV_     虚构 CPU 接口。
GIC-400 寄存器是内存映射的,下表列出了地址范畴:

内存映射的含意:对于 ARM 体系架构而言,IO 和内存是对立编制,寄存器会占用内存的地址范畴。至于 GIC-400 寄存器首地址映射在哪个内存地址上,这是硬件厂商设计,并通过 CP15 协处理器来获取。

2、具体寄存器

上面解释几个经典的寄存器,更多的寄存器请参考 ARM 出品的官网文档。

(1)GICD_CTRL 寄存器

寄存器 GICD_CTRL 各个位的含意如下:

GICD_CTRL_reserved_0:保留。

EnableGrp1:Global enable for forwarding pending Group 1 interrupts from the Distributor to the CPU interfaces:

EnableGrp0:Global enable for forwarding pending Group 0 interrupts from the Distributor to the CPU interfaces:

个人见解:第一,EnableGrp1 和 EnableGrp0 是全局开关,第二,这是 Distributor 侧的开关,至于 CPU interfaces 侧持续参考其它寄存器。

(2)2 GICD_TYPER


GICD_TYPER_reserved_0:个人见解:保留字段,不应用

LSPI:If the GIC implements the Security Extensions, the value of this field is the maximum number of implemented lockable SPIs, from 0 (0b00000) to 31 (0b11111), see Configuration lockdown on page 4-82. If this field is 0b00000 then the GIC does not implement configuration lockdown. If the GIC does not implement the Security Extensions, this field is reserved.

 个人见解:在不使能 ARM 平安体系的性能前提下,此处保留,平安体系的性能临时不应用。

SecurityExtn:
Indicates whether the GIC implements the Security Extensions.0 Security Extensions not implemented.1 Security Extensions implemented.

个人见解:ARM 平安体系的性能,使能后,0 组和 1 组含意不一样,具体须要另外篇幅来论述

GICD_TYPER_reserved_1:

CPUNumber:Indicates the number of implemented CPU interfaces. The number of implemented CPUinterfaces is one more than the value of this field, for example if this field is 0b011, thereare four CPU interfaces. If the GIC implements the Virtualization Extensions, this is also the number of virtual CPU interfaces.

个人见解:the number of implemented CPU interfaces = CPUNumber+1,域值是从 0 开始,含意却是从 1 开始。

ITLinesNumber:Indicates the maximum number of interrupts that the GIC supports. If ITLinesNumber=N, the maximum number of interrupts is 32(N+1). The interrupt ID range is from 0 to (number of IDs – 1).

For example: 0b00011 Up to 128 interrupt lines, interrupt IDs 0-127.

The maximum number of interrupts is 1020 (0b11111). See the text in this section for more information. Regardless of the range of interrupt IDs defined by this field, interrupt IDs 1020-1023 are reserved for special purposes.

个人见解:最大的中断数量是 32*(ITLinesNumber +1)

(3)GICD_IDDR

ProductID:

个人见解:值 0x020 意味着 GIC-400

GICD_IDDR_reserved_0:

个人见解:reserved

Variant:An IMPLEMENTATION DEFINED variant number. Typically, this field is used to distinguishproduct variants, or major revisions of a product.

个人见解:产品主版本号,0x2 代表版本为 2.0

Revision:An IMPLEMENTATION DEFINED revision number. Typically, this field is used to distinguish minor revisions of a product.

个人见解:产品小版本号,0x1 代表修订版为 r0p1。

Implementer:Contains the JEP106 code of the company that implemented the GIC Distributor: Bits [11:8] The JEP106 continuation code of the implementer. For an ARM implementation, this field is 0x4. Bits [7] Always 0. Bits [6:0] The JEP106 identity code of the implementer. For an ARM implementation, bits[7:0] are 0x3B.

个人见解:实现 CPU 接口的公司代码,0x43B 代表 ARM 公司。

(4)GICD_IGROUPn_0


Group_Status_Bits:The GICD_IGROUPR registers provide a status bit for each interrupt supported by the GIC.

Each bit controls whether the corresponding interrupt is in Group 0 or Group 1. Accessible by Secure accesses Only.

For each bit:
0 The corresponding interrupt is Group 0.
1 The corresponding interrupt is Group 1.

For interrupt ID m, when DIV and MOD are the integer division and modulo operations:
a. the corresponding GICD_IGROUPRn number, n, is given by n = m DIV 32
b. the offset of the required GICD_IGROUPR is (0x080 + (4*n))
c. the bit number of the required group status bit in this register is m MOD 32.

个人见解:
① 组状态位,对于每个位:“0”示意相应的中断为 Group 0;“1”示意相应的中断为 Group 1。
② 问:对于一个中断,如何设置它的 Group? 答:首先找到对应的 GICD_IGROUPRn 寄存器,即 n 是多少?还要确定应用这个寄存器里哪一位。对于 interrtups ID m,如下计算:n = m DIV 32,GICD_IGROUPRn 里的 n 就确定了;
③ GICD_IGROUPRn 在 GIC 外部的偏移地址是多少?答:0x080+(4*n),这个信息是为了定位到具体寄存器。
④ 应用 GICD_IPRIORITYRn 中哪一位来示意?答:bit = m mod 32。

⑤ GICD_IGROUPn_0 只是 GICD_IGROUPn 寄存器组的第一个,总共有 4 个寄存器:GICD_IGROUPn_0 到 GICD_IGROUPn_3

(5)GICD_ISENABLER0


Set_Enable_Bits:
The GICD_ISENABLERs provide a Set-enable bit for each interrupt supported by the GIC. For SPIs and PPIs, each bit controls the forwarding of the corresponding interrupt from the Distributor to the CPU interfaces:

Reads:
0 Forwarding of the corresponding interrupt is disabled.
1 Forwarding of the corresponding interrupt is enabled.

Writes:
0 Has no effect.
1 Enables the forwarding of the corresponding interrupt.

After a write of 1 to a bit, a subsequent read of the bit returns the value 1. For interrupt ID m, when DIV and MOD are the integer division and modulo operations:
a.the corresponding GICD_ISENABLER number, n, is given by n = m DIV 32
b.the offset of the required GICD_ISENABLER is (0x100 + (4*n))
c.the bit number of the required Set-enable bit in this register is m MOD 32.

个人见解:
① 对于 SPI 和 PPI 类型的中断,每一位管制对应中断的转发行为:从 Distributor 转发到 CPU interface:读:“0”示意以后是禁止转发的;“1”示意以后是使能转发的;写:“0”示意有效;“1”示意使能转发。
② 对于一个中断,如何找到 GICD_ISENABLERn 并确定相应的位?
答:对于 interrtups ID m,如下计算:n = m DIV 32,GICD_ISENABLERn 里的 n 就确定了;

GICD_ISENABLERn 在 GIC 外部的偏移地址是多少?计算方法为 0x100+(4*n),因为一个寄存器大小为 4 个字节。

应用 GICD_ISENABLERn 中哪一位来示意?计算方法为?bit = m mod 32。

③ 这里的开关也是 Distributor 侧的开关,GICV 硬件设计思维和软件设计思维相似。

④ GICD_ISENABLER0 是此类寄存器组的第一个,总共是 4 个。

(6)GICD_ICFGR0


Int_Config:
The GICD_ICFGRs provide a 2-bit Int_config field for each interrupt supported by the GIC.

For Int_config[1], the most significant bit, bit [2F+1], the encoding is:
0 Corresponding interrupt is level-sensitive.
1 Corresponding interrupt is edge-triggered.

Int_config[0], the least significant bit, bit [2F], reservedFor
For SGIs: Int_config[1] Not programmable, RAO/WI.
For PPIs: Int_config[1] Not programmable, RAZ/WI.
For SPIs: Int_config[1] this bit is programmable.

A read of this bit always returns the correct value to indicate whether the corresponding interrupt is level-sensitive or edge-triggered.

For interrupt ID m, when DIV and MOD are the integer division and modulo operations:
a. the corresponding GICD_ICFGR number, n, is given by n = m DIV 16
b. the offset of the required GICD_ICFGRn is (0xC00 + (4*n))
c. the required Priority field in this register, F, is given by F = m MOD 16, where field 0 refers to register bits [1:0], field 1 refers to bits [3:2], up to field 15 that refers to bits [31:30].

个人见解:对于每一个中断,都有对应的 2 位数据用来形容:它的边际触发,还是电平触发。对于 Int_config [1](即高位[2F + 1]),含意为:“0”示意相应的中断是电平触发;“1”示意相应的中断是边际触发。对于 Int_config [0],即低位[2F],是保留位,这一位就是当前才应用。


五、问题与倡议

1、ARM 芯片设计了 FIQ 和 IRQ 的 2 个解决模式,移植过程中没有用到 FIQ。
2、虚构中断相干的性能也没有用到。
3、平安相干的中断性能后期咱们也没有用到,后续在可信执行环境中会用到。
4、如果代码对中断爱护写得不好的话,会呈现 Systick 产生屡次中断,中断状态为 active &pending,在移植过程中 OpenHarmony 版本不反对嵌套中断。
5、中断解决分为边际触发解决和电平触发解决。这就给咱们不同的利用性能提供了抉择,使得咱们能够在不同个工作下抉择适宜的模式,边际触发实用于对工夫要求高的,比方中断中有计数之类的 (GATE 门控地位 1 时),而电平触发则适宜报警装置。
6、在基于 ARM 的嵌入式应用零碎中,存储系统通常是通过系统控制协处理器 CP15 实现的。ARM 处理器应用协处理器 15(CP15) 的寄存器来管制 cache、TCM 和存储器治理。CP15 蕴含 16 个 32 位的寄存器,其编号为 0~15,具体请参考 ARM 官网文档。
7、givc2 将中断分成了 group0 和 group1,默认状况下,所有中断都是组 0 中断,并应用 IRQ 向连贯的处理器发送信号中断请求。集体了解如果都改为组 1 也是没有问题的,然而没有验证。
8、GIC-400 通用初始化流程:
(1)设置 distributor 和 CPU interface 寄存器组的基地址;
(2)读取 GICD_TYPER 寄存器,计算以后 GIC 最大反对多少个中断源;
(3)初始化 distributor:
a.disable distributor;
b. 设置中断分组;
c. 设置 SPI 中断的路由;
d. 设置 SPI 中断的触发类型;
e.disactive 和 disable 所有中断源;
f.enable distributor;
(4)初始化 CPU Interface:
a. 设置 GIC_CPU_PRIMASK,设置中断优先级 mask level;
b.enable CPU interface;

六、总结

本篇文章从 GIC 控制器概述、GIC400 原理、GIC400 寄存器等方面介绍了 OpenHarmony 内核之根底硬件——中断控制器 GIC400 的内容,心愿开发者能从中学有所获,学以致用。

退出移动版