Cortex-A7内核架构知识总结

I.MX6UL 使用的是 Cortex-A7 架构,本章就给大家介绍一下 Cortex-A7 架构的一些基本知识。了解了 Cortex-A7 架构以后有利于我们后面的学习,因为后面有很多例程涉及到 Cortex-A7架构方面的知识,比如处理器模型、Cortex-A7 寄存器组等等,但是 Cortex-A7 架构很庞大,远不是一章就能讲完的,所以本章只是对 Cortex-A7 架构做基本的讲解,主要是为我们后续的试验打基础。

本章参考了《Cortex-A7 Technical ReferenceManua.pdf》和《ARM Cortex-A(armV7)编程手册 V4.0.pdf》这俩份文档,这两份文档都是 ARM 官方的文档,详细的介绍了 Cortex-A7 架构和ARMv7-A 指令集。

Cortex-A7 MPCore 简介

Cortex-A7 MPcore 处理器支持 1~4 核,通常是和 Cortex-A15 组成 big.LITTLE 架构的,Cortex-A15 作为大核负责高性能运算,比如玩游戏啥的,Cortex-A7 负责普通应用,因为 CortexA7 省电。Cortex-A7 本身性能也不弱,ARM 官网对于 Cortex-A7 的说明如下:

“在 28nm 工艺下,Cortex-A7 可以运行在 1.2~1.6GHz,并且单核面积不大于 0.45mm2 (含有浮点单元、NEON 和 32KB 的 L1 缓存),在典型场景下功耗小于 100mW, 这使得它非常适合对功耗要求严格的移动设备,这意味着 Cortex-A7 在获得与 Cortex-A9 相似性能的情况下,其功耗更低”。

Cortex-A7 MPCore 支持在一个处理器上选配 1~4 个内核,Cortex-A7 MPCore 多核配置如图6.1.1 所示:

注意区分架构和内核。

Cortex-A7 MPCore 的 L1 可选择 8KB、16KB、32KB、64KB,L2 Cache 可以不配,也可以选择 128KB、256KB、512KB、1024KB。I.MX6UL 配置了 32KB 的 L1 指令 Cache 和 32KB 的L1 数据 Cache,以及 128KB 的 L2 Cache。Cortex-A7MPCore 使用 ARMv7-A 架构,主要特性如下:

①、SIMDv2 扩展整形和浮点向量操作。

②、提供了与 ARM VFPv4 体系结构兼容的高性能的单双精度浮点指令,支持全功能的IEEE754。

③、支持大物理扩展(LPAE),最高可以访问 40 位存储地址,也就是最高可以支持 1TB 的内存。

④、支持硬件虚拟化。

⑥、支持 Generic Interrupt Controller(GIC)V2.0。

⑦、支持 NEON,可以加速多媒体和信号处理算法。

不太明白,先放着吧,后续有需要再深究。

Cortex-A 处理器运行模型

以前的 ARM 处理器有 7 中运行模型:User、FIQ、IRQ、Supervisor(SVC)、Abort、Undef和 System,其中 User 是非特权模式,其余 6 中都是特权模式。但新的 Cortex-A 架构加入了TrustZone 安全扩展,所以就新加了一种运行模式:Monitor,新的处理器架构还支持虚拟化扩展,因此又加入了另一个运行模式:Hyp,所以 Cortex-A7 处理器有 9 种处理模式,如表 6.2.1所示:

如果学过 STM32 和 UCOS、FreeRTOS 就会知道,STM32 只有两种运行模式,特权模式和非特权模式,但是 Cortex-A 就有 9 种运行模式。

在表 6.2.1中,除了 User(USR)用户模式以外,其它 8 种运行模式都是特权模式。这几个运行模式可以通过软件进行任意切换,也可以通过中断或者异常来进行切换。大多数的程序都运行在用户模式,用户模式下是不能访问系统所有资源的,有些资源是受限的,要想访问这些受限的资源就必须进行模式切换。但是用户模式是不能直接进行切换的,用户模式下需要借助异常来完成模式切换,当要切换模式的时候,应用程序可以产生异常,在异常的处理过程中完成处理器模式切换。

