lv11 嵌入式开发 中断处理 15

news2025/2/27 23:23:38

前言:中断属于7种异常的1种,这节主要讲CPU接收到中断之后怎么处理,回顾之前的知识。

目录

1 异常

1.1 概念

1.2 异常处理机制 

1.3 ARM异常源

1.4 异常模式 

1.5 ARM异常响应

1.6 异常向量表

1.7 异常返回

​编辑 1.8 IRQ异常举例

2 中断处理框架搭建 

2.1 代码框架介绍

2.2 当中断信号来,ARM如何处理

2.2.1 以BL为例说明LR如何保存下一条指令的地址。

2.2.2 IRQ异常LR寄存器说明如何保存下一条地址指令。 

2.3 编写IRQ异常处理程序

3 补充


1 异常

1.1 概念

处理器在正常执行程序的过程中可能会遇到一些不正常的事件发生    

这时处理器就要将当前的程序暂停下来转而去处理这个异常的事件    

异常事件处理完成之后再返回到被异常打断的点继续执行程序

1.2 异常处理机制 

不同的处理器对异常的处理的流程大体相似,但是不同的处理器在具体实现的机制上有所不同;比如处理器遇到哪些事件认为是异常事件遇到异常事件之后处理器有哪些动作、处理器如何跳转到异常处理程序如何处理异常、处理完异常之后又如何返回到被打断的程序继续执行等我们将这些细节的实现称为处理器的异常处理机制

1.3 ARM异常源

导致异常产生的事件称为异常源

FIQ、IRQ作为外部中断,驱动IRQ用得较多,FIQ速度较快。

1.4 异常模式 

在ARM的基本工作模式中有5个属于异常模式,即ARM遇到异常后会切换成对应的异常模式

1.5 ARM异常响应

2.1中相应的中断的意思:高优先级的可以打断低优先级的,但是平级中断不能被打断

真正处理跳转在第4点,自动修改成了向量表对应的地址。 

1.6 异常向量表

 ARM的异常向量表的基地址默认在0x00地址,但可以通过配置协处理器来修改其地址,如基址修改为0x40000000,那么IRQ的地址对应0x40000018

1.7 异常返回

ARM异常返回的动作(自己编写)

 1.8 IRQ异常举例

2 中断处理框架搭建 

2.1 代码框架介绍

common中写得是头文件和源文件,包含.c和.s的可以调用,如exynos_4412.h是寄存器的封装

start中放得是启动代码start.s,启动的汇编代码

makefile用于编译规则

map.lds链接脚本,用于生成文件的排版和格式

最终编译所有.c、.s等组成了一个.bin的文件。所有.c .s的源文件的内容的排版由map.lds决定。

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
	. = 0x40008000;
	. = ALIGN(4);
	.text      :
	{
		start/start.o(.text)
		*(.text)
	}
	. = ALIGN(4);
    .rodata : 
	{ *(.rodata) }
    . = ALIGN(4);
    .data : 
	{ *(.data) }
    . = ALIGN(4);
    .bss :
    { *(.bss) }
}

协处理器cp15中有个寄存器c12,往里面写什么地址,异常向量表就在什么地址

r0已经存了start的地址,把r0给c12,当arm遇到异常时就会跳转到异常向量表

目前没有写跳转指令 b.代表跳转到自身,占用了32个字节。

详细内容参考往期内容:

lv11 嵌入式开发 C工程与寄存器封装 10-CSDN博客

2.2 当中断信号来,ARM如何处理

 回顾:

 ARM寄存器

注:在某个特定模式下只能使用当前模式下的寄存器,一个模式下特有的寄存器其他模式下不可使用 

LR寄存器两种用途:

2.2.1 以BL为例说明LR如何保存下一条指令的地址。

当正在执行BL ADDR指令的时候,BL指令的下一条指令正在译码(三级流水线)BL指令的下下条正在取址。PC寄存器指向的永远是在取址的指令,CPU会执行BL的时候,会把PC的值减4的地址拷贝到LR

2.2.2 IRQ异常LR寄存器说明如何保存下一条地址指令。 

2.3 编写IRQ异常处理程序

start.s

