嵌入式Arm+Linux中断与异常全流程讲解

2023-05-16

嵌入式ARM+Linux中断全流程讲解

  • ARM处理器级别的中断(异常)
    • ARM的异常类型
    • CPU如何检测到异常信息、进入异常处理后怎么返回
      • 前置知识:流水线,指令周期,机器周期,时钟周期
      • 复位。复位就直接从程序第一条开始重新执行,不会有其他流程。
      • 未定义指令
      • 软件中断
  • Boot loader级别的中断(异常)
  • Linux级别的中断(异常)
      • Linux中异常、中断、系统调用、陷入的概念区分

ARM处理器级别的中断(异常)

ARM的异常类型

我们常说的IRQ中断和FIQ中断属于ARM异常的两种,下面统一用异常来表示,ARM有七种异常。如图1所示。
在这里插入图片描述

图1. ARM的七种异常

CPU如何检测到异常信息、进入异常处理后怎么返回

异常处理的源头,首先在于CPU检测到了异常信号。下面分别介绍这七种异常分别在什么时候被检测到,又在什么时候进行处理。

前置知识:流水线,指令周期,机器周期,时钟周期

我们站在汇编语言的角度来看待程序的执行,一条汇编指令从内存中取出该指令,到整个指令执行完毕,总花费的时间称为指令周期,如果是ARM7的三级流水线,每条指令的运行又分为取指、译码、执行三个阶段,如果是ARM9的五级流水线,每条指令的运行分为取指、译码、执行、访问内存、执行结果写入寄存器,后面两级是针对于内存的加载和存储指令的,‘执行’仍然在第三级上。像取指、译码、执行等操作,每完成一个这样的操作的时间叫做机器周期 ,当然每个操作的机器周期不一定相同,每个机器周期可能有包含若干个时钟周期,就是晶振频率的倒数,是计算机最基本的时间单元。还有注意一点,取指、译码、执行等操作都是在我们通常认为的CPU中进行的,任何一个阶段检测到异常信号,就等同于CPU检测到了异常信号。

复位。复位就直接从程序第一条开始重新执行,不会有其他流程。

未定义指令

假设有ins1、ins2、ins3、ins4、ins5,这五个汇编指令,其中ins3是未定义的指令,假设流水线是ARM9的五级(三级也一样,关键是执行这一级在哪个位置),假设流水线已经满载。在指令周期1中,当ins1在执行时,ins2在译码,ins3在取指,此时PC的值为ins1的地址+8(一般说法是PC指向下一条将要执行的指令的地址,这里的执行是概念上的执行,可以理解为运行,运行的第一步是取指,所以PC实际上是指向下一条将要取指的指令的地址);指令周期2中,ins2开始执行,ins3开始译码,ins4开始取指令,此时PC的值为ins2的地址+8,但是这里问题来了,由于ins3是未定义的,也就是说指令集里没有这个指令,那么在译码时就会出错,引发未定义指令异常。总结:未定义指令在译码阶段就会出现异常信号。 我们经常在各种书上看到一句"CPU在每条指令执行完后检测是否有异常信号"。我个人是这么理解的,由于执行阶段一般耗时比译码阶段长,所以ins3译码出问题后,会等待ins2执行完毕,这符合每条指令执行完毕就检测异常信号的说法。这样ins2执行完毕后,检测到未定义异常,ARM CPU核会自动做以下事情:
(1)将当前PC的值复制给LR_und,注意此时PC的值是ins2地址加8,也就是当前刚刚执行完毕的指令地址加8,也就是ins4的地址。
(2)将CPSR的值复制给SPSR_und
(3)设置CPSR为und模式
(4)将PC的值设置为und在异常向量表中的地址
程序员需要编写程序完成以下事情:
(1)在und异常向量表的地址放跳转指令,跳到具体处理und的代码
(2)在具体处理und的代码中:
(2.1)保存现场,将各种寄存器都压入栈
(2.2)处理und
(2.3)返回:将LR_und的值直接赋给PC。为什么是直接赋给PC呢?,这里返回正常是想继续让ins2的下一条指令,也就是ins3得到执行,但是ins3是未定义的,不需要执行,所以希望执行ins4,而此时PC的值正好就是ins4的地址。注意: 可能有人会疑惑之前ins2执行的时候,ins4不是已经取指了吗,直接进行译码不就行了?这是因为通过PC值进行无条件转移时会导致流水线清空,所以得从新取指令。

软件中断