当中断或者异常发生以后,处理器就会进入到相应的异常模式种,每一种模式都有一组寄存器供异常处理程序使用,这样的目的是为了保证在进入异常模式以后,用户模式下的寄存器不会被破坏。

Cortex-A 寄存器组

本节我们要讲的是 Cortex-A 的内核寄存器组,注意不是芯片的外设寄存器,本节主要参考《ARM Cortex-A(armV7)编程手册 V4.0.pdf》的“第 3 章 ARM Processor ModesAnd Registers”。

ARM 架构提供了 16 个 32 位的通用寄存器(R0~R15)供软件使用,前 15 个(R0~R14)可以用作通用的数据存储,R15 是程序计数器 PC,用来保存将要执行的指令。ARM 还提供了一个当前程序状态寄存器 CPSR 和一个备份程序状态寄存器 SPSR,SPSR 寄存器就是 CPSR 寄存器的备份。这 18 个寄存器如图 6.3.1 所示:

上一小节我们讲了 Cortex-A7 有 9 种运行模式,每一种运行模式都有一组与之对应的寄存器组。每一种模式可见的寄存器包括 15 个通用寄存器(R0~R14)、一两个程序状态寄存器和一个程序计数器 PC。在这些寄存器中,有些是所有模式所共用的同一个物理寄存器,有一些是各模式自己所独立拥有的,各个模式所拥有的寄存器如表 6.3.2 所示:

从图 6.3.2 中浅色字体的是与 User 模式所共有的寄存器,蓝绿色背景的是各个模式所独有的寄存器。可以看出,在所有的模式中,低寄存器组(R0~R7)是共享同一组物理寄存器的,只是一些高寄存器组在不同的模式有自己独有的寄存器,比如 FIQ 模式下 R8~R14 是独立的物理寄存器。假如某个程序在 FIQ 模式下访问 R13 寄存器,那它实际访问的是寄存器 R13_fiq,如果程序处于 SVC 模式下访问 R13 寄存器,那它实际访问的是寄存器 R13_svc。总结一下,CortexA 内核寄存器组成如下:

①、34 个通用寄存器,包括R0~ R15,再加上18个专用的(蓝绿色背景的) ,这些寄存器都是 32 位的。

②、8 个状态寄存器,包括 一个通用的CPSR 和7个专用的 SPSR。

③、Hyp 模式下独有一个 ELR_Hyp 寄存器。

通用寄存器

R0~R15 就是通用寄存器,通用寄存器可以分为以下三类:

①、未备份寄存器,即 R0~R7。

②、备份寄存器,即 R8~R14。

③、程序计数器 PC,即 R15。

分别来看一下这三类寄存器:

1、未备份寄存器

未备份寄存器指的是 R0~R7 这 8 个寄存器,因为在所有的处理器模式下这 8 个寄存器都是同一个物理寄存器,在不同的模式下,这 8 个寄存器中的数据就会被破坏。所以这 8 个寄存器并没有被用作特殊用途。

2、备份寄存器

备份寄存器中的 R8~R12 这 5 个寄存器有两种物理寄存器,在快速中断模式下(FIQ)它们对应着 Rx_irq(x=8~12)物理寄存器,其他模式下对应着 Rx(8~12)物理寄存器。FIQ 是快速中断模式,看名字就是知道这个中断模式要求快速执行! FIQ 模式下中断处理程序可以使用 R8~R12寄存器,因为 FIQ 模式下的 R8~R12 是独立的,因此中断处理程序可以不用执行保存和恢复中断现场的指令,从而加速中断的执行过程。

备份寄存器 R13 一共有 8 个物理寄存器,其中一个是用户模式(User)和系统模式(Sys)共用的,剩下的 7 个分别对应 7 种不同的模式。R13 也叫做 SP,用来做为栈指针。基本上每种模式都有一个自己的 R13 物理寄存器,应用程序会初始化 R13,使其指向该模式专用的栈地址,这就是常说的初始化 SP 指针。

备份寄存器 R14 一共有 7 个物理寄存器,其中一个是用户模式(User)、系统模式(Sys)和超级监视模式(Hyp)所共有的,剩下的 6 个分别对应 6 种不同的模式。R14 也称为连接寄存器(LR),LR 寄存器在 ARM 中主要用作如下两种用途:

