异常与中断(一)

使用生活实例引入中断

在这里插入图片描述
假设有个大房间里面有小房间,婴儿正在睡觉,他的妈妈在外面看书。
问:这个母亲怎么才能知道这个小孩醒?

  1. 过一会打开一次房门,看婴儿是否睡醒,然后接着看书
  2. 一直等到婴儿发出声音以后再过去查看,期间都在读书

第一种方法叫做查询方式

  • 优点:简单
  • 缺点: 累
while(1)
{
	1 read book(读书)
	2 open door(开门)
	  if(小孩还在睡)
		 return(继续读书)
	   else
		 照顾小孩	
}

第二种方法叫中断方式

  • 优点:不累
  • 缺点:复杂

如何写程序:

while(1)
{
	read book
}
中断服务程序() //核心问题:如何被调用?
{
	处理照顾小孩
}

我们还是看看母亲被小孩哭声打断如何照顾小孩?

母亲的处理过程

  • 平时看书
  • 发生了各种声音,如何处理这些声音
    • 有远处的猫叫(听而不闻,忽略)
    • 门铃声有快递(开门收快递)
    • 小孩哭声(打开房门,照顾小孩)
  • 母亲的处理
    • 只会处理门铃声和小孩哭声
      • 先在书中放入书签,合上书(保存现场)
      • 去处理 (调用对应的中断服务程序)
      • 继续看书(恢复现场)

不同情况,不同处理

  • 对于门铃:开门取快件
  • 对于哭声:照顾小孩

ARM系统中异常与中断处理流程

在这里插入图片描述
所有的中断源(按键、定时器等),它们发出的中断汇聚到中断控制器,再由中断控制器发送信号给CPU,告诉它发生了哪些紧急情况。

除了这些中断,还有什么可以打断CPU的运行:

  • 指令不对
  • 数据访问有问题
  • Reset信号

这些都可以打断CPU,这些被称为异常,中断属于异常的一种。

ARM系统中如何处理异常与中断?重点在于保存现场以及恢复现场

  • 保存现场(各种寄存器)
  • 处理异常(中断属于一种异常)
  • 恢复现场

细化一下,ARM系统中如何使用异常(中断)?

  • 初始化
    设置中断源,让它可以产生中断
    设置中断控制器(可以屏蔽某个中断,优先级)
    设置CPU总开关,使能中断
  • 执行其它程序:正常程序
  • 产生中断,举例:按下按键->中断控制器->CPU
  • CPU每执行完一条指令都会检查有无中断/异常发生
  • 发现有中断/异常产生,开始处理:
  • 保存现场
  • 分辨异常/中断,调用对于异常/中断的处理函数
  • 恢复现场

不同的芯片,不同的架构,在这方面的处理有差别:
不同的芯片,不同的架构,在这方面的处理稍有差别:

  • 保存/恢复现场:cortex M3/M4是硬件实现的,cortex A7是软件实现的
  • CPU中止当前执行,跳转去执行处理异常的代码:也有差异
    • cortex M3/M4在向量表上放置的是函数地址
    • cortex A7在向量表上放置的是跳转指令

ARM架构中异常与中断的处理

处理流程是一样的
每执行完一条指令都会检查有无中断/异常产生
发现有中断/异常产生,开始处理:

  • 保存现场
  • 分辨异常/中断,调用对应的异常/中断处理函数
  • 恢复现场

不同的芯片,不同的架构在这方面处理稍有差别:

  • CPU中止当前执行,跳转去执行处理异常的代码:也有差异
    cortex M3/M4在向量表上放置的是函数地址
    cortex A7在向量表上放置的是跳转指令
  • 保存/恢复现场:cortex M3/M4是硬件实现的,cortex A7是软件实现的

Cortex M3/M4的向量表

要想理解这个处理流程,需要从向量表说起。
向量,在数学定义里是有方向的量,在程序里可以认为向量就是一个数组,里面有多个项。
在ARM架构里,对于异常/中断,它们的处理入口会整齐地排放在一起。

M3/M4的向量表中,放置的是具体异常/中断的处理函数的地址。
比如发生Reset异常时,CPU就会从向量表里找到第1项,得到Reset_Handler函数的地址,跳转去执行。
比如发生EXTI Line0中断时,CPU就会从向量表里找到第22项,得到EXTI0_IRQHandler函数的地址,跳转去执行。

跳转之前,硬件会保存现场。
函数执行完毕,返回之后,硬件会恢复现场。

M3/M4的异常/中断处理流程

发生异常/中断时,硬件上实现了这些事情:

  • 保存现场:把被中断瞬间的寄存器的值保存进栈里
  • 根据异常/中断号,从向量表中得到函数地址,跳转过去执行
  • 函数执行完后,从栈中恢复现场