处理函数中做了几件事:

  • 修正LR返回地址
  • 压栈保护现场
  • 跳转异常处理程序
  • 恢复现场

处理跳转异常处理程序,只能使用汇编编写,因为C语言没有压栈出栈的操作函数

.text
.global _start
_start:
	/*
	 * Vector table
	 */ 
	b reset
	b .
	b .
	b .
	b .
	b .
	/*
	 * 从异常向量表再跳转到IRQ的异常处理程序
	 */
	b irq_handler
	b .

reset:
	/*
	 * Set vector address in CP15 VBAR register
	 */ 
	ldr	r0, =_start
	mcr	p15, 0, r0, c12, c0, 0	@Set VBAR

	/*
	 * Set the cpu to SVC32 mode, Disable FIQ/IRQ
	 */  
	mrs r0, cpsr
	bic r0, r0, #0x1f
	orr	r0, r0, #0xd3
	msr	cpsr ,r0

	/*
	 * Defines access permissions for each coprocessor
	 */  
    mov	r0, #0xfffffff
    mcr	p15, 0, r0, c1, c0, 2  	

	/*
	 * Invalidate L1 I/D                                                                                                                   
	 */
	mov	r0, #0					@Set up for MCR
	mcr	p15, 0, r0, c8, c7, 0	@Invalidate TLBs
	mcr	p15, 0, r0, c7, c5, 0	@Invalidate icache
	
	/*
	 * Set the FPEXC EN bit to enable the FPU
	 */ 
	mov r3, #0x40000000
	fmxr FPEXC, r3
	
	/*
	 * Disable MMU stuff and caches
	 */
	mrc	p15, 0, r0, c1, c0, 0
	bic	r0, r0, #0x00002000		@Clear bits 13 (--V-)
	bic	r0, r0, #0x00000007		@Clear bits 2:0 (-CAM)
	orr	r0, r0, #0x00001000		@Set bit 12 (---I) Icache
	orr	r0, r0, #0x00000002		@Set bit 1 (--A-) Align
	orr	r0, r0, #0x00000800		@Set bit 11 (Z---) BTB
	mcr	p15, 0, r0, c1, c0, 0

	/*
	 * Initialize stacks                                                                                                                  
	 */
init_stack:     
	/*svc mode stack*/
	msr cpsr, #0xd3
	ldr sp, _stack_svc_end

	/*undef mode stack*/
	msr cpsr, #0xdb
	ldr sp, _stack_und_end

	/*abort mode stack*/	
	msr cpsr,#0xd7
	ldr sp,_stack_abt_end

	/*irq mode stack*/	
	msr cpsr,#0xd2
	ldr sp, _stack_irq_end
	
	/*fiq mode stack*/
	msr cpsr,#0xd1
	ldr sp, _stack_fiq_end
	
	/*user mode stack, enable FIQ/IRQ*/
	msr cpsr,#0x10
	ldr sp, _stack_usr_end

	/*Call main*/
	b main

	/*
	 * IRQ的异常处理程序,需要写在main函数之后,否则就执行了。
	 */
irq_handler:
	/*
	 * 因为产生IRQ异常后ARM自动保存到LR中的返回地址是被IRQ打断的指令
     * 的下一条再下一条指令的地址,所以我们需要人为的去修正一下
	 */
	sub lr, lr, #4
	/*
	 * 因为IRQ模式下使用的R0-R12寄存器和USER模式下使用的是同一组
	 * 所以在处理异常之前需要先将之前寄存器中的值压栈保护
	 */
	stmfd sp!, {r0-r12,lr}
	/*
	 * 跳转到do_irq处理异常
	 */
	bl do_irq
	/*
	 * 异常返回
	 * 1.将R0-R12寄存器中的值出栈,使其恢复到被异常打断之前的值
	 * 2.将SPSR寄存器中的值恢复到CPSR,使CPU的状态恢复到被异常打断之前
	 * 3.将栈中保存的LR寄存器的值出栈给PC,使程序跳转回被异常打断的点继续执行
	 */
	ldmfd sp!,{r0-r12,pc}^

_stack_svc_end:      
	.word stack_svc + 512
