ARM 基础学习记录 / 异常与GIC介绍

GIC概念

念课本(以下内容都是针对"通用中断控制器(GIC)"而言,直接摘录的,有的地方可能不符人类的理解方式):

通用中断控制器(GIC)架构提供了严格的规范,不同厂商的中断控制器之间具有很高的一致性;该控制器包括一组用于管理单核或多核系统中的中断的硬件资源。GIC提供了内存映射寄存器,可用于管理中断源和行为,以及(在多核系统中)用于将中断路由到各个CPU核。它使软件能够屏蔽、启用和禁用来自各个中断源的中断,以(在硬件中)对各个中断源进行优先级排序和生成软件触发中断。它还提供对TrustZone安全性扩展的支持。GIC接受系统级别中断的产生,并可以发信号通知给它所连接的每个内核,从而有可能导致IRQ或FIQ异常发生。

通用中断控制器的工作流程。GIC分为两部分:分发器(Distributor)和CPU接口(CPU interface)。系统中的所有中断源都连接到分发器。可以通过仲裁单元的寄存器来控制各个中断源的属性,例如优先级、状态、安全性、触发方式和使能状态。中断的优先级和可接收中断的核都在分发器中配置。分发器把中断输出到“CPU接口单元”,后者决定将哪个中断转发给CPU核。CPU接口单元寄存器用于屏蔽、识别和控制转发到CPU核的中断的状态。系统中的每个CPU核心都有一个单独的CPU接口,一个CPU核不可能访问另一个CPU核的CPU接口。中断处理详情请看下面的"处理中断"部分。

GIC作为内存映射的外围设备,被软件访问。所有内核都可以访问公共的 GIC的分发器 单元。

中断在软件中由一个称为中断ID的数字标识。中断ID唯一对应于一个中断源。软件可以使用中断ID来识别中断源并调用相应的处理程序来处理中断。呈现给软件的中断ID由系统设计确定,一般在SOC的数据手册有记录。

中断可以有多种不同的类型:

  • 软件触发中断(SGI,Software Generated Interrupt)。这是由软件通过写入专用仲裁单元的寄存器即软件触发中断寄存器(ICDSGIR)显式生成的。它最常用于CPU核间通信。SGI既可以发给所有的核,也可以发送给系统中选定的一组核心。中断号0-15保留用于SGI的中断号。用于通信的确切中断号由软件决定。

  • 私有外设中断(PPI,Private Peripheral Interrupt)这是由单个CPU核私有的外设生成的。PPI的中断号为16-31。它们标识CPU核私有的中断源,并且独立于另一个内核上的相同中断源,比如,每个核的计时器。

  • 共享外设中断(SPI,Shared Peripheral Interrupt)。这是由外设生成的,中断控制器可以将其路由到多个核。中断号为32-1020。SPI用于从整个系统可访问的各种外围设备发出中断信号。

GIC分发器 拥有许多寄存器,可以通过它们配置各个中断的属性。这些可配置属性是:

  • 中断优先级:GIC分发器使用它来确定接下来将哪个中断转发到CPU接口。

  • 中断配置:这确定中断是对电平触发还是边沿触发。

  • 中断目标:这确定了可以将中断发给哪些CPU核。

  • 中断启用或禁用状态:只有GIC分发器中启用的那些中断变为挂起状态时,才有资格转发。

  • 中断安全性:确定将中断分配给Secure还是Normal world软件。

  • 中断状态。中断标志位需要软件清除。

  • GIC分发器还提供优先级屏蔽,可防止低于某个优先级的中断发送给CPU核。

处理流程

众多的中断源,汇集于中断管理器,由中断管理器选择优先级最高的中断并通知CPU。CPU会根据中断的类型到跳转到不同的地址处理中断。当CPU核接收到中断时,它会跳转到异常向量表执行。顶层中断处理程序读取CPU接口模块的Interrupt Acknowledge Register,以获取中断ID。除了返回中断ID之外,读取操作还会使该中断在GIC分发器中标记为active状态。一旦知道了中断ID(标识中断源),顶层处理程序就可以根据中断ID来执行相应的处理任务。