①、每种处理器模式使用 R14(LR)来存放当前子程序的返回地址,如果使用 BL 或者 BLX来调用子函数的话,R14(LR)被设置成该子函数的返回地址,在子函数中,将 R14(LR)中的值赋给 R15(PC)即可完成子函数返回,比如在子程序中可以使用如下代码:

MOV PC, LR @寄存器 LR 中的值赋值给 PC,实现跳转

或者可以在子函数的入口出将 LR 入栈:

PUSH {LR} @将 LR 寄存器压栈

在子函数的最后面出栈即可:

POP {PC}
@将上面压栈的 LR 寄存器数据出栈给 PC 寄存器,严格意义上来讲应该是将

@LR-4 赋给 PC,因为 3 级流水线,这里只是演示代码。

②、当异常发生以后,该异常模式对应的 R14寄存器被设置成该异常模式将要返回的地址,R14 也可以当作普通寄存器使用。

3、程序计数器 R15

程序计数器 R15 也叫做 PC,R15 保存着当前执行的指令地址值加 8 个字节,这是因为 ARM的流水线机制导致的。ARM 处理器 3 级流水线:取指->译码->执行,这三级流水线循环执行,比如当前正在执行第一条指令的同时也对第二条指令进行译码,第三条指令也同时被取出存放在 R15(PC)中。我们喜欢以当前正在执行的指令作为参考点,也就是以第一条指令为参考点,那么 R15(PC)中存放的就是第三条指令,换句话说就是 R15(PC)总是指向当前正在执行的指令地址再加上 2 条指令的地址。对于 32 位的 ARM 处理器,每条指令是 4 个字节,所以: R15 (PC)值 = 当前执行的程序位置 + 8 个字节。

程序状态寄存器

所有的处理器模式都共用一个 CPSR 物理寄存器,因此 CPSR 可以在任何模式下被访问。CPSR 是当前程序状态寄存器,该寄存器包含了条件标志位、中断禁止位、当前处理器模式标志等一些状态位以及一些控制位。所有的处理器模式都共用一个 CPSR 必然会导致冲突,为此,除了 User 和 Sys 这两个模式以外,其他 7 个模式每个都配备了一个专用的物理状态寄存器,叫做 SPSR(备份程序状态寄存器),当特定的异常中断发生时,SPSR 寄存器用来保存当前程序状态寄存器(CPSR)的值,当异常退出以后可以用 SPSR 中保存的值来恢复 CPSR。

因为 User 和 Sys 这两个模式不是异常模式,所以并没有配备 SPSR,因此不能在 User 和Sys 模式下访问 SPSR,会导致不可预知的结果。由于 SPSR 是 CPSR 的备份,因此 SPSR 和 CPSR 的寄存器结构相同,如图 6.3.2.1 所示:

图 6.3.2.1 CPSR 寄存器

N(bit31):当两个补码表示的 有符号整数运算的时候,N=1 表示运算对的结果为负数,N=0表示结果为正数。

Z(bit30):Z=1 表示运算结果为零,Z=0 表示运算结果不为零,对于 CMP 指令,Z=1 表示进行比较的两个数大小相等。

C(bit29):在加法指令中,当结果产生了进位,则 C=1,表示无符号数运算发生上溢,其它情况下 C=0。在减法指令中,当运算中发生借位,则 C=0,表示无符号数运算发生下溢,其它情况下 C=1。对于包含移位操作的非加/减法运算指令,C 中包含最后一次溢出的位的数值,对于其它非加/减运算指令,C 位的值通常不受影响。

V(bit28):对于加/减法运算指令,当操作数和运算结果表示为二进制的补码表示的带符号数时,V=1 表示符号位溢出,通常其他位不影响 V 位。

Q(bit27):仅 ARM v5TE_J 架构支持,表示饱和状态,Q=1 表示累积饱和,Q=0 表示累积不饱和。

IT[1:0](bit26:25):和 IT[7:2](bit15:bit10)一起组成 IT[7:0],作为 IF-THEN 指令执行状态。

J(bit24):仅 ARM_v5TE-J 架构支持,J=1 表示处于 Jazelle 状态,此位通常和 T(bit5)位一起表示当前所使用的指令集。

GE[3:0](bit19:16):SIMD 指令有效,大于或等于。

