ARM处理器有哪些工作模式和寄存器?各寄存器作用是什么?ARM异常中断处理流程?

快速学习嵌入式开发其他基础知识?>>>>>>>>> 返回专栏总目录 《嵌入式工程师自我修养/C语言》<<<<<<<<<

Tip📌:鼠标悬停双虚线关键词/句,可获得更详细的描述

一、ARM处理器的工作模式及寄存器

1.1 ARM处理器的工作模式

  ARM处理器有多种工作模式,如下表所示。应用程序正常运行时,ARM处理器工作在用户模式(User mode),当程序运行出错或有中断发生时,ARM处理器就会切换到对应的特权工作模式

处理器模式 模式编码 模式介绍
User mode 0B10000 应用程序正常运行时的工作模式
FIQ mode 0B10001 快速中断模式,中断优先级比IRQ高,用于处理高优先级中断请求
IRQ mode 0B10010 中断模式
Supervisor mode 0B10011 管理模式,用于处理中断和异常,复位和软中断时一般会进入该模式
Abort mode 0B10111 用于处理内存访问错误,指令读取失败时会进入该模式
Undefined mode 0B11011 CPU遇到无法识别的、未定义的指令,会进入该模式
System mode 0B11111 类似用户模式,但可以运行特权OS任务,如切换到其他模式
Monitor mode 0B10110 仅限于安全扩展

1.2 ARM处理器中的寄存器

  在ARM处理器内部,除了基本的ALU和控制单元,还有一系列寄存器(推荐先阅读《CPU是如何工作的?什么是冯·诺依曼架构和哈弗架构?》),包括各种通用寄存器、状态寄存器、控制寄存器,用来控制处理器的运行,保存程序运行时的各种状态和临时结果,如下图所示。

  ARM总共37个寄存器,但每种模式下最多只能访问18个。

在这里插入图片描述

总结:
1、7个模式中除了user是普通模式以外,其他6个都是特权模式
2、6个特权模式中,除了System模式以外,其他5个都是异常模式
3、模式的切换是通过代码写CPSR寄存器进行主动切换的,或者CPU自动切换
4、各种模式可访问的寄存器数量不同,操作权限不同,方便操作系统的安全等级需求
——引自:CSDN-图南楠:《ARM的工作模式和37个寄存器》

  ARM处理器中的寄存器可分为通用寄存器和专用寄存器两种。寄存器R0~R12属于通用寄存器,除了FIQ工作模式,在其他工作模式下这些寄存器都是共用、共享的:

  • R0~R3:通常用来传递函数参数;
  • R4~R11:用来保存程序运算的中间结果或函数的局部变量等;
  • R12:常用来作为函数调用过程中的临时寄存器。

  除了这些在各个模式下通用的寄存器,还有1个R15寄存器固定用作PC,一个固定用作CPSR,还有一些寄存器在各自的工作模式下是独立存在的,如R13、R14、SPSR寄存器,在每个工作模式下都有自己单独的寄存器,各个寄存器功能描述如下:

  • R13:堆栈指针寄存器(StackPointer,SP),用来维护和管理函数调用过程中的栈帧变化,R13总是指向当前正在运行的函数的栈帧,一般不能再用作其他用途
  • R14:链接寄存器(Link Register,LR),在函数调用过程中主要用来保存上一级函数调用者的返回地址;
  • R15:程序计数器(Program Counter,PC),CPU从内存取指令执行,就是默认从PC保存的地址中取的(所以程序跳转时就是把目标地址代码放到PC中),每取一次指令,PC寄存器的地址值自动增加。
  • CPSR:处理器状态寄存器(Current Processor State Register),主要用来表征当前处理器的运行状态。除了各种状态位、标志位,CPSR寄存器里也有一些控制位,用来切换处理器的工作模式和中断使能控制。该寄存器的详细说明如下图所示。