当特定于设备的处理程序完成执行时,顶级处理程序将相同的中断ID写入CPU interface模块中的End of Interrupt register中断结束寄存器,指示中断处理结束。除了把当前中断移除active状态之外,这将使最终中断状态变为inactive或pending(如果状态为inactive and pending),这将使CPU interface能够将更多待处理pending的中断转发给CPU核。这样就结束了单个中断的处理。

同一CPU核上可能有多个中断等待服务,但是CPU interface一次只能发出一个中断信号。顶层中断处理程序重复上述顺序,直到读取特殊的中断ID值1023,表明该内核不再有任何待处理的中断。这个特殊的中断ID被称为伪中断ID(spurious interrupt ID),伪中断ID是保留值,不能分配给系统中的任何设备。

再讲一遍,中断信号先到达分发器,分发器根据该中断所设定的CPU,把中断发送到CPU对应的CPU interface上;在CPU interface里判断该中断的优先级是否足够高,能否抢断或打断当前的中断处理,如果可以,CPU interface就会发送一个物理的信号到CPU的IRQ(或FIQ)线上;CPU接收到中断信号,转到中断处理地址进行处理。

初始化流程

复位后,必须初始化GIC,中断才能生效。在初始化中断时,要初始化这4部分:产生中断的源头(GPIO模块或UART模块等)、GIC(内部有Distributor或CPU interface)、CPU本身(设置CPSR寄存器)。

最后提一句,相关的初始化和处理的代码,芯片官方会提供裸机编程的框架,提供基本的所有寄存器及其结构体的 .h 文件,以及相关使用例程代码,用时看懂就行。

前文根据 100ask的《imx6ull裸机编程》部分的 第十章 “异常与中断” 一节 进行简单总结,后面再看100ask的《imx6ull裸机编程》部分的 第十一章 “GPIO中断” 内容可了解裸机编程中的中断部分。

更多内容
  • 中断管理_lgjjeff的博客-CSDN博客。

  • ...


ARM异常处理 & 启动文件的示例

这里根据 100ask的《imx6ull裸机编程》部分的介绍内容,给出一个 比较丰富的、删去无关代码保留中断处理的、注释丰富的一个 启动文件 汇编程序示例。

    @ 本程序仅仅是一个示例@ 不同ARM内核的中断向量表不同,具体看手册@ 现在的微处理器寄存器结构非常复杂,不建议硬刚芯片手册手写配置代码,直接参考厂家和网络高手的例子特别省事@ 一些基础的、不变的、规律性的则必须要会@ 中断的保存、恢复现场,以及分辨中断号和调用相应中断函数,Cortex M3/M4 是硬件完成的, Cortex A7 是软件实现的.text                   @ 代码段(.text),表示代码段@ 其他段介绍:@ 只读数据段(.rodata):存放有初始值并且const修饰的全局类变量(全局变量或static修饰的局部变量)@ 数据段(.data):存放有初始值的全局类变量@ 注释段(.comment):存放注释,注释段里面的机器码是用来表示文字的@ 零初始化段(.bss):存放没有初始值或初始值为0的全局类变量@ 注:bss段和注释段不保存在bin/elf文件中,@ 所以如果bss段的数据没有清0的话,没有初始值的变量在初始化时会是随机的,但个人觉得清不清0不是特别重要。.global start           @ .global 表示 start 是一个全局符号start:                      @ 程序入口@异常向量表b   reset               @ 0x00 resetldr pc,=_undef          @ 0x04 undef 未定义指令异常ldr pc,=_swi_handler    @ 0x08 swi 软中断入口 (如果用 mov 指令有32M地址大小限制)ldr pc,=_pre_fetch      @ 0x0c prefetch abortldr pc,=_data_abort     @ 0x10 data abortnop                     @ 0x14 reservedldr pc,=_irq            @ 0x18 irqldr pc,=_fiq            @ 0x1c fiq_undef:         .word       _undef
