Cortex-A7中断详解(二)

news2024/12/28 5:03:04

CP15协处理器

CP15协处理器一般用于存储系统管理,但是在中断中也会使用到,CP15协处理器一共有16个32位寄存器。CP15协处理器的访问通过以下指令完成:

  • MRC:将CP15协处理器中的寄存器数据读到ARM寄存器中。
  • MCR:将ARM寄存器的数据写入到CP15协处理器寄存器中。
  • MCR{cond} p15, , , , ,
  • cond:指令执行的条件码,如果忽略的话就表示无条件执行。
  • opcl:协处理器要执行的操作码
  • Rt:ARM源寄存器,要写到CP15寄存器的数据就保存到此寄存器中。
  • CRn:CP15协处理器的目标寄存器。
  • CRm:协处理器中附加的目标寄存器或者源操作数寄存器,如果不需要附加信息就将CRm设置为C0,否则结果不可预测。
  • opc2:可选的协处理器特定操作码,当不需要的时候要设置为 0。

IRQ和FIQ总中断使能

IRQ 和 FIQ 分别是外部中断和快速中断的总开关,就类似家里买的进户总电闸,然后ID0~ID1019 这 1020 个中断源就类似家里面的各个电器开关。要想开电视,那肯定要保证进户总电闸是打开的,因此要想使用 I.MX6U 上的外设中断就必须先打开 IRQ 中断。
寄存器 CPSR 的 I=1 禁止 IRQ,当 I=0 使能 IRQ;F=1 禁止 FIQ,F=0 使能 FIQ。
我们还有更简单的指令来完成 IRQ 或者 FIQ 的使能和禁止:

在这里插入图片描述

ID0~ID1019中断使能和禁止

GIC寄存器GICD_ISENABLERn和GICD_ICENABLERn用来完成外部中断的使能和禁止,对于Coretex-A7内核来说中断ID只使用了512个。一个bit控制一个中断ID的使能,那么就需要512/32=16个GICD_ISENABLER 寄存器来完成中断的使能。同理,也需要 16 个
GICD_ICENABLER 寄存器来完成中断的禁止。

其中GICD_ISENABLER0的bit[15:0]对于ID150的SGI中断,GICD_ISENABLER0的bit[31:16]对应ID3116的PPI中断。剩下的
GICD_ISENABLER1~GICD_ISENABLER15 就是控制 SPI 中断的。

中断优先级设置

Cortex-M的中断优先级分为抢占优先级和子优先级,两者是可以配置的。同样的 Cortex-A7 的中断优先级也可以分为抢占优先级和子优先级,两者同样是可以配置的。

数字越小,优先级越高!
Cortex-A7选择了32个优先级,在使用中断的时候需要初始化GICC_PMR寄存器,此寄存器用来决定使用几级优先级。
在这里插入图片描述
GICC_PMR 寄存器只有低 8 位有效,这 8 位最多可以设置 256 个优先级。
在这里插入图片描述
I.MX6U 是 Cortex-A7内核,所以支持 32 个优先级,因此 GICC_PMR 要设置为 0b11111000。

抢占优先级和子优先级各占多少位是由寄存器 GICC_BPR 来决定的。
在这里插入图片描述
在这里插入图片描述
某个中断ID的中断优先级设置由寄存器D_IPRIORITY来完成,前面说了Cortex-A7使用了512个中断ID,每个中断ID配有一个优先级寄存器,所以一共有512 个 D_IPRIORITYR 寄存器。
当优先级个数为3时,使用寄存器 D_IPRIORITYR 的 bit7:4 来设置优先级,也就是说实际的优先级要左移 3 位。

因此,优先级设置主要有三部分:

  1. 设置寄存器GICC_PMR,配置优先级个数,比如I.MX6U支持32级优先级。
  2. 设置抢占优先级和子优先级位数,一般为了简单起见,会将所有的位数都设置为抢占优先级。
  3. 设置指定中断 ID 的优先级,也就是设置外设优先级。

重新编写start.S文件

/* 复位中断 */	

Reset_Handler:



	cpsid i						/* 关闭全局中断 */



	/* 关闭I,DCache和MMU 

	 * 采取读-改-写的方式。

	 */

	mrc     p15, 0, r0, c1, c0, 0     /* 读取CP15的C1寄存器到R0中       		        	*/

    bic     r0,  r0, #(0x1 << 12)     /* 清除C1寄存器的bit12位(I位),关闭I Cache            	*/

    bic     r0,  r0, #(0x1 <<  2)     /* 清除C1寄存器的bit2(C位),关闭D Cache    				*/

    bic     r0,  r0, #0x2             /* 清除C1寄存器的bit1(A位),关闭对齐						*/

    bic     r0,  r0, #(0x1 << 11)     /* 清除C1寄存器的bit11(Z位),关闭分支预测					*/

    bic     r0,  r0, #0x1             /* 清除C1寄存器的bit0(M位),关闭MMU				       	*/

    mcr     p15, 0, r0, c1, c0, 0     /* 将r0寄存器中的值写入到CP15的C1寄存器中	 				*/



	