_stack_und_end:      
	.word stack_und + 512
_stack_abt_end:      
	.word stack_abt + 512
_stack_irq_end:      
    .word stack_irq + 512
_stack_fiq_end:
    .word stack_fiq + 512
_stack_usr_end:      
    .word stack_usr + 512

.data
stack_svc:      
	.space 512
stack_und:
	.space 512
stack_abt:      
	.space 512
stack_irq:      
	.space 512
stack_fiq:      
	.space 512
stack_usr:      
	.space 512

编写do_irq

 获取中断号

诉中断控制器,当前中断已经处理完成,可以发送其他中断

#include "exynos_4412.h"

void Delay(unsigned int Time)
{
	while(Time--);
}

//IRQ异常处理
void do_irq(void)
{
	unsigned int IrqNum = 0;
	/*从中断控制器中获取当前中断的中断号,只需要10位*/
	IrqNum = CPU0.ICCIAR & 0x3FF;
	
	/*根据中断号处理不同的中断*/
	switch(IrqNum)
	{
		case 0:
			//0号中断的处理程序
			break;
		case 1:
			//1号中断的处理程序
			break;
			/*
			 * ... ...
			 */
		case 57:
			printf("Key2 Pressed\n");
			/*清除GPIO控制器中GPX1_1的中断挂起标志位,不清楚结束会跳转到main3然后再持续执行上面的中断处理函数*/
			EXT_INT41_PEND = (1 << 1);
			/*将当前中断的中断号写回到中断控制器中,以这种方式来告知中断控制器当前的中断已经处理完成,可以发送其它中断*/
			CPU0.ICCEOIR = CPU0.ICCEOIR & (~(0x3FF)) | (57);
			break;
			/*
			 * ... ...
			 */
		case 159:
			//159号中断的处理程序
			break;
		default:
			break;
	}

}

int main()
{
	/*外设层次 - 让外部的硬件控制器产生一个中断信号发送给中断控制器*/
	/*将GPX1_1设置成中断功能*/
	GPX1.CON = GPX1.CON | (0xF << 4);
	/*设置GPX1_1的中断触发方式为下降沿触发*/
	EXT_INT41_CON = EXT_INT41_CON & (~(0x7 << 4)) | (0x2 << 4);
	/*使能GPX1_1的中断功能*/
	EXT_INT41_MASK = EXT_INT41_MASK & (~(1 << 1));

	/*中断控制器层次 - 让中断控制器接收外设产生的中断信号并对其进行管理然后再转发给CPU处理*/
	/*全局使能中断控制器使其能接收外设产生的中断信号并转发到CPU接口*/
	ICDDCR = ICDDCR | 1;
	/*在中断控制器中使能57号中断,使中断控制器接收到57号中断后能将其转发到CPU接口*/
	ICDISER.ICDISER1 = ICDISER.ICDISER1 | (1 << 25);
	/*选择由CPU0来处理57号中断*/
	ICDIPTR.ICDIPTR14 = ICDIPTR.ICDIPTR14 & (~(0xFF << 8)) | (0X01 << 8);
	/*使能中断控制器和CPU0之间的接口,使中断控制器转发的中断信号能够到达CPU0*/
	CPU0.ICCICR = CPU0.ICCICR | 1;

	GPX2.CON = GPX2.CON & (~(0xF << 28)) | (0x1 << 28);

    while(1)
	{   
		/*点亮LED2*/
		GPX2.DAT = GPX2.DAT | (1 << 7); 
		/*延时*/
		Delay(1000000);
		/*熄灭LED2*/
		GPX2.DAT = GPX2.DAT & (~(1 << 7));
		/*延时*/
		Delay(1000000);
	}   

	return 0;
}

注:清除GPIO控制器中GPX1_1的中断挂起标志位,不清楚会持续发送给CPU。写1清零。

正在开发的时候linux或者其他操作系统会帮我们写好,重点理解中断和轮询处理流程。

3 补充

frq速度快的原因:

  • 优先级高
  • 异常向量表最后一位,可以不写跳转指令,直接接着写处理函数
  • frq模式下r8-r12是私有的,如果用了r8-r12可以不用压栈,但如果用了r0-r7寄存器,那么还是需要压栈的。

 

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

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