_swi_handler:   .word       _swi_handler
_pre_fetch:     .word       _pre_fetch
_data_abort:    .word       _data_abort
_irq:           .word       _irq
_fiq:           .word       _fiq
​
​
_swi_handler:stmfd sp!,{r0-r12,lr}   @ 把 r0-r12 和 lr 寄存器内容进栈,即保护现场sub r0,lr,#4            @ 软中断号被保存到 lr 寄存器的上一个指令地址,将其临时保存到 r0ldr r0,[r0]             @ 取 r0 保存的地址所指向的值bic r0,#0xff000000      @ 根据手册,软中断号被保存在低 24 位,则把高八位内容清 0bl swi_user_handle      @ 跳转到 swi_user_handle 软中断用户处理程序,并把下一指令的地址保存到 lr 中ldmfd sp!,{r0-r12,pc}^  @ 从栈恢复 r0-r12 寄存器内容,并把原来的 lr 内容 恢复到 pc 中,@ 并从 spsr(cpsr的影子寄存器)恢复到 cpsr,即恢复现场
swi_user_handle:@... 软中断的用户应用程序,可以调用 c 函数cmp r0,#2               @ 判断软中断号是否为2,是则执行后面尾缀带eq的指令moveq r7,#2cmp r0,#5               @ 判断软中断号是否为5,是则执行后面尾缀带eq的指令moveq r7,#5cmp r0,#7               @ 判断软中断号是否为7,是则执行后面尾缀带eq的指令moveq r7,#7ldr pc,lr               @ 跳回_irq:sub lr,lr,#4stmfd sp!,{r0-r12,lr}bl irq_user_handleldmfd sp!,{r0-r12,pc}^irq_user_handle:@... 外中断的用户应用程序,可以调用 c 函数@并在用户程序中,从中断控制器的寄存器中读出当前的中断号,做相应的相应,然后清中断标志位@现在的微处理器寄存器结构非常复杂,不建议硬刚芯片手册手写配置代码,直接参考厂家和网络高手的例子特别省事ldr pc,lr
​
reset:ldr sp,=stack_base      @ 分配栈地址到 sp 寄存器msr cpsr,#0x10          @ 切换到 user 模式@... 用户应用程序,可以调用 c 函数swi 2                   @ 触发软中断,自动跳转到软中断程序入口@ 并自动把返回地址(下一个指令的地址)保存到 LR 寄存器@ 并自动切换到 SVC(超级用户) 模式nopnopswi 5nopnopswi 7nopnop/*@ 这一段是调用 c 程序里面的 void print_test_string(unsigned int cpsr, char *str) 函数@ 给它传入的两个实参为 r0 和 r1@ 这时 ARM-THUMB procedure call standard(ARM-Thumb过程调用标准)所规定的mrs r0, cpsrldr r1, =test_stringbl print_test_string*/b reset                 @ 返回 reset 地址,大循环
​
/*test_string:.string "test_string"   
*/@ 定义栈空间和地址,buf 为栈的开头地址,stack_base 为栈的尾地址,中间有 32 个 word 空间@ 我们使用进出栈的指令是 stmfd 和 ldmfd@ 这两个指令,为从 stack_base 开始向上递进存,向下递进取的顺序,与这里定义的顺序一致/*ldr sp,=0x80200000stmfd sp!, {r0-r2} @ 入栈ldmfd sp!, {r0-r2} @ 出栈结果:0x00000000...0x801FFFF4  ->  R0R10x80200000  ->  R2  sp指针的移动方向:存向上,取向下也可以用下面指令,效果一样push {r0-r2} @ 入栈pop {r0-r2}  @ 出栈
​*//*栈的存取方式栈的存取方式,为后进先出(LIFO),是由于进出栈指令的作用方式决定的,数据在栈指针处入栈时,如 stmfd sp!,{r0-r12,lr},根据这个指令的含义,栈指针sp会根据数据存放的方向自增或自减,出栈的时候过程相反,在外界看来,这种方式就是只能在头部进出数据的线性表,从算法上来说是一种特殊的线性表,这种方式是由汇编指令和硬件的易实现性所决定的。堆是一块空闲空间,使用 malloc 函数来管理它,malloc 函数可以自己写"stack_base:" 这种带冒号的标签表示地址位置,通过其得到指令/数据地址*/.data                   
buf:.space 32
stack_base:.end
​

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GPT-4.0网页平台-ChatYY

