基于设备树的内核中断子系统分析(一)

内核版本:linux-4.19.8

一、ARM架构的CPU中断基础知识

ARM 体系结构中,存在7 种异常处理。当异常发生时,处理器会把PC 设置为一个特定的存储器地址。这一地址放在被称为向量表(vector table)的特定地址范围内。向量表的入口是一些跳转指令,跳转到专门处理某个异常或中断的子程序。

存储器映射地址0x00000000 是为向量表(一组32 位字)保留的。在有些处理器中,向量表可以选择定位在存储空间的高地址(从偏移量0xffff0000 开始)。一些嵌入式操作系统,如Linux 和Windows CE 就要利用这一特性。

当异常发生时,分组寄存器r14 和SPSR 用于保存处理器状态,操作伪指令如下。

R14_<exception_mode> = return link
SPSR_<exception_mode> = CPSR
CPSR[4∶0] = exception mode number
CPSR[5] = 0 /*进入ARM 状态*/
If <exception_mode> = = reset or FIQ then
CPSR[6] = 1 /*屏蔽快速中断FIQ*/
CPSR[7] = 1 /*屏蔽外部中断IRQ*/
PC = exception vector address

异常向量表

异常返回时,SPSR 内容恢复到CPSR,连接寄存器r14 的内容恢复到程序计数器PC。

对于外部中断IRQ,当处理器的外部中断请求引脚有效,而且CPSR 寄存器的I 控制位被清除时,处理器产生外部中断IRQ 异常。系统中各外部设备通常通过该异常中断请求处理器服务。当外部中断IRQ 发生时,处理器执行下列伪操作。

r14_irq = address of next instruction to be executed + 4
SPSR_irq = CPSR
CPSR[4∶0] = 0b10010 /*进入特权模式*/
CPSR[5] = 0 /*处理器进入ARM 状态*/
/*CPSR[6]保持不变*/
CPSR[7] = 1 /*禁止外设中断*/
If high vectors configured then
PC = 0xffff0018
Else
PC = 0x00000018

ARM 内核只有两个外部中断输入信号nFIQ 和nIRQ。但对于一个系统来说,中断源可能多达几十个。为
此,在系统集成的时候,一般都会有一个或多个异常控制器来处理异常信号,即为处理器的 interrupt controller。通用中断处理系统逻辑如下:

在多核处理器中,对于中断控制器的级联,存在两种情况:一是每个中断控制器连接一部分CPU,就相当于一组CPU处理一个中断控制器的中断信号,这种拓扑结构削弱了多核处理器在中断控制中的能力;二是利用root中断控制器的共享中断,将其他中断控制器级联,如上图所示,这种拓扑结构又削弱了次级中断控制器的能力,所以实际使用中,是根据具体处理器来确定的。在单核处理器中就没有这种问题,如S3C2440,采用图中所示的拓扑结构,有root中断控制器处理所有的中断信号。

在多核处理器中,对于中断信号的分发,当一个中断控制器接收到一个中断信号,通过中断信号线发送给CPU,是发送给某一个CPU呢还是广播给所有CPU,或是发送给一组CPU,显然无论是广播给所有CPU还是发送给一组CPU都将导致资源浪费,在ARM体系中,通常的做法是中断控制器预留寄存器来设置每个中断源,从而指定上报的CPU。

二、Linux中断处理流程

当外设发生中断时,CPU进入外部中断异常,CPSR 寄存器的I 控制位被清除,处理器产生外部中断IRQ 异常。CPU进入异常向量表,处理IRQ。在arch\arm\kernel\entry-armv.S有异常向量表如下:

    .section .vectors, "ax", %progbits
.L__vectors_start:
    W(b)    vector_rst
    W(b)    vector_und
    W(ldr)  pc, .L__vectors_start + 0x1000
    W(b)    vector_pabt
    W(b)    vector_dabt
    W(b)    vector_addrexcptn
    W(b)    vector_irq
    W(b)    vector_fiq

vector_irq 是由宏定义的,宏展开就会发现在保存现场,处理中断,中断处理完毕恢复现场。

    .macro    vector_stub, name, mode, correction=0
    .align    5
vector_\name:
...
vector_stub irq, IRQ_MODE, 4  
    .long   __irq_usr               @  0  (USR_26 / USR_32)
    .long   __irq_invalid           @  1  (FIQ_26 / FIQ_32)
    .long   __irq_invalid           @  2  (IRQ_26 / IRQ_32)
    .long   __irq_svc               @  3  (SVC_26 / SVC_32)
...

由异常向量表调用vector_irq,它会根据SPSR寄存器的值,判断被中断时CPU是处于USR状态还是SVC状态,然后调用下面的__irq_usr或__irq_svc进入irq_hander

__irq_usr:
	usr_entry
	kuser_cmpxchg_check
	irq_handler
	.macro	irq_handler
#ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
	ldr	r1, =handle_arch_irq
	mov	r0, sp
	badr	lr, 9997f
	ldr	pc, [r1]
#else
	arch_irq_handler_default
#endif
9997:
	.endm

由此调用handle_arch_irq,这是一个C函数,从名字就可以大致知道,进入具体处理器,处理这个中断。那么handle_arch_irq从哪里来?这里以S3C2440为例:drivers/irqchip/irq-s3c24xx.c

IRQCHIP_DECLARE(s3c2410_irq, "samsung,s3c2410-irq", s3c2410_init_intc_of);
    s3c2410_init_intc_of
        set_handle_irq(s3c24xx_handle_irq);
            handle_arch_irq = handle_irq;

中断handle在具体的处理器中断处理初始化中设置的,对于上面这一段代码将在后续解释。分析到这里可以得出,处

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值