IT[7:2](bit15:10):参考 IT[1:0]。

E(bit9):大小端控制位,E=1 表示大端模式,E=0 表示小端模式。

A(bit8):禁止异步中断位,A=1 表示禁止异步中断。

I(bit7):I=1 禁止 IRQ,I=0 使能 IRQ。

F(bit6):F=1 禁止 FIQ,F=0 使能 FIQ。

T(bit5):控制指令执行状态,表明本指令是 ARM 指令还是 Thumb 指令,通常和 J(bit24)一起表明指令类型,参考 J(bit24)位。

M[4:0]:处理器模式控制位,含义如表 6.3.2.2 所示:

Cortex-A7中断系统

跟 STM32 一样,Cortex-A7 也有中断向量表,中断向量表也是在代码的最前面。CortexA7 内核有 8 个异常中断,这 8 个异常中断的中断向量表如表 17.1.2.1 所示:

这么少??????????????????????

中断向量表里面都是中断服务函数的入口地址,因此一款芯片有什么中断都是可以从中断向量表看出来的。从表 17.1.2.1 中可以看出,Cortex-A7 一共有 8 个中断,而且还有一个中断向量未使用,实际只有 7 个中断。和STM32F103 中断向量表比起来少了很多!难道一个能跑 Linux 的芯片只有这 7 个中断?明显不可能的!那类似 STM32 中的EXTI9_5_IRQHandler、TIM2_IRQHandler 这样的中断向量在哪里?I2C、SPI、定时器等等的中断怎么处理呢?这个就是 Cortex-A 和 Cotex-M 在中断向量表这一块的区别,对于 Cortex-M 内核来说,中断向量表列举出了一款芯片所有的中断向量,包括芯片外设的所有中断。对于 CotexA 内核来说并没有这么做,在表 17.1.2.1 中有个 IRQ 中断, Cortex-A 内核 CPU 的所有外部中断都属于这个 IRQ 中断,当任意一个外部中断发生的时候都会触发 IRQ 中断。在 IRQ 中断服务函数里面就可以读取指定的寄存器来判断发生的具体是什么中断,进而根据具体的中断做出相应的处理。这些外部中断和 IRQ 中断的关系如图 17.1.2.1 所示:

在图 17.1.2.1 中,左侧的 Software0_IRQn~PMU_IRQ2_IRQ 这些都是 I.MX6U 的中断,他们都属于 IRQ 中断。当图 17.1.2.1 左侧这些中断中任意一个发生的时候 IRQ 中断都会被触发,所以我们需要在 IRQ 中断服务函数中判断究竟是左侧的哪个中断发生了,然后再做出具体的处理。

在表 17.1.2.1 中一共有 7 个中断,简单介绍一下这 7 个中断:

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

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

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

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

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

⑥、IRQ 中断(IRQ Interrupt),外部中断,前面已经说了,芯片内部的外设中断都会引起此中断的发生。

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

在上面的 7 个中断中,我们常用的就是复位中断和 IRQ 中断。

GIC 控制器简介

ARM通用中断控制器GIC(generic Interrupt Controller)

GIC 控制器总览

STM32(Cortex-M)的中断控制器叫做 NVIC,I.MX6U(Cortex-A)的中断控制器叫做 GIC,关于 GIC 的详细内容请参考开发板光盘中的文档《ARM Generic Interrupt Controller(ARM GIC控制器)V2.0.pdf》。

GIC 是 ARM 公司给 Cortex-A/R 内核提供的一个中断控制器,类似 Cortex-M 内核中的NVIC。目前 GIC 有 4 个版本:V1~V4,V1 是最老的版本,已经被废弃了。V2~V4 目前正在大量的使用。GIC V2 是给 ARMv7-A 架构使用的,比如 Cortex-A7、Cortex-A9、Cortex-A15 等,V3 和 V4 是给 ARMv8-A/R 架构使用的,也就是 64 位芯片使用的。I.MX6U 是 Cortex-A 内核的,因此我们主要讲解 GIC V2。GIC V2 最多支持 8 个核。ARM 会根据 GIC 版本的不同研发出不同的 IP 核,那些半导体厂商直接购买对应的 IP 核即可,比如 ARM 针对 GIC V2 就开发出了 GIC400 这个中断控制器 IP 核。当 GIC 接收到外部中断信号以后就会报给 ARM 内核,但是ARM 内核只提供了四个信号给 GIC 来汇报中断情况:VFIQ、VIRQ、FIQ 和 IRQ,他们之间的关系如图 17.1.3.1 所示:

