您当前的位置: 首页 > 

风间琉璃•

暂无认证

  • 0浏览

    0关注

    337博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Cortex-A7中断系统

风间琉璃• 发布时间:2022-02-05 18:49:26 ,浏览量:0

一、中断向量表

中断向量表存放的是中断向量,中断服务程序的入口地址或存放中断服务程序的首地址成为中断向量,因此中断向量表是一系列中断服务程序入口地址组成的表。当某个中断被触发以后就会自动跳转到中断向量表中对应的中断服务程序(函数)入口地址处。中断向量表在整个程序的最前面(是指中断向量表在链接到程序的首地址)

Cortex-A7 一共有 8 个中断,Cortex-A 内核 CPU 的所有外部中断都属于 IRQ 中断,当任意一个外部中断发生的时候都会触发 IRQ 中断。在 IRQ 中断服务函数里面可以读取指定的寄存器来判断发生的具体是什么中断(读取到中断号),进而根据具体的中断做出相应的处理

 ①复位中断(Rest): CPU 复位以后就会进入复位中断,可以在复位中断服务函数里面做一些初始化工作,比如初始化 SP 指针、 DDR 

②未定义指令中断(Undefined Instruction):如果指令不能识别的话就会产生此中断

③软中断(Software Interrupt,SWI):由 SWI 指令引起的中断, Linux 的系统调用会用 SWI 指令来引起软中断,通过软中断来陷入到内核空间

④指令预取中止中断(Prefetch Abort):预取指令的出错的时候会产生此中断

⑤数据访问中止中断(Data Abort):访问数据出错的时候会产生此中断

⑥IRQ 中断(IRQ Interrupt):外部中断,芯片内部的外设中断都会引起此中断的发生

⑦FIQ 中断(FIQ Interrupt):快速中断,如果需要快速处理中断的话就可以使用此中断。

一般ARM 处理器都是从地址 0X00000000 开始运行的,但是阿尔法程序起始地址是0X87800000,所以,可以通过中断向量表偏移将中断向量表存放到任意地址处,中断向量表偏移配置在函数 int_init() (汇编也可以)中完成

常用是复位中断和 IRQ 中断,需要编写这两个中断的中断服务函数,根据上表 的内容来创建中断向量表,中断向量表处于程序最开始的地方

_start:
	ldr pc, =Reset_Handler		/* 复位中断 					*/	
	ldr pc, =Undefined_Handler	/* 未定义中断 					*/
	ldr pc, =SVC_Handler		/* SVC(Supervisor)中断 		*/
	ldr pc, =PrefAbort_Handler	/* 预取终止中断 					*/
	ldr pc, =DataAbort_Handler	/* 数据终止中断 					*/
	ldr	pc, =NotUsed_Handler	/* 未使用中断					*/
	ldr pc, =IRQ_Handler		/* IRQ中断 					*/
	ldr pc, =FIQ_Handler		/* FIQ(快速中断)未定义中断 			*/

 二、GIC控制器 1.GIC简介

Cortex-M的中断控制器叫做 NVIC,Cortex-A的中断控制器叫做 GIC,类似于NVIC。当 GIC 接收到外部中断信号以后就会汇报给 ARM 内核,但是ARM 内核只提供了四个信号给 GIC 来汇报中断情况: VFIQ、 VIRQ、 FIQ 和 IRQ

 GIC内部结构:

左侧部分是中断源,中间部分是 GIC 控制器,右侧是中断控制器向处理器内核发送中断信息 GIC 将中断源分为分为三类:

(1)SPI(Shared Peripheral Interrupt):共享中断,所有 Core 共享的中断,外部中断都属于 SPI 中断 。这些中断所有的 Core 都可以处理,不限定特定 Core

(2)PPI(Private Peripheral Interrupt):私有中断,GIC 是支持多核的,每个核有自己独有的中断。这些独有的中断是要指定的核心处理

(3)SGI(Software-generated Interrupt):软件中断,由软件触发引起的中断,通过向寄存器GICD_SGIR 写入数据来触发,系统会使用 SGI 中断来完成多核之间的通信  

 2.中断ID号

为了区分这些不同的中断源为它们分配一个唯一 ID,每一个 CPU 最多支持 1020 个中断 ID,中断 ID 号为 ID0~ID1019。020 个 ID 包含了 PPI、 SPI 和 SGI

SGI:D0~ID15 PPI:ID16~ID31 SPI:ID32~ID1019

 

 3.GIC逻辑分块

GIC 架构分为了两个逻辑块: Distributor(分发器端) 和 CPU Interface(CPU 接口端)