两条Tips📌:

  1. CPSR中的mode位(bit4~bit0共5位)决定了CPU的工作模式,在uboot代码中会使用汇编进行设置。
  2. CPSR中的T控制位(bit5共5位)决定了ARM内核的工作状态,如下所示:
  • ARM状态(T为0):ARM处理器执行32位的ARM指令集:

    • 异常中断时,需要使用ARM指令(ARM状态);
    • ARM处理器在上电开始执行代码时,只能处于ARM状态;
  • THUMB状态(T为1):ARM微处理器执行16位的Thumb指令集

在这里插入图片描述

  • SPSR:程序状态保存寄存器(Saved Processor State Register),当ARM处理器切换工作模式或发生异常时,SPSR用来保存当前工作模式下的处理器现场,即将CPSR寄存器的值保存到当前工作模式下的SPSR寄存器。当ARM处理器从异常返回时,就可以从SPSR寄存器中恢复原先的处理器状态,切换到原来的工作模式继续运行。

Tip📌:
  在ARM所有的工作模式中,有一种工作模式比较特殊,即FIQ模式。为了快速响应中断,减少中断现场保护带来的时间开销,在FIQ工作模式下,ARM处理器有自己独享的R8~R12寄存器。

二、ARM 异常中断处理

2.1 什么是异常?异常向量表是什么?

——异常
  正常工作之外的流程都叫异常,中断是异常的一种。异常会打断正在执行的工作,并且一般我们希望异常处理完成后继续回来执行原来的工作。当 CPU 正常运行时,每执行完一条指令,PC 值都会增加 4 (即往后移动 32 位,指向下一条指令,thumb指令集PC步进为2)。

Tip📌:
  异常和中断都是处理系统中突发事件的机制,请求处理器打断正常的程序执行流程,进入特定的处理或服务程序。但异常是意外操作引起,系统被动接受,与正在执行的指令有直接关系;中断是向处理器主动申请的,和正在执行的指令没有关系。

——异常向量表
  所有的CPU都有异常向量表,这是CPU设计时就设定好的,是硬件决定的。当发生异常中断时的处理方式为:执行完当前指令后,保护现场并跳转到异常中断处理程序处(CPU 通过将 PC 值改为异常向量表中对应异常处理程序的地址,实现跳转)开始执行。处理程序执行完毕,再回到中断前的位置,恢复现场并继续执行。
Tip📌:异常向量表是硬件向软件提供的处理异常的支持。

  向量表是异常的入口地址,发生对应异常时CPU会跳到对应的向量地址,然后再跳转到向量地址中的异常处理地址,实现异常处理。异常向量表一般都存在地址的最低端,异常类型、来源以及对应的地址分布如下表所示:

地址 异常 来源
0x00 复位(Reset) 复位引脚有效(也是系统刚上电时 CPU 跑到的第一个地址)
0x04 未定义指令(Undefined Instruction) 读到了无法解码的指令
0x08 软件中断(SWI,Software Interrupt) 指令引起的异常
0x0C 指令预取中止(Prefetch) 当程序试图执行一个非法的指令或没有执行权限的指令时,会产生该异常
0x10 数据访问终止(DataAbort) 当程序试图访问一个非法的内存地址或没有访问权限的内存地址时,会产生该异常
0x14 无操作(NOP)
0x18 外部中断(IRQ) 当外部设备向处理器发出中断请求时,会产生该异常
0x1C 快速中断(FIQ) 当某些设备需要快速响应时,可以使用该异常,该异常的优先级高于IRQ异常

Tip📌:
  在ARM中,向量表中0x14处的异常类型NOP指的是“无操作”(No Operation),也就是说,当处理器遇到该异常时,它不会执行任何操作,直接返回到下一条指令的执行。这个异常类型通常被用作调试或占位符,以确保向量表的每个条目都被占用,不会被其他异常类型所覆盖。

2.2 异常的响应和返回流程

——异常响应流程

  1. 把返回地址存入对应模式的 LR (即 R14 ,链接寄存器);
  2. CPSR 存入对应 SPSR。这个 SPSR 指的是要跳到的中断模式的 SPSR,比如要从 USR 跳到 FIQ,那就把用户模式的 CPSR 送 FIQ 的SPSR;
  3. 重设 CPSR 各域值,实现把 CPU 切换到对应的模式,比如 FIQ 模式位就是 10001,然后就可以用该模式下的独立寄存器了;
  4. 设置 PC( R15 )为中断向量地址,实现强制跳转。
    在这里插入图片描述