#if 0

	/* 汇编版本设置中断向量表偏移 */

	ldr r0, =0X87800000



	dsb

	isb

	mcr p15, 0, r0, c12, c0, 0

	dsb

	isb

#endif

    

	/* 设置各个模式下的栈指针,

	 * 注意:IMX6UL的堆栈是向下增长的!

	 * 堆栈指针地址一定要是4字节地址对齐的!!!

	 * DDR范围:0X80000000~0X9FFFFFFF

	 */

	/* 进入IRQ模式 */

	mrs r0, cpsr

	bic r0, r0, #0x1f 	/* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 	*/

	orr r0, r0, #0x12 	/* r0或上0x13,表示使用IRQ模式					*/

	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中 					*/

	ldr sp, =0x80600000	/* 设置IRQ模式下的栈首地址为0X80600000,大小为2MB */



	/* 进入SYS模式 */

	mrs r0, cpsr

	bic r0, r0, #0x1f 	/* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 	*/

	orr r0, r0, #0x1f 	/* r0或上0x13,表示使用SYS模式					*/

	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中 					*/

	ldr sp, =0x80400000	/* 设置SYS模式下的栈首地址为0X80400000,大小为2MB */



	/* 进入SVC模式 */

	mrs r0, cpsr

	bic r0, r0, #0x1f 	/* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 	*/

	orr r0, r0, #0x13 	/* r0或上0x13,表示使用SVC模式					*/

	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中 					*/

	ldr sp, =0X80200000	/* 设置SVC模式下的栈首地址为0X80200000,大小为2MB */



	cpsie i				/* 打开全局中断 */

#if 0

	/* 使能IRQ中断 */

	mrs r0, cpsr		/* 读取cpsr寄存器值到r0中 			*/

	bic r0, r0, #0x80	/* 将r0寄存器中bit7清零,也就是CPSR中的I位清零,表示允许IRQ中断 */

	msr cpsr, r0		/* 将r0重新写入到cpsr中 			*/

#endif



	b main				/* 跳转到main函数 			 	*/
  • 先调用指令cpsid i关闭IRQ
  • 关闭I/D Cache、MMU、对齐检测和分支预测
  • 汇编版本的中断向量表重映射
  • 设置不同模式下的sp指针,分别设置IRQ模式、SYS模式和SVC模式的栈指针,每种模式的栈大小都是2MB
  • cpsie i重新打开IRQ中断
  • 操作CPSR寄存器打开IRQ中断
  • 当初始化工作都完成以后就可以进入main函数了。