相关文章

什么是DDoS攻击

DDoS攻击 1. 定义2. DDoS攻击类型2.1 网络层攻击2.2 传输层攻击2.3 应用层攻击 3.DDoS攻击态势特点 1. 定义 分布式拒绝服务&#xff08;DDoS&#xff09;攻击是一种常见的网络攻击形式。攻击者利用恶意程序对一个或多个目标发起攻击&#xff0c;企图通过大规模互联网流量耗尽…

java学习part29线程通信

139-多线程-线程间的通信机制与生产者消费者案例_哔哩哔哩_bilibili 1.等待唤醒 类似于golang的channel&#xff0c; 1.1用法 类似于go的wait()&#xff0c; 1.sleep和wait的一个重大区别是&#xff0c;sleep不会让线程失去同步监视器&#xff0c;而wait会释放 2.wait必须tr…

【深度学习】深度学习框架的环境配置

目录 1. 配置cuda环境 1.1. 安装cuda和cudnn 1.1.1. 显卡驱动配置 1.1.2. 下载安装cuda 1.1.3. 下载cudnn&#xff0c;将解压后文件复制到cuda目录下 1.2. 验证是否安装成功 2. 配置conda环境 2.1. 安装anaconda 2.2. conda换源 2.3. 创建conda环境 2.4. pip换源 3…

使用MD5当做文件的唯一标识,这样安全么?

使用MD5作为文件唯一标识符可靠么&#xff1f; 文章目录 使用MD5作为文件唯一标识符可靠么&#xff1f;什么是MD5&#xff1f;MD5的用途MD5作为文件唯一标识的优劣优势劣势 使用MD5作为文件唯一标识的建议其他文件标识算法结束语 什么是MD5&#xff1f; MD5&#xff08;Messag…

企业计算机服务器中了locked1勒索病毒怎么解锁,locked1勒索病毒数据恢复

随着网络技术在企业的不断应用&#xff0c;企业的生产运营效率得到了极大提升&#xff0c;越来越多的企业利用网络开展工作&#xff0c;这也导致了企业的受到的网络安全威胁也不断增加。在本月&#xff0c;云天数据恢复中心陆续接到很多企业的求助&#xff0c;企业的计算机服务…

无线物理层安全学习

文章目录 3.17到3.203.85到3.88 3.17到3.20 3.85到3.88

np.array无法直接用matplotlib画图,因为需要借用np.squeeze先转化

文章目录 前言一、使用步骤1.没使用np.squeeze转化2.使用np.squeeze转化 前言 实际工作中&#xff0c;时而难免会遇见np.array无法直接用matplotlib画图的情况&#xff0c;这个时候&#xff0c;是因为在画图之前少了一个步骤&#xff0c;需要先借用np.squeeze先转化 一、使用步…

Gateway网关--java

网关是建立于请求到服务之前的,可以用网关限制访问量,添加过滤等 创建网关模块,引入相关pome依赖 配置yml 具体相关的作用可以参考 Spring Cloud Gateway 这样就可以了 基础的网关配置,我们的实现效果 我们可以通过10010端口访问,通过转发到nacos,再找到相应的模块,实现…

JS逆向-mytoken之code参数

前言 本文是该专栏的第60篇,后面会持续分享python爬虫干货知识,记得关注。 本文以mytoken为例,通过js逆向获取其code参数的生成规律。具体的“逆向”思路逻辑,笔者将会详细介绍每个步骤,并且将在正文结合“完整代码”进行详细说明。 接下来,跟着笔者直接往下看正文详细…

P5 链表 尾部插入新节点(不是指定点)

目录 前言 01 链表数据插入之直接在链表尾插入&#xff08;不是指定点&#xff09; 02 尾插创建链表优化 示例代码 前言 &#x1f3ac; 个人主页&#xff1a;ChenPi &#x1f43b;推荐专栏1: 《C》✨✨✨ &#x1f525; 推荐专栏2: 《 Linux C应用编程&#xff08;概念…

跟着chatgpt一起学|2.clickhouse入门(1)