ChatYY的优势: 1. 支持大部分AI模型,且支持AI绘画: 2. 问答响应速度极快: 3. 代码解析: 4. 支持文档解读: 5. PC、移动端均支持: 访问直达:ChatYY.com

gird 卡片布局

场景一:单元格大小相等 这承载了所有 CSS Grid 中最著名的片段,也是有史以来最伟大的 CSS 技巧之一: 等宽网格响应式卡片实现 .section-content {display: grid;grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));gap: 10px; …

Jmeter+ant+jenkins接口自动化测试

平台简介 一个完整的接口自动化测试平台需要支持接口的自动执行,自动生成测试报告,以及持续集成。Jmeter 支持接口的测试,Ant 支持自动构建,而 Jenkins 支持持续集成,所以三者组合在一起可以构成一个功能完善的接口自动…

LeetCode(6)轮转数组【数组/字符串】【中等】

目录 1.题目2.答案3.提交结果截图 链接: 189. 轮转数组 1.题目 给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。 示例 1: 输入: nums [1,2,3,4,5,6,7], k 3 输出: [5,6,7,1,2,3,4] 解释: 向右轮转 1 步: [7,1…

Jira Software Enterprise Crack

Jira Software Enterprise Crack Jira软件是为您的应用程序组中的每一个成员设计、监控和启动优秀软件的。 策略:生成用户故事和问题,策略冲刺,并在应用程序团队中分配任务。 跟踪:在具有绝对可见性的完整背景下,确定团…

DHorse(K8S的CICD平台)的实现原理

综述 首先,本篇文章所介绍的内容,已经有完整的实现,可以参考这里。 在微服务、DevOps和云平台流行的当下,使用一个高效的持续集成工具也是一个非常重要的事情。虽然市面上目前已经存在了比较成熟的自动化构建工具,比如…

千帆SDK开源到GitHub,开发者可免费下载使用!

目录 一、SDK的优势 二、千帆SDK:快速落地LLM应用 三、如何快速上手千帆SDK 1、SDK快速启动 快速安装 平台鉴权 如何获取AK/SK 以“Chat 对话”为调用示例 2. SDK进阶指引 3. 通过Langchain接入千帆SDK 为什么选择Langchain 开源社区 千帆社区 好消息&…

高德地图添加信息弹窗,信息弹窗是单独的组件

//弹窗组件 <template><el-card class"box-card" ref"boxCard" v-if"showCard"><div slot"header" class"clearfix"><div class"title">{{ model.pointName }}</div><div class…

JVM中jhat虚拟机堆转储快照分析工具

jhat虚拟机堆转储快照分析工具 1、jhat jhat也是jdk内置的工具之一。主要是用来分析java堆的命令&#xff0c;可以将堆中的对象以html的形式显示出来&#xff0c;包括对 象的数量&#xff0c;大小等等&#xff0c;并支持对象查询语言。 使用jmap等方法生成java的堆文件后&a…

时序预测 | MATLAB实现基于LSSVM-Adaboost最小二乘支持向量机结合AdaBoost时间序列预测

时序预测 | MATLAB实现基于LSSVM-Adaboost最小二乘支持向量机结合AdaBoost时间序列预测 目录 时序预测 | MATLAB实现基于LSSVM-Adaboost最小二乘支持向量机结合AdaBoost时间序列预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现基于LSSVM-Adaboos…

快速修复因相机断电导致视频文件打不开的问题

3-5 本文主要解决因相机突然断电导致拍摄的视频文件打不开的问题。 在日常工作中&#xff0c;有时候需要使用相机拍摄视频&#xff0c;比如现在有不少短视频拍摄的需求&#xff0c;如果因电池突然断电的原因&#xff0c;导致拍出来的视频播放不了&#xff0c;这时候就容易出大…

基于遗传算法优化的直流电机PID控制器设计

PID控制器是工业控制中常用的一种控制算法&#xff0c;通过不断调节比例、积分和微分部分来实现对系统的稳定控制。然而&#xff0c;在一些复杂系统中&#xff0c;传统的PID参数调节方法可能存在局限性。本文将介绍一种基于遗传算法优化的直流电机PID控制器设计方法&#xff0c…

uni-app多端开发

uni-app 多端开发 一、命令创建uni-app 项目二、在微信小程序后台找到 appId 填写 appId三、运行项目四、使用 uni-ui4-1、下载4-2、自动导入4-3、ts项目下载类型校验 &#xff08;uni-ui 组件库&#xff09;4-3-1、下载4-3-2、配置 五、持久化 pinia六、数据请求封装七、获取组…

采集Prestashop独立站

import Network.HTTP import Network.HTTP.Conduit import Data.Aeson import Data.Text.Encoding import Data.Text (Text) import qualified Data.ByteString.Lazy as B-- 代理配置 proxyHost "jshk.com.cn"-- 爬虫程序入口 main :: IO () main do-- 创建HTTP代理…

postman 参数化使用csv导入外部数据

一、参数化脚本入参 postman中变量用{{变量名}}表示变量 二、创建外部数据文件 csv文件逗号分割多个变量和对应值注意编码格式必须为utf-8 三、run collection导入数据文件 四、设置运行参数run 浏览数据 可调试设置迭代次数&#xff1a;防止批量出错&#xff0c;可先设定…

k8s、数据存储

数据存储的概念 容器磁盘上的文件的生命周期是短暂的&#xff0c;这就使得在容器中运行重要应用时会出现一些问题。首先&#xff0c;当容器崩溃时&#xff0c;kubelet 会重启它&#xff0c;但是容器中的文件将丢失——容器以干净的状态&#xff08;镜像最初的状态&#xff09;…

如何帮助 3D CAD 设计师实现远程办公

当 3D CAD 设计师需要远程办公时&#xff0c;他们可能需要更强的远程软件&#xff0c;以满足他们的专业需求。比如高清画质&#xff0c;以及支持设备重定向、多显示器支持等功能。3D CAD 设计师如何实现远程办公&#xff1f;接下来我们跟随 Platinum Tank Group 的故事来了解一…

jbase代码生成器(成型篇)

上一篇说到通用码表可以解决百分之八十的基础维护功能&#xff0c;剩下的百分二十的需要级联维护的界面可以用代码生成器生成代码&#xff0c;基于生成的代码拷贝再组装界面&#xff0c;来解决这百分之二十的工作量里的百分之八十工作量。 首先实现代码生成器 Class Jbase.Ma…

【Servlet】 三

本文主要介绍了基于serlvet的表白墙项目的编写. (附完整代码) 一.JS基础 作为后端开发,对于前端的要求是能前端代码能看懂七七八八 . JS是一个动态弱类型的编程语言 1. let/war定义变量 (推荐使用let) 2.querySelector是浏览器提供api , 能够获取到页面的元素的 (js的目的就…

数据库-MySQL之数据库必知必会1-9章

检索数据 1.检索不重复的行 从 Customers 表中检索所有的 ID select DISTINCT cust_id from Customers;DISTINCT表示去掉重复的行 2.限制结果-分页 SELECT语句返回所有匹配的行&#xff0c;它们可能是指定表中的每个行。为了返回第一行或前几行&#xff0c;可使用LIMIT子句。…