跟上文一样,假设ins3是软中断指令,个人假设,由于cpu是知道这类swi指令必然引发软中断异常的,所以在译码阶段就能识别这是软中断指令,从而引发异常。总结:软中断指令和未定义指令一样,在译码阶段检测到异常 。同时由于译码完成,也已经知道了软中断调用的系统调用号,这时ins2执行完毕后检测到异常信号,跳转去执行软中断的处理,过程和上面类似,在处理完成后返回时,仍然是将LR_svc的值直接赋给PC,因为不需要实际运行ins3,我们知道它是swi指令,知道它要运行的系统调用,我们已经在swi中断中处理了,所以直接运行ins4。
https://blog.csdn.net/weixin_43625081/article/details/108622207
https://blog.csdn.net/Setul/article/details/53992920
https://blog.51cto.com/embedjee/739830
https://blog.csdn.net/lee244868149/article/details/49488575?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-49488575-blog-75193885.pc_relevant_multi_platform_whitelistv1&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1-49488575-blog-75193885.pc_relevant_multi_platform_whitelistv1&utm_relevant_index=1

Boot loader级别的中断(异常)

以uboot为例子,uboot在没启动内核之前,可能需要用到中断,比如USB传输数据需要用到中断,这时可以在启动文件中做一些中断的处理,这部分和单板中断没有区别。但是如果uboot马上要启动内核了,内核启动之前必须禁止中断,因为内核启动过程中虽然会有对中断的初始化,但是如果还没有初始化好,处在一个中间阶段,这时出现了中断,会跳到uboot的中断代码,这样uboot运行后不一定能再次正确的启动内核。

Linux级别的中断(异常)

检测到异常信号时,CPU怎么知道异常向量表在哪里呢?是不是在芯片手册中固定死了的?这个

Linux中异常、中断、系统调用、陷入的概念区分

参考1:https://blog.csdn.net/clp_csdnid/article/details/50964641
参考2:https://www.6miu.com/read-3186100.html
参考3:https://blog.csdn.net/linuxweiyh/article/details/106891526
参考4:https://blog.csdn.net/icyfire0105/article/details/1898523

一个原则:不管Linux是怎样的,Linux最终还是要运行在具体的硬件上,比如用户态和内核态,最终还是区别在arm模式的区别。对于中断和异常,arm芯片有自己的定义(异常包含中断,七种异常,七种模式),Linux的运行必定是依赖于arm芯片的。

系统调用: 系统调用通过SWI软中断指令实现,比如我们在应用程序(运行在用户空间)调用read()函数,这个函数实际调用C库中的read函数,C库中的read函数引发SWI软中断,一般单板用SWI后面会指定一个立即数,该立即数是系统调用号,注意所有的系统调用都用软中断,软中断会跳转到处理软中断的中断处理程序,处理程序需要系统调用号来区别这个软中断具体需要执行什么,比如read和write都是软中断,也就是说系统调用号是来区分open、read、write这种的。回忆我们在用户程序中对read的调用,我们调用的read函数还带有几个参数,比如读的文件名字、读的大小等等,因为SWI加立即数已经占满了一条指令32位的空间,所以这些参数是通过寄存器传递的,C库会负责将参数放到指定的寄存器中,再去调用具体的系统调用,系统调用处理函数首先根据系统调用号选择操作类型,然后根据寄存器内容进行具体操作。当然,结果得返回也是通过寄存器进行传递的。
在这里插入图片描述
上图的sys_read()就会根据传入的文件名找到其主从设备号,进而找到对应驱动,调用驱动中的read函数。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式Arm+Linux中断与异常全流程讲解 的相关文章