Distributor(分发器端):  此逻辑块负责处理各个中断事件的分发问题,也就是中断事件应该发送到哪个 CPU Interface 上去。分发器收集所有的中断源,可以控制每个中断的优先级,它总是将优先级最高的中断事件发送到 CPU 接口端

CPU Interface(CPU 接口端):CPU Core 相连接的,每个 CPU Core 都可以在 GIC 中找到一个与之对应的 CPU Interface。 CPU 接口端就是分发器和 CPU Core 之间的桥梁

/*
* GIC 寄存器描述结构体,
* GIC 分为分发器端和 CPU 接口端
*/
typedef struct
{
    /* 分发器端寄存器 */
    uint32_t RESERVED0[1024];
    __IOM uint32_t D_CTLR; /* Offset: 0x1000 (R/W) */

    .....

    /* CPU 接口端寄存器 */
    __IOM uint32_t C_CTLR; /* Offset: 0x2000 (R/W) */
    .....
}

GIC 的分发器端相关寄存器,相对于 GIC 基地址偏移为 0X1000,在获取到 GIC 基地址以后只需要加上 0X1000 即可访问 GIC 分发器端寄存器  

CPU 接口端相关寄存器,相对于 GIC 基地址的偏移为 0X2000,获取到 GIC 基地址以后只需要加上 0X2000 即可访问 GIC 的 CPU 接口段寄存器  

那么GIC 控制器的寄存器基地址在哪里呢?由Cortex-A 的 CP15 协处理器决定  

三、CP15协处理器

CP15 协处理器一般用于存储系统管理, 但是在中断中也会使用到, CP15 协处理器一共有16 个 32 位寄存器  

1.访问指令

MRC: 将 CP15 协处理器中的寄存器数据读到 ARM 寄存器中MCR: 将 ARM 寄存器的数据写入到 CP15 协处理器寄存器中

写:MCR{cond} p15, , , , , cond:指令执行的条件码,如果忽略的话就表示无条件执行 opc1:协处理器要执行的操作码 Rt: ARM 源寄存器,要写入到 CP15 寄存器的数据就保存在此寄存器 CRn: CP15 协处理器的目标寄存器 CRm: 协处理器中附加的目标寄存器或者源操作数寄存器,如果不需要附加信息就将 CRm 设置为 C0,否则结果不可预测 opc2: 可选的协处理器特定操作码,当不需要的时候要设置为 0

读:MRC{cond} p15, , , , ,

此时,Rt 就是目标寄存器,也就是从CP15 指定寄存器读出来的数据会保存在 Rt 中

CRn 就是源寄存器,也就是要读取的写处理器寄存器

 2.寄存器

CP15 协处理器有 16 个 32 位寄存器, c0~c15,这里只介绍c0、 c1、 c12 和 c15 这四个寄 存器,在使用 MRC 或者 MCR 指令访问这 16 个寄存器的时候,指令中的 CRn、 opc1、 CRm 和 opc2 通过不同的搭配,其得到的寄存器含义是不同的

(1)c0寄存器:不同搭配的不同含义 

当 MRC/MCR 指令中的 CRn=c0, opc1=0, CRm=c0, opc2=0 的时候就表示此时的 c0 就是 MIDR 寄存器(主 ID 寄存)

(2)c1寄存器

当 MRC/MCR 指令中的 CRn=c1, opc1=0, CRm=c0, opc2=0 的时候表示此时的 c1 就是 SCTLR 寄存器(系统控制寄存器)

SCTLR 寄存器主要是完成控制功能的,比如使能或者禁止 MMU、 I/D Cache

bit13(V):  中断向量表基地址选择位,为 0 中断向量表基地址为 0X00000000,软件可以使用 VBAR 来重映射此基地址(中断向量表重定位)。为 1 的话中断向量表基地址为0XFFFF0000,此基地址不能被重映射  

bit12:I Cache 使能位,为 0 的话关闭 I Cache,为 1 的话使能 I Cache  

bit11:分支预测使能位,如果开启 MMU 的话,此位也会使能  

bit2:D Cache 和缓存一致性使能位,为 0 的时禁止 D Cache 和缓存一致性,为 1 时使能

bit1:内存对齐检查使能位,为 0 的时关闭内存对齐检查,为 1 的时使能内存对齐检查

bit0: MMU 使能位,为 0 的时禁止 MMU,为 1 的时使能 MMU。  

/* 关闭I,DCache和MMU 
	 * 采取读-改-写的方式。
	 */
	mrc     p15, 0, r0, c1, c0, 0     /* 读取CP15的C1寄存器到R0中       		        	*/
    bic     r0,  r0, #(0x1             
关注
打赏
1665385461
查看更多评论
0.0425s