保存现场、分辨异常/中断、跳转执行,都是硬件实现的。
我们只需要在向量表中,把处理函数的地址填进去就可以了。
硬件承包了大部分工作。

M3/M4的向量表中,存放的是函数地址

Cortex A7 向量表

实际上,以前的S3C2440属于ARM9处理器,它的异常/中断处理流程与Cortex A7一样。

A7的向量表中,放置的是某类异常的跳转指令。
比如发生Reset异常时,CPU就会从向量表找到第0项,得到b reset指令,执行后就跳转到reset函数。
比如发生任何的中断时,CPU就会从向量表里找到第6项,得到ldr pc,_irq指令,执行后就跳转到_irq函数。

跳转之前,硬件只会保存CPSR寄存器。
跳转之后,软件要保存现场。
函数执行完毕,返回之前,软件恢复现场。

_start: 
    b	reset
	ldr	pc, _undefined_instruction
	ldr	pc, _software_interrupt
	ldr	pc, _prefetch_abort
	ldr	pc, _data_abort
	ldr	pc, _not_used
	ldr	pc, _irq
	ldr	pc, _fiq

A7的异常/中断处理流程

  1. CPU切换到对应的异常模式,比如IRQ模式、未定义模式、SVC模式
  2. 保存被中断时的CPSR到SPSR
    CPSR:当前程序状态寄存器
    SPSR:保存的程序状态寄存器
  3. 跳到这个异常的入口地址去,执行指令,这通常是一条跳转指令

软件要做的事情就比较多了:

  • 保存现场
  • 分辨异常/中断
  • 调用对应的处理函数
  • 恢复现场

A7的向量表中,存放的是跳转指令

中断/异常通用处理流程

CPU每执行完一条指令都会检查有无中断/异常产生,发现有中断/异常产生,开始处理:

  1. 保存现场
  2. 分辨异常/中断,调用对应的异常/中断处理函数
  3. 恢复现场

对于不同的处理器,具体处理工作差别:

  • 保存现场:cortex M3/M4里是硬件完成,cortex A7等是软件实现
  • 分辨异常/中断:cortex M3/M4里是硬件完成,cortex A7等是软件实现
  • 调用处理函数:cortex M3/M4里是硬件来调用,cortex A7等是软件自己去调用
  • 恢复现场:cortex M3/M4里是软件触发、硬件实现,cortex A7等是软件实现

不管是硬件还是软件实现,第一步都是保存现场

为什么要保存现场

在这里插入图片描述
任何程序,最终都会转换为机器码,上述C代码可以转换为右边的汇编指令。

对于这4条指令,它们可能随时被异常打断,怎么保存异常处理完后,被打断的程序还能正常运行?

  • 这4条指令涉及R0、R1寄存器,程序被打断时、恢复运行时,R0、R1要保持不变。
  • 执行完第3条指令,比较结果保存在程序状态寄存器里,程序被打断时、恢复运行时,程序状态寄存器保持不变。
  • 这4条指令,读取a、b内容,程序被打断时,恢复运行时,a、b内容保持不变。

内存保持不变,这很容易实现,程序不越界就可以。
所以,关键在于R0、R1、程序状态寄存器要保持不变(当然不止这些寄存器):

  • 在处理异常前,把这些寄存器保存在栈中,这称为保存现场
  • 在处理完异常后,从栈中恢复这些寄存器,这称为恢复现场

保存现场

在这里插入图片描述
在arm中有个ATPCS(ARM-THUMB procedure call standard)(ARM-Thumb过程调用标准)。
约定R0-R15寄存器的用途:

  • R0-R3:调用者和被调用者之间传参数
  • R4-R11:函数可能被使用,所以在函数的入口保存它们,在函数的出口恢复它们、

在这里插入图片描述

还有一个程序状态寄存器,对于M3/M4它被称为XPSR,对于A7它被称为CPSR,我们简称为PSR。

R0-R15、PSR,就是所谓的现场。

发生异常/中断后,在处理异常/中断前,需要保存现场,难道需要保存所有这些寄存器吗?

不需要!
在C函数中,可以修改R0-R3、R12、R14(LR)以及PSR。
如果C函数要用到这些寄存器,就要把它们保存到栈里,在函数结束前从栈中恢复它们。

这些寄存器被拆分成2部分:调用者保存的寄存器(R0-R3、R12、LR、PSR)、被调用者保存的寄存器(R4-R11)。

比如函数A调用函数B,函数A应该知道:

  • R0-R3是用来传参数给函数B的
  • 函数B可以肆意修改R0-R3
  • 函数A不要指望函数B帮你保存R0-R3
  • 保存R0-R3,是函数A的事情
  • 对于LR、PSR也是同样的事情,保存它们是函数A的责任。