上周我们一起学习了spark&#xff0c;这周让chatgpt帮我们规划下clickhouse的学习路径吧&#xff01; 目录 ​编辑 1.了解Clickhouse的基本概念 1.1 Clickhouse是什么&#xff1f; 1.2 ClickHouse的特点和优势 1.3 Clickhouse的基本架构与组件 1.了解Clickhouse的基本概念…

Sql Server数据库跨机器完整恢复(源文件恢复)

问题描述 在操作系统异常的情况下&#xff0c;SQL Server 和相关的业务系统遭受了不可用的情况。由于操作系统问题&#xff0c;导致旧服务器无法正常运行。为了恢复业务功能并确保数据完整性&#xff0c;采取了以下步骤来在新机器上进行 SQL Server 的重新安装和数据恢复。 面…

软件工程 - 第8章 面向对象建模 - 3 - 动态建模

状态图 状态是指在对象生命周期中满足某些条件、执行某些活动或等待某些事件的一个条件和状况 。 案例一&#xff1a;描述烧水器在工作时的详细行为细节 “人就是一个类&#xff0c;而你”、我”、张三”等都是“人这个类的一个实例&#xff0c;站着”、“躺着等都是对象的一…

POSTGRESQL中如何利用SQL语句快速的进行同环比?

1. 引言 在数据驱动的时代&#xff0c;了解销售、收入或任何业务指标的同比和环比情况对企业决策至关重要。本文将深入介绍如何利用 PostgreSQL 和 SQL 语句快速、准确地进行这两种重要分析。 2. 数据准备 为了演示&#xff0c;假设我们有一张 sales 表&#xff0c;存储了销…

基于社区电商的Redis缓存架构-写多读多场景下的购物车缓存架构

社区电商的购物车缓存架构 在购物车中的功能主要有这几个&#xff1a;商品加入购物车、查看购物车列表、删除购物车商品、选中购物车商品进行结算 这里购物车的场景和之前用户信息以及菜谱分享信息还不同&#xff0c;如果在举办了大型购物活动时&#xff0c;购物车可能需要面…

古琴零基础自学考级入门,从初级到高级古琴教学全集

一、教程描述 本套教程是古琴的组合教程&#xff0c;内容是超级齐全的&#xff0c;包括了很多套完整的古琴教程&#xff0c;来自国内知名的古琴教师、专家&#xff0c;教授等&#xff0c;都是从零基础开始讲起的&#xff0c;而且理论与实践相结合&#xff0c;对于刚学古琴入门…

【LeetCode热题100】【双指针】移动零

给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 示例 1: 输入: nums [0,1,0,3,12] 输出: [1,3,12,0,0] 示例 2: 输入: nums [0] 输出…

MyBatis的创建,简单易懂的一篇blog

文章目录 一、MyBatis是什么二、操作流程三.配置resource总结 一、MyBatis是什么 MyBatis 是⼀款优秀的持久层框架&#xff0c;它⽀持⾃定义 SQL、存储过程以及⾼级映射。MyBatis 去除了⼏乎所有的 JDBC 代码以及设置参数和获取结果集的⼯作。MyBatis 可以通过简单的 XML 或注…

试用 Windows Terminal 中的 Terminal Chat 功能

文章目录 1. 引言2. 设置 Terminal Chat2.1 安装 Windows Terminal Canary2.2 设置服务地址和密钥 3. 使用 Terminal Chat3.1 打开聊天3.2 对话使用 4. 最后 1. 引言 最近&#xff0c;Windows Terminal Canary 推出了一项名为 Terminal Chat 的新功能&#xff0c;它允许用户在…

深入理解贝叶斯分类与朴素贝叶斯模型(Naive Bayes, NB):从基础到实战

目录 贝叶斯分类 公式 决策规则 优点 贝叶斯分类器的例子——垃圾邮件问题 1. 特征&#xff08;输入&#xff09;&#xff1a; 2. 类别&#xff1a; 3. 数据&#xff1a; 4. 模型训练&#xff1a; 注&#xff1a;类别先验概率 5. 模型预测&#xff1a; 朴素贝叶斯模…