IRQ_Handler:

	push {lr}					/* 保存lr地址 */

	push {r0-r3, r12}			/* 保存r0-r3,r12寄存器 */



	mrs r0, spsr				/* 读取spsr寄存器 */

	push {r0}					/* 保存spsr寄存器 */



	mrc p15, 4, r1, c15, c0, 0 /* 从CP15的C0寄存器内的值到R1寄存器中

								* 参考文档ARM Cortex-A(armV7)编程手册V4.0.pdf P49

								* Cortex-A7 Technical ReferenceManua.pdf P68 P138

								*/							

	add r1, r1, #0X2000			/* GIC基地址加0X2000,也就是GIC的CPU接口端基地址 */

	ldr r0, [r1, #0XC]			/* GIC的CPU接口端基地址加0X0C就是GICC_IAR寄存器,

								 * GICC_IAR寄存器保存这当前发生中断的中断号,我们要根据

								 * 这个中断号来绝对调用哪个中断服务函数

								 */

	push {r0, r1}				/* 保存r0,r1 */

	

	cps #0x13					/* 进入SVC模式,允许其他中断再次进去 */

	

	push {lr}					/* 保存SVC模式的lr寄存器 */

	ldr r2, =system_irqhandler	/* 加载C语言中断处理函数到r2寄存器中*/

	blx r2						/* 运行C语言中断处理函数,带有一个参数,保存在R0寄存器中 */



	pop {lr}					/* 执行完C语言中断服务函数,lr出栈 */

	cps #0x12					/* 进入IRQ模式 */

	pop {r0, r1}				

	str r0, [r1, #0X10]			/* 中断执行完成,写EOIR */



	pop {r0}						

	msr spsr_cxsf, r0			/* 恢复spsr */



	pop {r0-r3, r12}			/* r0-r3,r12出栈 */

	pop {lr}					/* lr出栈 */

	subs pc, lr, #4				/* 将lr-4赋给pc */

	
  • 保存现场
  • 获取当前中断号,中断号被保存到了r0寄存器
  • 调用函数system_irqhandler,此函数是一个C语言函数,此函数有一个参数为中断号,形参可以由r0~r3这四个寄存器来传递,所以给r0寄存器写入中断号就可以解决函数system_irqhandler参数传递问题。
  • 向GICC_EOIR寄存器写入刚刚处理完成的中断号,当一个中断处理完成以后必须向GICC_EOIR寄存器写入其中断号表示中断处理完成。
  • 恢复现场。
  • 中断处理完成后就要重新返回曾经被中断打断的地方运行。

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

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

相关文章

坚持刷题2个月,终于去了梦寐以求的大厂....

写在前面 最近一个读者和我反馈&#xff0c;他坚持刷题2个月&#xff0c;终于去了他梦寐以求的大厂&#xff0c;薪资涨幅非常可观&#xff0c;期间面字节跳动还遇到了原题…并表示目前国内的大厂和一些独角兽&#xff0c;已经越来越效仿硅谷公司的做法&#xff0c;通过面试给定…

软件测试的测试用例

1.白盒和黑盒测试: 黑盒测试&#xff1a;把代码看成一个黑盒子&#xff0c;只关心输入和输出结果之间的关系 产品功能是否符合要求&#xff1b; 白盒测试&#xff1a;能够看到代码本身&#xff0c;针对代码本身进行测试&#xff0c;测试代码本身的逻辑是否符合规范。 2.测试用…

常用图标(icon)css下载

1、演示图例&#xff08;icon1.css&#xff09;[24*18] 2、演示图例&#xff08;icon2.css&#xff09;[24*24] 3、演示图例&#xff08;icon3.css&#xff09;[24*24] 4、演示图例&#xff08;icon4.css&#xff09;[24*18] 5、演示图例&#xff08;icon5.css&#xff09;[26*…

C/C++每日一练(20230426)

目录 1. 不喜欢带钱的小C &#x1f31f;&#x1f31f; 2. 数组排序 ※ 3. 超级素数 ※ &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Python每日一练 专栏 C/C每日一练 专栏 Java每日一练 专栏 1. 不喜欢带钱的小C 小C不喜欢带钱&#xff0c…

linux 安装zsh shell工具

安装zsh sudo apt install zsh chsh -s /bin/zsh sh -c "$(curl -fsSL https://raw.github.com/robbyrussell/oh-my-zsh/master/tools/install.sh)" 这一步需要网络状态比较好 ~$ git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf ~$ ~/.fzf/i…

USB2.0、USB3.0和typec引脚定义

USB2.0 USB 2 (Type A) pinout PinNameDirectionColorDescription1Vred5 V power2D-←→whiteData -3D←→greenData 4GNDblackGround USB 2 (Type B) pinout PinNameDirectionColorDescription1Vred5 V power2D-←→whiteData -3D←→greenData 4GNDblackGround USB Mini/M…

输入 jupyter notebook 报错 ModuleNotFoundError: No module named ‘pysqlite2‘ 解决方案

今天在cmd命令行中输入jupyter notebook想要打开jupyter时&#xff0c;出现了以下问题&#xff1a;即找不到模块‘pysqlite2’。 找到出问题的文件“sessionmanager.py”&#xff0c;发现出问题的地方在于&#xff1a;尝试导入sqlite3没有导致失败 因此&#xff0c;以下是解决…

HCIA-RS实验-ENSP设备的基础配置

本文主要简单地介绍ENSP设备的基础配置&#xff0c;帮助读者快速上手使用ENSP。可以掌握一些基础的配置方案&#xff0c;更改名称&#xff0c;系统时间&#xff0c;系统地区、密码登录等信息 以下是该文章的拓扑图&#xff1b;现将这2台设备启动&#xff1b;后续双击即可进入命…

mac软件卸载不干净怎么回事 mac如何卸载软件干净

很多苹果用户会发现&#xff0c;mac卸载软件不干净。明明是早都卸载的软件还能看到那些软件的图标和残留文件夹。mac软件卸载不干净怎么回事&#xff1f;mac如何卸载软件干净&#xff1f;今天小编就来教大家如何将软件彻底卸载&#xff0c;保证电脑磁盘的干净。 一、mac软件卸…

“分布式基础概念”全面解析,让你秒懂分布式系统!【一】

前言 在项目中学习这些技术、加深了对其的使用和深层次的理解。以下总结来自谷粒商城项目案例资料 1、什么是微服务&#xff1f; 微服务架构风格&#xff0c;就像是把一个单独的应用程序开发为一套小服务&#xff0c;每个小服务运行在自己的进程中&#xff0c;并使用轻量级机…

Nacos单机搭建并集成项目

Nacos概述 Nacos Nacos是阿里巴巴开源的服务注册中心及配置中心&#xff0c;致力于给开发者提供一款便捷、简单上手的开源框架 Nacos注册中心Eureka 服务配置Config 服务总线Bus 服务发现和服务健康监测 Nacos 使服务更容易注册&#xff0c;并通过DNS或HTTP接口发现其他…

Flutter集成个推推送-安卓原生篇

前言 在众多的集成化推送中选择了个推&#xff0c;个推在flutter集成中还是比较简单的&#xff0c;只需要跟着官网一步一步走就可以了。今天这篇文章不涉及到flutter项目个推的集成&#xff0c;只是记录个推离线走安卓厂商时&#xff0c;进行获取一个离线的点击通知数据。 在…

ChatGPT APIs for HCL DOMINO

大家好&#xff0c;才是真的好。 近期网络上最热闹的话题就是OpenAI的ChatGPT&#xff0c;从去年11月份到现在&#xff0c;一波又一波热潮蜂拥而至&#xff0c;以至于让我们Domino人应接不暇。 ChatGPT和Domino的缘分还真不是完全没有&#xff0c;毕竟刚出来时&#xff0c;很…

Redis(09)centos8下载安装最新redis

redis下载安装 1. 安装make构建工具2. 下载Redis源码包3. 解压源码包并编译4. 配置环境变量5. 注册系统服务6. 设置可远程访问7.防火墙配置: 1. 安装make构建工具 Redis是采用C语言开发的需要编译安装。make是一种自动化编译工具,可以自动编译Redis源代码。 yum install make…

40岁高中老师开源的数据集LAION,改变了生成式AI的未来丨智源大会嘉宾风采

导读 如今&#xff0c;拥有超过50亿个图文对的 LAION数据集已经成为生成式AI未来的中心ーー而随之而来的关于如何监管人工智能的争论也日益激烈。 在德国北部城市汉堡郊区的一栋房屋前&#xff0c;一个信箱上用铅笔潦草地写着一个单词——“ LAION”。这唯一的记号表明&#xf…

jupyter notebook 打开指定文件路径

1 按住winR键&#xff0c;开打运行界面 winR 2 在运行界面输入cmd,进入控制命令行窗口 cmd 4 激活conda环境 conda activate 5 输入要打开的指定路径 #c:\Users\test为要打开的指定路径&#xff0c;用户按需修改即可jupyter notebook c:\Users\test 正常来说&#xff0c;输…

服务注册于发现-Consul

Consul是HashiCorp公司推出的开源工具&#xff0c;用于实现分布式系统的服务发现与配置。 Consul是分布式的、高可用的、可横向扩展的。它具备以下特性 : 服务发现&#xff1a;consul通过DNS或者HTTP接口使服务注册和服务发现变的很容易&#xff0c;一些外部服务&#xff0c;例…

佳能驱动支持,佳能打印机驱动无法安装的解决方法

随着打印机设备的普及&#xff0c;不少用户都会选购一台佳能、惠普、爱普生、兄弟等品牌的打印机&#xff0c;虽然安装打印机及打印机驱动并不难&#xff0c;但也会出现无法安装的情况&#xff0c;只有打印机驱动安装好了才能正常使用佳能打印机设备。以佳能打印机为例&#xf…

关于Vue3刷新页面报错404的解决方法

最近正在写VUE3项目时&#xff0c;遇到了一个问题&#xff0c;页面一刷新就出错。 如下&#xff1a; 查看控制台报错信息是404。 这时候怎么刷新页面都没有用&#xff0c;只能重新输入地址&#xff0c;一想到每次代码发生改变我都要输入一遍地址&#xff0c;那心情都不好了。在…

MongoDB管理神器来袭!NexNoSqlClient让你的效率翻倍!

背景&#xff1a; 如果你在日常工作中需要经常使用MongoDB&#xff0c;那么你一定体验过这样一些痛点;繁琐的脚本编写&#xff0c;冗长的命令行操作&#xff0c;复杂的数据建模和索引等等。这些问题不仅让我们的工作效率低下&#xff0c;还容易出现错误和漏洞&#xff0c;给数…