对于函数B:

  • 我用到R4-R11中的某一个,我都会在函数入口保存、在函数返回前恢复
  • 保证在B函数调用前后,函数A看到的R4-R11保持不变

假设函数B就是异常/中断处理函数,函数B本身能保证R4-R11不变,那么保存现场时,只需要保存这些:

  • 调用者保存的寄存器R0-R3、R12、LR、PSR
  • PC

硬件保存现场

在这里插入图片描述

调用C函数

中断处理程序执行完后,它返回LR所指示的位置。
难道把LR设置为被中断的程序的地址就行了吗?
如果只是返回LR所指示的地方,硬件帮我们保存在栈里的寄存器,怎么恢复?

M3/4在调用异常处理函数前,把LR设置为一个特殊的值,转给特殊的值称为EXC_RETURN

当PC寄存器的值等于EXC_RETURN时,会触发异常返回机制,简单地说,会从栈里恢复R0-R3,R12,LR,PC,PSR等寄存器。

操作模式:M3/4有两个操作模式

  • 处理模式:执行中断服务程序等异常处理时,处于处理模式。
  • 线程模式:执行普通应用程序代码时,处于线程模式。

M3/M4有多个SP寄存器:SP_process、SP_main

  • 有些RTOS在运行用户程序时会使用SP_process,默认使用SP_main。

对于A7

在这里插入图片描述
处理器有9中模式:User、Sys、FIQ、IRQ、ABT、SVC、UND、MON、HYP。
上图中深色的寄存器,表示该模式下的"Banked"寄存器,比如SPSR寄存器,在很多模式下都有自己的、单独的寄存器。
比如IRQ模式下访问SPSR时,访问到的是IRQ模式下自己的SPSR irq,别的模式下无法访问SPSR irq。

比较值得关注的是FIQ模式,名为“快中断”,它有很多“Banked”寄存器:R8-R12,SP,LR。
在FIQ模式下,它既然能使用自己的R8-R12,SP,LR,自然不需要去保存被中断的程序的R8-R12,SP,LR寄存器,省去保存这几个寄存器的时间,处理中断时自然就快很多,所以被称为FIQ。

从上图可以看出,几乎每个模式下都有自己的SP寄存器,意味着这些模式下有自己的栈。

当发生异常时,以IRQ为例:

  • CPU会自动切换进入对应的模式,比如进入IRQ模式。
  • 并且会把被中断时的CPSR保存到SPSR_irq里
    所以发生异常/中断时,在保存现场时,只需要保存
  • 调用者保存的寄存器(R0-R3、R12、LR)
  • PC

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/145005.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

接口测试用例设计

接口测试 最后感谢每一个认真阅读我文章的人,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走: 这些资料,对于【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也…

【论文阅读】(VAE)Auto-Encoding Variational Bayes

论文地址:[1312.6114] Auto-Encoding Variational Bayes (arxiv.org) 【前言】:VAE模型是Kingma(也是Adam的作者)大神在2014年发表的文章,是一篇非常非常经典,且实现非常优雅的生成模型,同时它还为bayes概率图模型难以…

老卫带你学---go语言中context库里propagateCancel函数

go语言中context库里propagateCancel函数 // 设置当父context取消时候,子context也取消的逻辑 func propagateCancel(parent Context, child canceler) {//父context永远不会被取消(例如WithValue)done : parent.Done()if done nil {return …

SAP:解决函数CONNE_IMPORT_WRONG_COMP_DECS CX_SY_IMPORT_MISMATCH_ERROR错误

用户反馈报表中取数异常,经检查发现SE37执行取数函数ZLY_R_CWFX03报以下错误。 Category ABAP Programming Error Runtime Errors CONNE_IMPORT_WRONG_COMP_DECS Except. CX_SY_IMPORT_MISMATCH_ERROR ABAP Program ZLY_R_CWFX03FT Application Component Not Assig…

爱上C语言:整型和浮点型在内存中的存储(进制转换,原码,反码,补码以及大小端)

🚀 作者:阿辉不一般 🚀 你说呢:生活本来沉闷,但跑起来就有风 🚀 专栏:爱上C语言 🚀作图工具:draw.io(免费开源的作图网站) 如果觉得文章对你有帮助的话,还请…

spring-cloud 简介

springcloud 定义 1.定义:springcloud为开发人员提供了在分布式系统中快速构建一些通用模式的工具(例如配置管理、服务发现、断路器、路由、控制总线等)2.微服务:基于单体应用,基于业务进行拆分,每个服务都是独立应用…

μC/OS-II---消息邮箱管理1(os_flag.c)