在图 17.1.3.1 中,GIC 接收众多的外部中断,然后对其进行处理,最终就只通过四个信号报给 ARM 内核,这四个信号的含义如下:

VFIQ:虚拟快速 FIQ。

VIRQ:虚拟外部 IRQ。

FIQ:快速中断 IRQ。

IRQ:外部中断 IRQ。

VFIQ 和 VIRQ 是针对虚拟化的,我们不讨论虚拟化,剩下的就是 FIQ 和 IRQ 了,我们前面都讲了很多次了。本教程我们只使用 IRQ,所以相当于 GIC 最终向 ARM 内核就上报一个 IRQ信号。那么 GIC 是如何完成这个工作的呢?GICV2 的逻辑图如图 17.1.3.2 所示:

图 17.1.3.2 中左侧部分就是中断源,中间部分就是 GIC 控制器,最右侧就是中断控制器向处理器内核发送中断信息。我们重点要看的肯定是中间的 GIC 部分,GIC 将众多的中断源分为分为三类:

①、SPI(Shared Peripheral Interrupt),共享中断,顾名思义,所有 Core 共享的中断,这个是最常见的,那些外部中断都属于 SPI 中断(注意!不是 SPI 总线那个中断) 。比如按键中断、串口中断等等,这些中断所有的 Core 都可以处理,不限定特定 Core。

②、PPI(Private Peripheral Interrupt),私有中断,我们说了 GIC 是支持多核的,每个核肯定有自己独有的中断。这些独有的中断肯定是要指定的核心处理,因此这些中断就叫做私有中断。

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

中断 ID (中断号)

中断源有很多,为了区分这些不同的中断源肯定要给他们分配一个唯一 ID,这些 ID 就是中断 ID。每一个 CPU 最多支持 1020 个中断 ID,中断 ID 号为 ID0~ID1019。这 1020 个 ID 包含了 PPI、SPI 和 SGI,那么这三类中断是如何分配这 1020 个中断 ID 的呢?这 1020 个 ID 分配如下:

ID0~ID15:这 16 个 ID 分配给 SGI。

ID16~ID31:这 16 个 ID 分配给 PPI。

ID32~ID1019:这 988 个 ID 分配给 SPI,像 GPIO 中断、串口中断等这些外部中断 ,至于具体到某个 ID 对应哪个中断那就由半导体厂商根据实际情况去定义了。比如 I.MX6U 的总共使用了 128 个中断 ID,加上前面属于 PPI 和 SGI 的 32 个 ID,I.MX6U 的中断源共有 128+32=160个,这 128 个中断 ID 对应的中断在《I.MX6ULL 参考手册》的“3.2 CortexA7 interrupts”小节完整的中断源自行查阅。

GIC 逻辑分块

GIC 架构分为了两个逻辑块:Distributor 和 CPU Interface,也就是分发器端和 CPU 接口端。

这两个逻辑块的含义如下:

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

①、全局中断使能控制。

②、控制每一个中断的使能或者关闭。

③、设置每个中断的优先级。

④、设置每个中断的目标处理器列表。

⑤、设置每个外部中断的触发模式:电平触发或边沿触发。

⑥、设置每个中断属于组 0 还是组 1。

CPU Interface(CPU 接口端):CPU 接口端听名字就知道是和 CPU Core 相连接的,因此在图 17.1.3.2 中每个 CPU Core 都可以在 GIC 中找到一个与之对应的 CPU Interface。CPU 接口端就是分发器和 CPU Core 之间的桥梁,CPU 接口端主要工作如下:

①、使能或者关闭发送到 CPU Core 的中断请求信号。

②、应答中断。

③、通知中断处理完成。

④、设置优先级掩码,通过掩码来设置哪些中断不需要上报给 CPU Core。

⑤、定义抢占策略。

⑥、当多个中断到来的时候,选择优先级最高的中断通知给 CPU Core。

中断使能

中断使能包括两部分,一个是 IRQ 或者 FIQ 总中断使能,另一个就是 ID0~ID1019 这 1020个中断源的使能。