——异常返回流程
在这里插入图片描述
  其中“将PC变回用户指令流中相应指令处”的实际操作时:LR 值减去偏移量后送 PC(减偏移量是因为异常来的时候,硬件可能来不及调整地址。下面是一些异常和对应返回的位置):

异常 返回时LR取值
复位(Reset) 不用返回原位置了
未定义指令(Undefined Instruction) LRLR(无偏移)
软件中断(SWI,Software Interrupt) LR(无偏移)
指令预取中止(Prefetch) LR-4
数据访问终止(DataAbort) LR-8
无操作(NOP)
外部中断(IRQ) LR-4
快速中断(FIQ) LR-4

2.3 异常处理过程示例

AREA boot, CODE, READONLY
ENTRY
    LDR PC, Reset_Add           @ 中断向量表
    LDR PC, Undefined_Add
    @...
    LDR PC, FIQ_Add
    
Reset_Add       DCD Start_Boot  @ 中断处理程序入口,放在内存中
                                @ DCD:分配一段连续的空间并初始化
                                @ 含义:标号 Reset_Add 的值为 Start_Boot 起的一段
Undefined_Add   DCD Undefined_Handler
@...
FIQ_Add         DCD FIQ_Handler
​
Start_Boot                      @...进行实际处理的代码,即中断处理程序实现
Undefined_Handler               @...进行实际处理的代码
FIQ_Handler                     @...进行实际处理的代码

Tip📌:这个可以当模板用,其他的中断处理也就是改改调用的函数。

EXPORT IRQ_Handler      @ EXPORT,声明全局标号,全程序可见,可在其他文件中引用
AREA IRQ_Handler, CODE, READONLY
SUB LR, LR, #0x4        @ 设置返回地址为 LR-4
STMFD SP!, {
   R0-R12, LR} @ 寄存器压栈,保护现场。进中断后这些寄存器随便用
MRS R4, SPSR            @ SPSR 存 R4
STMFD SP!, {
   R4}         @ 压栈,R4 存入 SP 指向的内存位置(即栈顶)
BL IRQ_Function         @ 跳转到真正的中断处理子函数
LDMFD SP!, {
   R4}         @ 恢复
MSR SPSR_cxsf, R4       @ cxsf是指四个8位的域,此处是整个32位寄存器
LDMFD SP!, {
   R0-R12, PC}^ @ 恢复现场并返回
END

>>>>>>>>> 返回专栏总目录 《嵌入式工程师自我修养/C语言》<<<<<<<<<

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-02-21 14:50:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-02-21 14:50:01       100 阅读
  3. 在Django里面运行非项目文件

    2024-02-21 14:50:01       82 阅读
  4. Python语言-面向对象

    2024-02-21 14:50:01       91 阅读

热门阅读

  1. VS和QT联合开发

    2024-02-21 14:50:01       55 阅读
  2. vue父组件调用子组件的方法 或传递值给子组件

    2024-02-21 14:50:01       56 阅读
  3. vue中404解决方法

    2024-02-21 14:50:01       43 阅读
  4. Spring: MultipartFile和File的区别

    2024-02-21 14:50:01       47 阅读
  5. 布客深度学习译文集 2024.2 更新

    2024-02-21 14:50:01       55 阅读
  6. A*的python实现加讲解

    2024-02-21 14:50:01       54 阅读
  7. Python中的Lambda函数

    2024-02-21 14:50:01       49 阅读
  8. 一个网址包含有什么? URL-简介

    2024-02-21 14:50:01       53 阅读
  9. 软件价值14-碰撞弹球

    2024-02-21 14:50:01       52 阅读
  10. C语言:幂的末尾

    2024-02-21 14:50:01       45 阅读
  11. stm32 DMA

    2024-02-21 14:50:01       45 阅读