目录 消息邮箱创建消息邮箱删除等待邮箱中的消息向邮箱发送一则消息 消息邮箱创建 OS_EVENT *OSMboxCreate (void *pmsg) {OS_EVENT *pevent; #if OS_CRITICAL_METHOD 3u /* Allocate storage for CPU status register */OS_CPU_SR cpu_sr …

老师们是怎样发期中考试成绩的?

每次期中考试后,老师们总是忙碌于回答家长和学生咨询成绩。技术发展飞快,发布成绩的方式也在不断进步。如今,已经可以通过各种代码、Excel以及小程序等,让学生和家长自助查询成绩,既安全又方便。 简单来说,…

一分钟搞懂什么是this指针(未涉及静态成员和函数)

前言 我们在学习类的过程中,一定听说过this指针,但是并不知道它跟谁相似,又有什么用途,所以接下来,让我们一起去学习this指针吧! 一、this指针的引入 我们先来看下面两段代码,它们输出的是什么&…

Pytorch CUDA CPP简易教程,在Windows上操作

文章目录 前言一、使用的工具二、学习资源分享三、libtorch环境配置1.配置CUDA、nvcc、cudnn2.下载libtorch3.CLion配置libtorch4.CMake Application指定Environment variables5.测试libtorch 四、PyTorch CUDA CPP项目流程1.使用CLion结合torch extension编写可以调用cuda的C代…

DSP生成hex方法

以下使用两种方法生成的HEX文件,亲测可用 (1)万能法 不管.out文件是哪个版本CCS编译器生成的,只要用HEX2000.exe软件,翻译都可以使用。方法: hex2000 -romwidth 16 -memwidth 16 -i -o 20170817chuankou…

问题 D: 过山车(二分图)

首先,绘制二分图 核心思想: 对于每一个左边端点,查找每个右边端点, 若右边端点无对象,则暂时作为该左端点的对象 若右边端点有对象,递归查询其对象是否有其他选择 (1.若有其他选择&#xf…

【Robotframework+python】实现http接口自动化测试

前言 下周即将展开一个http接口测试的需求,刚刚完成的java类接口测试工作中,由于之前犯懒,没有提前搭建好自动化回归测试框架,以至于后期rd每修改一个bug,经常导致之前没有问题的case又产生了bug,所以需要…

MHA的那些事儿

什么是MHA? masterhight availability:基于主库的高可用环境下,主从复制和故障切换 主从的架构 MHA至少要一主两从 出现的目的:解决MySQL的单点故障问题。一旦主库崩溃,MHA可以在0-30s内自动完成故障切换 MHA使用的…

[MySQL] MySQL中的数据类型

在MySQL中,数据类型用于定义表中列的数据的类型。在前面的几篇文章中,我们也会看到有很多的数据类型,例如:char、varchar、date、int等等。本篇文章会对常见的数据类型进行详细讲解。希望会对你有所帮助! 文章目录 一、…

海康G5系列(armv7l) heop模式下交叉编译Qt qmqtt demo,出现moc缺少高版本GLibc问题之解决

1.编辑源 sudo vi /etc/apt/sources.list 2.添加高版本的源 deb http://th.archive.ubuntu.com/ubuntu jammy main #添加该行到文件 3.运行升级 sudo apt update sudo apt install libc6 4.strings /**/libc.so.6 |grep GLIBC_ 参考链接:version GLIBC_2.3…

github 私人仓库clone的问题

github 私人仓库clone的问题 公共仓库直接克隆就可以,私人仓库需要权限验证,要先申请token 1、登录到github,点击setting 打开的页面最底下,有一个developer setting 这里申请到token之后,注意要保存起来&#xff…

【Python+requests+unittest+excel】实现接口自动化测试框架

一、框架结构: 工程目录 二、Case文件设计 三、基础包 base3.1 封装get/post请求(runmethon.py) 1 import requests2 import json3 class RunMethod:4 def post_main(self,url,data,headerNone):5 res None6 if header …

Stable Diffusion新手村-我们一起完成AI绘画

1.工具搭建 感谢bilibili的"秋葉aaaki"大佬出的整合包,让我们方便下载安装一键启动,去它的网盘里下载 我的显卡设备,暂时还够哈,出图速度还可以1-2分钟比较美的质感画面 下载以后需要解压下sd-webui-aki-v4.4.7z&#…

spring-cloud-alibaba-sentinel

sentinel (哨兵) 简介 # 官网 - https://spring-cloud-alibaba-group.github.io/github-pages/hoxton/en-us/index.html#_spring_cloud_alibaba_sentinel # github - https://github.com/alibaba/Sentinel/wiki# 简介 - 随着微服务的普及,服务调用的稳定性变得越来…