1、IRQ 和 FIQ 总中断使能

IRQ 和 FIQ 分别是外部中断和快速中断的总开关,就类似家里买的进户总电闸,然后ID0~ID1019 这 1020 个中断源就类似家里面的各个电器开关。要想开电视,那肯定要保证进户总电闸是打开的,因此要想使用 I.MX6U 上的外设中断就必须先打开 IRQ 中断(本教程不使用FIQ)。在“6.3.2 程序状态寄存器”小节已经讲过了,寄存器 CPSR 的 I=1 禁止 IRQ,当 I=0 使能 IRQ;F=1 禁止 FIQ,F=0 使能 FIQ。我们还有更简单的指令来完成 IRQ 或者 FIQ 的使能和禁止,图表 17.1.5.1 所示:

ID0~ID1019 中断使能和禁止

GIC 寄存器 GICD_ISENABLERn 和 GICD_ ICENABLERn 用来完成外部中断的使能和禁止,对于 Cortex-A7 内核来说中断 ID 只使用了 512 个。一个 bit 控制一个中断 ID 的使能,那么就需要 512/32=16 个 GICD_ISENABLER 寄存器来完成中断的使能。同理,也需要 16 个GICD_ICENABLER 寄存器来完成中断的禁止。其中GICD_ISENABLER0 的 bit[15:0]对应ID15~0 的 SGI 中断,GICD_ISENABLER0 的 bit[31:16]对应 ID31~16 的 PPI 中断。剩下的GICD_ISENABLER1~GICD_ISENABLER15 就是控制 SPI 中断的。

中断优先级设置

优先级数配置

学过 STM32 都知道 Cortex-M 的中断优先级分为抢占优先级和子优先级,两者是可以配置的。同样的 Cortex-A7 的中断优先级也可以分为抢占优先级和子优先级,两者同样是可以配置的。GIC 控制器最多可以支持 256 个优先级,数字越小,优先级越高!Cortex-A7 选择了 32 个优先级。在使用中断的时候需要初始化 GICC_PMR 寄存器,此寄存器用来决定使用几级优先级,寄存器结构如图 17.1.6.1 所示:

GICC_PMR 寄存器只有低 8 位有效,这 8 位最多可以设置 256 个优先级,其他优先级数设置如表 17.1.6.1 所示:

I.MX6U 是 Cortex-A7内核,所以支持 32 个优先级,因此 GICC_PMR 要设置为 0b11111000。

抢占优先级和子优先级位数设置

抢占优先级和子优先级各占多少位是由寄存器 GICC_BPR 来决定的,GICC_BPR 寄存器结构如图 17.1.6.2 所示:

寄存器 GICC_BPR 只有低 3 位有效,其值不同,抢占优先级和子优先级占用的位数也不同,配置如表 17.1.6.2 所示:

为了简单起见,一般将所有的中断优先级位都配置为抢占优先级,比如 I.MX6U 的优先级位数为 5(32 个优先级),所以可以设置 Binary point 为 2,表示 5 个优先级位全部为抢占优先级。

优先级设置

前面已经设置好了 I.MX6U 一共有 32 个抢占优先级,数字越小优先级越高。具体要使用某个中断的时候就可以设置其优先级为 0~31。某个中断 ID 的中断优先级设置由寄存器D_IPRIORITYR 来完成,前面说了 Cortex-A7 使用了 512 个中断 ID,每个中断 ID 配有一个优先级寄存器,所以一共有 512 个 D_IPRIORITYR 寄存器。如果优先级个数为 32 的话,使用寄存器 D_IPRIORITYR 的 bit7:4 来设置优先级,也就是说实际的优先级要左移 3 位。比如要设置ID40 中断的优先级为 5,示例代码如下:

GICD_IPRIORITYR[40] = 5 << 3;

有关优先级设置的内容就讲解到这里,优先级设置主要有三部分:

①、设置寄存器 GICC_PMR,配置优先级个数,比如 I.MX6U 支持 32 级优先级。

②、设置抢占优先级和子优先级位数,一般为了简单起见,会将所有的位数都设置为抢占优先级。

③、设置指定中断 ID 的优先级,也就是设置外设优先级。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值