随机推荐

  • Win 10下Anaconda安装 Tensorflow&Tensorflow-gpu

    Win 10安装 Tensorflow amp Tensorflow gpu 运行环境为WIN 10 Anaconda python 3 7 3 本文为Anaconda直接安装匹配的cuda xff0c cudnn 安装Anaconda A
  • 80c51流水灯程序汇编语言,单片机闪烁灯流水灯汇编代码大全

    1 单片机AT89C51的P2口接8个发光二极管 xff0c 让这8个发光二极管显示闪烁功能 xff0c 即八灯亮2S xff0c 熄灭3S xff0c 如此循环 参考程序 xff1a ORG 0000H start MOV P1 0H C
  • xp系统登录不上ftp服务器,在XP中顺利登录FTP服务器

    董师傅教你 xff1a 通过系统设置解决在IE7 0中直接输入FTP地址无法登录服务器问题 最近 xff0c 笔者新装了Windows XP系统 xff0c 系统自带的IE版本为7 0 在IE地址栏中输入内网FTP地址 xff0c 如ftp
  • linux内核模块签名,如何签名内核模块Ubuntu 18.04

    问题描述 我是使用Ubuntu的新手 我正在尝试安装Genymotion xff0c 以便可以访问Android模拟器 为了使用Genymotion xff0c 需要我有VirtualBox 我已经安装了VirtualBox xff0c 但
  • 常用的几种API获取ip地理位置的使用方法

    最近公司让做一个用户登录 付费的时候记录操作人的地理位置 搜了很多帖子 xff0c 一开始用的淘宝的api xff0c 但是用了一段时间发现 xff0c 这个api当获取的次数多了之后 xff0c 就报404了 xff0c 导致很多记录没有
  • java部分匹配字符串_关于字符串:在Java中匹配子字符串

    我有一个输入数据存储在arraylist中 在遍历列表时 xff0c 输出是 Input 0 Overcast 1 High 2 Normal 3 Weak Input 0 Rainy 1 Mild 2 High 3 Strong Inpu
  • Ubuntu20.04LTS环境docker+cephadm方式部署Ceph 17.2.5

    Ubuntu20 04LTS环境docker 43 cephadm方式部署Ceph 17 2 5 1 前言2 环境准备2 1 主机信息2 2 NTP时间同步2 3 关闭 iptable 和 firewalld2 4 关闭 SElinux2
  • java如何解析xml?

    技术点 xff1a getResourceAsStream方法 xff0c dom4j的SaxReader解析xml 例 xff1a 1 加载磁盘xml文件到内存中 InputStream package com example utils
  • python识别数字论文_Python3使用tesserocr识别字母数字验证码的实现

    一 背景 最近有个需求是从一个后台的留言网站爬取留言数据 xff0c 后台管理网站必然涉及到了登录 xff0c 登录就有个验证码的问题必须得解决 xff0c 由于验证码是从后端生成的 xff0c 并且不了解其生成规则 xff0c 那就只能通
  • 用jsonserve和axios做交互_vue中axios对json-server提供的多层json数据如何增删改?

    问题描述 使用json server将json变成一个服务 xff0c 可以根据后缀不同获取到不同的数据 xff0c 而axios可以对数据进行操作 xff01 xff01 xff01 xff01 xff01 xff01 xff01 xff
  • Linux下redis基本安装配置(CentOS7)

    1 下载 http redis io download 2 上传安装包 3 开始安装 rpm ivh jemalloc 3 6 0 1 el7 x86 64 rpm rpm ivh redis 4 0 8 1 el7 remi x86 64
  • 更新计算机策略命令,组策略更新命令

    对于Windows 2000域来说 xff0c 如果你想让新修改的计算机策略立即生效的话 xff0c 可以依次单击 开始 运行 命令 xff0c 打开系统运行对话框 xff0c 并在其中输入字符串命令 cmd xff0c 单击 确定 按钮后
  • 嵌入式安卓项目笔记

    前言 xff1a 时间2021年7月电子科大人文交流月课程 嵌入式安卓系统开发 的大作业 项目描述 基于VM虚拟机Ubuntu 18 04 参考老师所给的suspendmonitor例程 xff0c 实现USB插拔监控驱动 43 APP用户
  • (一)DSP28335

    前言 xff1a 用于记录一些在学习实验室48V无人机项目所用的DSP28335时的一些心得体会 xff0c 主要参考资料是普中科技的那个资料手册 1 通信相关 区分开串口通信与串行通信 xff0c 串口通信 xff08 Serial Co
  • arm中的程序计数器PC

    在cpu中 xff0c 一条指令的执行简单的划分为 xff1a 取指 译码 执行 xff0c 三个部分 pc中存放的是下一条将要 执行 的指令的地址 xff0c 这里的执行并不是取指 译码 执行中的第三个步骤 xff0c 而是指的将存放于内
  • 韦东山第一期课程内容概要

    韦东山第一期课程内容概要 1一个嵌入式程序要运行所需的东西1 1第一条指令 b reset1 2 reset要完成的事件1 2 1设置开门狗1 2 2设置时钟1 2 3判断启动方式并设置堆栈1 2 4代码重定位 1 3执行main函数 12
  • 韦东山第一二期衔接课程内容概要

    韦东山第一二期衔接课程内容概要 0 使得一个裸板Jz2440能运行linux应用程序的过程1 uboot启动内核总结1 1 u boot分析之编译体验1 2 u boot分析之Makefile结构分析1 3 u boot分析之源码第一阶段1
  • 嵌入式总线与通信

    嵌入式总线与通信 I2C通信I2C通信的特点I2C通信协议I2C硬件连接I2C在一条数据线SDA上如何实现双向传输 xff1f xff08 如何实现半双工 xff09 SOC上的I2C通用硬件接口I2C接口与接口之间的连接I2C设备在整个A
  • jquery为动态dom元素绑定点击事件(比如动态生成的表格)

    js为动态dom元素绑定点击事件 需要给页面动态加载还未出现的元素添加事件时 xff0c 可以用jQuery的on xff0c live xff0c delegate来绑定事件 叫做委派事件 比如控制的动态生成的表格 xff0c 给一列中的
  • 嵌入式Arm+Linux中断与异常全流程讲解

    嵌入式ARM 43 Linux中断全流程讲解 ARM处理器级别的中断 异常 ARM的异常类型CPU如何检测到异常信息 进入异常处理后怎么返回前置知识 xff1a 流水线 xff0c 指令周期 xff0c 机器周期 xff0c 时钟周期复位