精华内容
下载资源
问答
  • 中断向量表的地址空间
    千次阅读
    2021-01-21 13:34:06

    中断向量表(interrupt vector table,IVT)是中断源的识别标志,可用来形成相应的中断服务程序的入口地址或存放中断服务程序的首地址称为中断向量。在Pc/AT中由硬件产生的中断标识码被称为中断类型号(当然,中断类型号还有其他的产生方法,如指令中直接给出、CPU自动形成等),即在中断响应期间8259A产生的是当前请求中断的最高优先级的中断源的中断类型号。中断类型号和中断向量之间有下面的关系: 中断类型号×4=存放中断向量的首地址 有了存放中断向量的首地址,从该地址开始的4个存储单元中取出的就是中断服务程序的入口。

    介绍

    是指中断服务程序入口地址的偏移量与段基值一个中断向量占据4字节空间。中断向量表是8086系统内存最低端1K字节空间,它的作用就是按照中断类型号从小到大的顺序存储对应的中断向量,总共存储256个中断向量。在中断响应过程中,CPU通过从接口电路获取的中断类型号(中断向量号)计算对应中断向量在表中的位置,并从中断向量表中获取中断向量,将程序流程转向中断服务程序的入口地址。

    列表

    80x86系统是把所有的中断向量集中起来,按中断类型号从小到大的顺序存放到存储器的某一区域内,这个存放中断向量的存储区叫做中断向量表,即中断服务程序入口地址表。

    由于中断向量表可以在操作系统层面灵活修改,因此,不同的系统的中断向量表可能是不同的。此外,intel在CPU的保护模式下,占用了0x00 ~ 0x1F共32个中断号,在Linux下,是从0x20开始用于系统自身的中断的,包括8259芯片的中断重置。

    BIOS(实模式)的中断向量表如下:

    80x86

    I/O ADDR

    INT TYPE(16进制)

    FUNCTION

    00 ~ 03

    0

    除法溢出中断

    04 ~ 07

    1

    单步(用于DEBUG)

    08 ~ 0B

    2

    非屏蔽中断(NMI)

    0C ~ 0F

    3

    断点中断(用于DEBUG)

    10 ~ 13

    4

    溢出中断

    14 ~ 17

    5

    打印屏幕

    18 ~ 1F

    6/7

    保留

    8259主片

    I/O ADDR

    INT TYPE(16进制)

    FUNCTION

    20 ~ 23

    8

    定时器(IRQ0)

    24 ~ 27

    9

    键盘(IRQ1)

    28 ~ 2B

    A

    彩色/图形(IRQ2)

    2C ~ 2F

    B

    串行通信COM2(IRQ3)

    30 ~ 33

    C

    串行通信COM1(IRQ4)

    34 ~ 37

    D

    LPT2控制器中断(IRQ5)

    38 ~ 3B

    E

    磁盘控制器中断(IRQ6)

    3C ~ 3F

    F

    LPT1控制器中断(IRQ7)

    BIOS

    I/O ADDR

    INT TYPE(16进制)

    FUNCTION

    40 ~43

    10

    视频显示 I/O

    44 ~ 47

    11

    设备检验

    48 ~ 4B

    12

    测定存储器容量

    4C ~ 4F

    13

    磁盘 I/O

    50 ~ 53

    14

    RS-232 串行口 I/O

    54 ~ 57

    15

    系统描述表指针

    58 ~ 5B

    16

    键盘 I/O

    5C ~ 5F

    17

    打印机 I/O

    60 ~ 63

    18

    ROM BASIC 入口代码

    64 ~ 67

    19

    引导装入程序

    68 ~ 6B

    1A

    日时钟

    提供用户中断

    I/O ADDR

    INT TYPE(16进制)

    FUNCTION

    6C ~ 6F

    1B

    Ctrl - Break 控制的软中断

    70 ~ 73

    1C

    定时器控制的软中断

    74 ~ 77

    1D

    视频参数块

    78 ~ 7B

    1E

    软盘参数块

    7C ~ 7F

    1F

    图形字符扩展码

    在DOS系统(实模式)下,从0x20开始,用于操作系统本身。

    DOS

    I/O ADDR

    INT TYPE(16进制)

    FUNCTION

    80 ~ 83

    20

    DOS 中断返回

    84 ~ 87

    21

    DOS 系统功能调用

    88 ~ 8B

    22

    程序中止时 DOS 返回地址(用户不能直接调用)

    8C ~ 8F

    23

    Ctrl - Break 处理地址(用户不能直接调用)

    90 ~ 93

    24

    严重错误处理(用户不能直接调用)

    94 ~ 97

    25

    绝对磁盘读功能

    98 ~ 9B

    26

    绝对磁盘写功能

    9C ~ 9F

    27

    终止并驻留程序

    A0 ~ A3

    28

    DOS安全使用

    A4 ~ A7

    29

    快速写字符

    A8 ~ AB

    2A

    Microsoft 网络接口

    B8 ~ BB

    2E

    基本 SHELL 程序装入

    BC ~ BF

    2F

    多路服务中断

    CC ~ CF

    33

    鼠标中断

    104 ~ 107

    41

    硬盘参数块

    118 ~ 11B

    46

    第二硬盘参数块

    11C ~ 3FF

    47 ~ FF

    BASIC 中断

    保护模式

    在Linux下(保护模式),没有使用BIOS设置的中断向量表,0x00 ~ 0x1F是CPU保护模式下的默认中断向量,而0x20开始,都是被Linux系统重新设置的。

    X86占用的中断向量表如下:

    向量号

    助记符

    说明

    类型

    错误号

    产生源

    0

    #DE

    除出错

    故障

    DIV或IDIV指令。

    1

    #DB

    调试

    故障/陷阱

    任何代码或数据引用,或是INT 1指令。

    2

    --

    NMI中断

    中断

    非屏蔽外部中断。

    3

    #BP

    断点

    陷阱

    INT 3指令。

    4

    #OF

    溢出

    陷阱

    INTO指令。

    5

    #BR

    边界范围超出

    故障

    BOUND指令。

    6

    #UD

    无效操作码

    故障

    UD2指令或保留的操作码。

    7

    #NM

    设备不存在

    故障

    浮点或WAIT/FWAIT指令。

    8

    #DF

    双重错误

    异常终止

    有(0)

    任何可产生异常、NMI或INTR的指令。

    9

    --

    协处理器段超越(保留)

    故障

    浮点指令

    10

    #TS

    无效的任务状态段TSS

    故障

    任务交换或访问TSS

    11

    #NP

    段不存在

    故障

    加载段寄存器或访问系统段

    12

    #SS

    堆栈段错误

    故障

    堆栈操作或SS寄存器加载

    13

    #GP

    一般保护错误

    故障

    任何内存引用和其他保护检查

    14

    #PF

    页面错误

    故障

    任何内存引用

    15

    --

    (intel保留)

     

     

    16

    #MF

    x87 FPU浮点错误

    故障

     

    17

    #AC

    对齐检查

    故障

    有(0)

    对内存中任何数据的引用。

    18

    #MC

    机器检查

    异常终止

    错误码(若有)和产生源与CPU类型有关。

    19

    #XF

    SIMD浮点异常

    故障

     

    Linux自己设置的中断以后再添加。

    更多相关内容
  • 在MCU/ARM/DSP中,都有1个启动过程,这里主要设计复位...复位及中断的入口具有多个间隔固定的程序空间,它们可以是单独的跳转地址及函数指针,如ARM的中断向量表。也可是一块小的固定程序空间,如51的n*8+3和DSP5402的4字。
  • ARM嵌入式系统中断向量表的动态配置,通常32位ARM嵌入式系统的中断向量表是在程序编译前设置好的,每次编写中断程序都要改C程序的汇编启动代码,相当繁琐。本文给出一种配置ARM中断向量表新方法。该方法比通常方法仅...
  • STM32 的中断向量表复制到 SRAM 运行

    1、生成Map文件

    复制中断向量表前需要知道中断向量表的大小,可以通过编译生成的Map文件查看。
    在这里插入图片描述

    2、查看中断向量表大小

    中断向量表的大小是固定的,与程序代码量无关,打开Map文件,直接搜索0x08000000,我使用的 MCU 是 STM32H743XIH6,中断向量表大小为 664 字节,即 MDK 编译生成的 Bin 文件,开始的 664 个字节是中断向量表

        RESET                                    0x08000000   Section      664  startup_stm32h743xx.o(RESET)
        !!!main                                  0x08000298   Section        8  __main.o(!!!main)
        !!!scatter                               0x080002a0   Section       52  __scatter.o(!!!scatter)
        !!dczerorl2                              0x080002d4   Section       90  __dczerorl2.o(!!dczerorl2)
        !!handler_zi                             0x08000330   Section       28  __scatter_zi.o(!!handler_zi)
    

    3、读取中断向量表的内容,并直接放在指定的SRAM 地址处

    // 中断向量表大小 664 字节 
    #define  VECTOR_TABLE_SIZE 664
    // 中断向量表复制到 SRAM 0x24001000 地址
    u8 vector_table[VECTOR_TABLE_SIZE] __attribute__ ((at(0X24001000)));
    // 读取 Flash 内容
    // STMFLASH_Read(addr,(u32*)vector_table,VECTOR_TABLE_SIZE/4);
    

    值得注意的是,STMFLASH_Read 函数不能读取 Flash 程序代码所在的空间,否则会出现异常

    我这里的设计是 BootLoader 程序通过 Can 接收待升级的固件 Bin 文件(然后写入指定的 FLASH 地址处,在把前 664 字节数据读出来复制给 vector_table)并将前 664 个字节的中断向量表直接复制给 vector_table,即完成了中断向量表的复制到 SRAM 的 0x24010000

    4、APP程序的设置

    以上只是完成了,中断向量表的复制,还需要告诉 APP 程序中断向量表的位置,APP程序中添加如下代码。

    SCB->VTOR = D1_AXISRAM_BASE|0x1000;   
    

    再运行 APP 程序的时候,使用的就是 SRAM 中的中断向量表了。
    这样做的目的是,固件升级的时候,可以在 FLASH 中存放多个 APP 程序。

    展开全文
  • 汇编_修改中断向量表_自定义中断

    千次阅读 2021-10-01 10:42:28
    规定中断向量表的起始地址为0000h,结束地址为03FF,即(0000000000)b~(1111111111)b,总共占用了前1024个字节。 注:0200h~02FFh地址空闲,还没有给定中断向量地址 索引方式: 中断向量表的索引地址由两部分构成,...

    中断向量表

    介绍

    在dos系统中,总共设计了256种中断,每个中断都有一个中断号,通过中断号来映射中断程序的地址。为了实现映射的功能,引入中断向量表。规定中断向量表的起始地址为0000h,结束地址为03FF,即(0000000000)b~(1111111111)b,总共占用了前1024个字节。
    注:0200h~02FFh地址空闲,还没有给定中断向量地址

    在这里插入图片描述

    索引方式:

    中断向量表的索引地址由两部分构成,分别是CS和IP,其低地址存放IP,高地址存放CS。当触发中断号x时,操作系统先保存PSW和PC到核心栈中,然后设置IP=[0000:[x*2]],CS=[0000:[x*2+2]],然后进行中断调用。
    例如:
    当触发21h号中断时,系统先保存PSW和PC,然后将IP设置为[0000:[42h]],CS设置为[0000:[44h]],然后执行中断调用。

    修改中断向量表

    修改中断向量表,其实就是修改目标中断的CS和IP的值,让中断发生时,CS:IP指向我们自定义的中断。
    比如修改0号中断的中断向量表。

        mov ax, 0
        mov es, ax
    
        mov word ptr es:[0*4], 200h
        mov word ptr es:[0*4+2],0;设置中断向量表
    

    自定义中断

    思路

    前面我们已经说到,0200h~02FFh这个地址空间是空闲的,可以用来存放程序。而中断向量表的作用是用于索引中断向量,于是,我们可以利用修改中断向量表,使其指向我们自定义的中断程序,便可以实现自定义中断的效果。
    在这里插入图片描述

    实现效果:

    0号中断为除数为0中断,将其自定义为:在屏幕的正中央输出heppen 0 interrupt。
    在这里插入图片描述

    实现代码

    伪码描述:
    1.根据中断号找到中断向量地址。
    2.修改中断向量地址为我们自定义的中断向量地址。
    3.运行设置程序do0.exe
    4.运行测试程序test.exe
    汇编代码

    ;do0.asm
    
    assume cs:codesg
    
    codesg segment
    start: 
        mov ax, cs
        mov ds, ax;源段地址
        mov si, offset do0;源地址偏移
    
        mov ax, 0
        mov es, ax;目标段地址
        mov di, 200h;目标地址偏移
        
        mov cx, offset do0end - offset do0;目标地址长度
    
        cld;设置传输方向为正
        rep movsb;ds:[si]->es:[di] 循环cx次
    
        mov ax, 0
        mov es, ax
    
        mov word ptr es:[0*4], 200h
        mov word ptr es:[0*4+2],0;设置中断向量表
    
        mov ax, 4c00h
        int 21h;
    do0:
        jmp short do0start
        db "happen 0 interrupt";中断后显示的数据
    do0start:
        mov ax, 0h
        mov ds, ax
        mov si, 202h;数据的起始地址
    
        mov ax, 0B800h
        mov es, ax
        mov di, 12*160+36*2;设置显示位置
        mov cx, 18
    
    s:  mov al,[si];将数据放入显存
        mov ah,0FFh
        mov es:[di], ax
        inc si
        add di, 2
        loop s
    
        mov ax, 4c00h
        int 21h
    
    do0end:
        nop
    codesg ends
    
    end start
    
    ;test.asm
    
    assume cs:codesg
    
    codesg segment
    start:
        mov ax, 12h
        mov dx, 0h
        div dx
    
        mov ax, 4c00h
        int 21h
    codesg ends
    end start
    

    执行步骤

    1.ml do0.asm
    2.do0.exe
    3.ml test.asm
    4.do0.exe
    也可以逐步编译,连接
    1.masm do0.asm
    2.link do0.obj
    3.do0.exe
    4.masm test.asm
    5.link test.obj
    6.test.exe

    展开全文
  • 摘要:通常32位ARM嵌入式系统的中断向量表是在程序编译前设置好的,每次编写中断程序都要改C程序的汇编启动代码,相当繁琐。本文给出一种配置ARM中断向量表新方法。该方法比通常方法仅增加一条指令执行时间,简便...
  • 来存放中断向量(共256个),称这一片内存区为中断向量表地址范围是0~3FFH 中断向量地址: 存储中断向量的存储单元地址 中断向量: 中断向量的集合,按中断类型号从小到大的顺序存放到存储器的某一区域内,这个存放...

    参考:https://www.cnblogs.com/douzi2/p/5112743.html

    当异常中断发生时,系统执行完当前指令后,将跳转到相应的异常中断处理程序处执行。在异常中断处理程序执行完成后,程序返回到发生中断的指令的下一条指令处执行。

    说明

    Kernel版本:4.14.111
    ARM处理器,Contex-A7
    在《ARM体系结构与编程》第9章中说到,ARM 中有个概念叫做“异常中断”,也就是包括外部中断在内的各种异常。显然,ARM体系的“异常中断”概念更加接近MIPS体系中的“异常”概念。
    在这里插入图片描述

    思考

    1. 首先中断向量是什么,中断向量表又是什么.
    2. ARM中异常中断的种类
    3. 向量中断和非向量中断
    4. 内核在哪里定义中断向量表
    5. 异常来时,中断跳转过程
    6. 为什么异常中断向量表必须设置在从0地址开始
    7. FIQ相比IRQ,FIQ称为快速中断,IRQ称为普通中断。FIQ为什么比IRQ快

    1. 首先中断向量是什么,中断向量表又是什么

    • 中断向量
      中断服务程序的入口地址。在某些计算机中,中断向量的位置存放一条跳转到中断服务程序入口地址的跳转指令。
      来存放中断向量(共256个),称这一片内存区为中断向量表,地址范围是0~3FFH

    • 中断向量地址:
      存储中断向量的存储单元地址

    • 中断向量:
      中断向量的集合,按中断类型号从小到大的顺序存放到存储器的某一区域内,这个存放中断向量的存储区叫做中断向量表,即中断服务程序入口地址表。

    CPU是根据中断号获取中断向量值,即对应中断服务程序的入口地址值。因此为了让CPU由中断号查找到对应的中断向量,就需要在内存中建立一张查询表

    2. ARM中异常中断的种类

    说明
    Kernel版本:4.14.111
    ARM处理器,Contex-A7
    在《ARM体系结构与编程》第9章中说到,ARM 中有个概念叫做“异常中断”,也就是包括外部中断在内的各种异常。显然,ARM体系的“异常中断”概念更加接近MIPS体系中的“异常”概念。
    在这里插入图片描述
    ARM异常中断向量表
    在这里插入图片描述
    ARM的异常中断向量表可以是高端向量表,也可以是低端向量表,两者取其一。区别是基地址不同。高端向量是ARM架构可选配置,可以通过硬件外部输入管脚来配置是低端向量还是高端向量,不能通过指令来改变向量的位置,但如果ARM芯片内部有标准ARM协处理器,那么协处理器CP15的寄存器C1的bit13可以用来切换低端和高端向量地址,等于0时为低端向量,等于1时为高端向量。
      Linux内核分用户空间、内核空间,通常32位处理器,用户空间0-3G,内核空间3-4G,所以Linux内核使用高端向量表。

    ARM的一个非常重要的寄存器——CPSR程序状态寄存器
    cpsr这个寄存器用来设定进入哪种模式

    3. 向量中断和非向量中断

    向量中断 非向量中断
        向量者,矢量也,即指方向,门路。
        向量中断------由硬件提供中断服务程序入口地址;
        非向量中断------由软件件提供中断服务程序入口地址;

    推荐向量中断就是不同的中断有不同的入口地址,非向量中断就只有一个入口地址,进去了再判断中断标志来识别具体是哪个中断。向量中断实时性好,非向量中断简单

    • 向量中断模式用于RESET、NMI(非屏蔽中断)、异常处理。当向量中断产生时,控制器直接将PC赋值,如跳到0x0000000d处,而在0x0000000d地址处通常放置ISR服务程序地址LDR PC, =ISR_HANDLER。——代码都是现成的
    • 非向量中断模式,有一个寄存器标识位,跳转到统一的函数地址,此函数通过判别寄存器标识位和优先级关系进行中断处理。向量中断模式是当CPU读取位于0x18处的IRQ中断指令的时候,系统自动读取对应于该中断源确定地址上的指令取代0x18处的指令,通过跳转指令系统就直接跳转到对应地址函数中,节省了中断处理时间提高了中断处理速度。例如 ADC 中断的向量地址为0xC0,则在0xC0处放如下代码:ldr PC,=HandlerADC 当ADC中断产生的时候系统会自动跳转到HandlerADC函数中处理中断。

    对于ARM,ARM没有NMI,外部中断走的是非向量中断,即走注册的中断服务例程ISP,这个是驱动工程师自己注册的request_irq的irq_handle

    但是无论是非向量中断还是向量中断,都会走到__vectors_start,然后根据中断类型走到对于的分类,例如IRQ就是走到了__vectors_start的vendor_irq,然后最终走到了irq_desc(中断例程描述符表),里面就定义了irqaction,irqaction链表指向了irq_handler_t中断服务程序,即reques_irq注册的中断服务程序

    而对于其他类型的异常,如RESET,硬件已经做好了现成的处理code,根据向量表直接到达代码的地址,然后执行。区别于非向量的IRQ是统一的地址,进入这个地址后,再由中断例程描述符表区分中断

    4. 内核在哪里定义中断向量表

    在vmlinux.lds.S描述了__vectors_start的起始位置,从0xffff0000开始

    	/*
    	 * The vectors and stubs are relocatable code, and the
    	 * only thing that matters is their relative offsets
    	 */
    	__vectors_start = .;
    	.vectors 0xffff0000 : AT(__vectors_start) {			(1)
    		*(.vectors)
    	}
    	. = __vectors_start + SIZEOF(.vectors);
    	__vectors_end = .;
    
    	__stubs_start = .;
    	.stubs ADDR(.vectors) + 0x1000 : AT(__stubs_start) {
    		*(.stubs)										(2)
    	}
    	. = __stubs_start + SIZEOF(.stubs);
    	__stubs_end = .;
    
    

    1)链接时,将.vectors段内容链接到虚拟地址0xffff0000地址。(这里我理解为在vmlinux镜像中.vectors段连续,夹在__vectors_start和__vectors_end 中间,但是链接的虚拟地址指向0xffff0000)
    2)同上。
      arch/arm/kernel/entry-armv.S 中.vectors段保存了异常向量表。

    	.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
    
    

    (软件中的向量表和硬件中的offset定义的一致性)
    在这里插入图片描述
    上面是中断向量表,而具体的向量是在vector_stub中,例如,vector_irq

    /*
     * Interrupt dispatcher
     */
        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)
        .long   __irq_invalid           @  4
        .long   __irq_invalid           @  5
        .long   __irq_invalid           @  6
        .long   __irq_invalid           @  7
        .long   __irq_invalid           @  8
        .long   __irq_invalid           @  9
        .long   __irq_invalid           @  a
        .long   __irq_invalid           @  b
        .long   __irq_invalid           @  c
        .long   __irq_invalid           @  d
        .long   __irq_invalid           @  e
        .long   __irq_invalid           @  f
    

    5. 异常来时,中断跳转过程

    参考:http://blog.chinaunix.net/uid-29045944-id-3968667.html

    根据异常向量表,有异常的时候就可以跳转了;但是跳到哪里呢?

    上面说到,当有IRQ中断(我们在7种异常中断类型举IRQ为例)时,CPU根据中断向量表进入vector_irq,vector_irq的描述在vector_stub中,假如IRQ中断时在用户usr模式,则进入
    __irq_usr,__irq_usr

    __irq_usr:
    	usr_entry    @保存中断上下文
    	kuser_cmpxchg_check
    	irq_handler  @调用中断处理程序
    	get_thread_info tsk @获取当前进程的进程描述符中的成员变量thread_info的地址,并将该地址保存到寄存器tsk(r9)(在entry-header.S中定义)
    	mov	why, #0
    	b	ret_to_user_from_irq @中断处理完成,恢复中断上下文并返回中断产生的位置
     UNWIND(.fnend		)
    ENDPROC(__irq_usr)
    

    如果发生中断前处于核心态则进入__irq_svc,其定义如下

    __irq_svc:
    	svc_entry  @保存中断上下文
    	irq_handler  @调用中断处理程序
    
    #ifdef CONFIG_PREEMPT
    	ldr	r8, [tsk, #TI_PREEMPT]		@ get preempt count
    	ldr	r0, [tsk, #TI_FLAGS]		@ get flags
    	teq	r8, #0				@ if preempt count != 0
    	movne	r0, #0				@ force flags to 0
    	tst	r0, #_TIF_NEED_RESCHED
    	blne	svc_preempt  @如果不等于0,说明发生内核抢占,需要重新调度。
    #endif
    
    	svc_exit r5, irq = 1			@恢复中断上下文
     UNWIND(.fnend		)
    ENDPROC(__irq_svc)
    

    上面代码中的usr_entry和svc_entry是一个宏定义,主要用于保护中断上下文到栈中
    保存中断上下文后则进入中断处理程序——irq_handler,定义在arch/arm/kernel/entry_armv.S文件中:

    #ifdef CONFIG_MULTI_IRQ_HANDLER
    	ldr	r1, =handle_arch_irq
    	mov	r0, sp
    	badr	lr, 9997f
    	ldr	pc, [r1]
    #else
    	arch_irq_handler_default
    #endif
    

    这里32位走arch_irq_handler_default,64位走handle_arch_irq

    (1 )arch_irq_handler_default:

    arch_irq_handler_default ——>asm_do_IRQ()—>handle_IRQ()—>__handle_domain_irq()—>generic_handle_irq()—>调用用户request_irq注册的中断处理函数

    (2)handle_arch_irq :
    handle_arch_irq---->set_handle_irq---->gic_handle_irq---->handle_domain_irq()---->__handle_domain_irq()---->generic_handle_irq()---->generic_handle_irq_desc()

    2种最终都调用到了desc->handle_irq(desc)

    (kernel/include/linux/irqdesc.h)
    static inline void generic_handle_irq_desc(struct irq_desc *desc)
    {
    	desc->handle_irq(desc);  // 这里真正调用到,用户request_irq注册的中断处理函数
    }
    
    

    generic_handle_irq_desc调用中断描述符的handle_irq回调函数。对于不同的中断类型,handle_irq回调函数可能是handle_simple_irq、handle_level_irq、handle_fasteoi_irq、handle_edge_irq、handle_edge_eoi_irq、handle_percpu_irq。

    假如我们用reques_irq注册的是gpio电平触发中断,那么这里的desc->handle_irq就是handle_level_irq。(省略转换流程)

    最终,handle_level_irq----> handle_irq_event(desc)-----> handle_irq_event_percpu------> res = action->handler(irq, action->dev_id); /* 调用action->handler,即request_irq 时注册的handler 函数 */

    这里我们关注struct irq_desc,称为中断描述符,该数据结构保存了关于所有IRQ的中断描述符信息

    struct irq_desc {
             irq_flow_handler_t       handle_irq;  //指向中断函数, 中断产生后,就会执行这个handle_irq
             struct irq_chip   *chip; //指向irq_chip结构体,用于底层的硬件访问,下面会介绍
             struct msi_desc             *msi_desc; 
             void                     *handler_data;  
             void                     *chip_data;
             struct irqaction     *action;      /* IRQ action list */   //action链表,用于中断处理函数
             unsigned int                  status;                  /* IRQ status */
             unsigned int                  depth;                  /* nested irq disables */
             unsigned int                  wake_depth;        /* nested wake enables */
             unsigned int                  irq_count;   /* For detecting broken IRQs */
             unsigned int                  irqs_unhandled;
             spinlock_t            lock;          
         ... ...
             const char            *name;              //产生中断的硬件名字
    } ;
    

    其中的成员*chip的结构体,用于底层的硬件访问, irq_chip类型如下:

    struct irq_chip {
             const char   *name;
             unsigned int    (*startup)(unsigned int irq);       //启动中断 
             void            (*shutdown)(unsigned int irq);      //关闭中断
             void            (*enable)(unsigned int irq);         //使能中断
             void            (*disable)(unsigned int irq);        //禁止中断
             void            (*ack)(unsigned int irq);       //响应中断,就是清除当前中断使得可以再接收下个中断
             void            (*mask)(unsigned int irq);     //屏蔽中断源 
             void            (*mask_ack)(unsigned int irq);  //屏蔽和响应中断
             void            (*unmask)(unsigned int irq);   //开启中断源
             ... ...
         int              (*set_type)(unsigned int irq, unsigned int flow_type);  //将对应的引脚设置为中断类型的引脚
         ... ...
    #ifdef CONFIG_IRQ_RELEASE_METHOD
             void            (*release)(unsigned int irq, void *dev_id);       //释放中断服务函数
    #endif
    
    };
    

    其中的成员struct irqaction *action,主要是用来存用户注册的中断处理函数,
    一个中断可以有多个处理函数 ,当一个中断有多个处理函数,说明这个是共享中断.
    所谓共享中断就是一个中断的来源有很多,这些来源共享同一个引脚。
    所以在irq_desc结构体中的action成员是个链表,以action为表头,若是一个以上的链表就是共享中断
    irqaction结构定义如下:

    struct irqaction {
             irq_handler_t handler;      //等于用户注册的中断处理函数,中断发生时就会运行这个中断处理函数
             unsigned long flags;         //中断标志,注册时设置,比如上升沿中断,下降沿中断等
             cpumask_t mask;           //中断掩码
             const char *name;          //中断名称,产生中断的硬件的名字
             void *dev_id;              //设备id
             struct irqaction *next;        //指向下一个成员
             int irq;                    //中断号,
             struct proc_dir_entry *dir;    //指向IRQn相关的/proc/irq/
    
    };
    

    上面3个结构体的关系如下图所示:
    在这里插入图片描述

    7. 为什么异常中断向量表必须设置在从0地址开始

    由硬件电路决定,一般固定设置异常中断向量表在0地址开始,即复位异常触发的地址

    8. FIQ相比IRQ,FIQ称为快速中断,IRQ称为普通中断。FIQ为什么比IRQ快

    1. 寄存器处理速度快。FIQ比IRQ有更多的banked寄存器,可以自动保存和恢复值。如果你FIQ中断处理程序足够用这几个独立的寄存器来运作,它就不会进行通用寄存器的压栈,这样也省了一些时间。
    2. FIQ比IRQ有更高的优先级,如果FIQ和IRQ同时产生,那么FIQ先处理。
    3. FIQ比IRQ至少少了一条跳转指令。FIQ的1C以后没有任何中断向量表了,这样可以直接在1C处放FIQ的中断处理程序,而IRQ的18只能放一条指令,然后跳转
    4. FIQ的响应比IRQ更快
    展开全文
  • ARM Cortex-M系列之中断向量表

    千次阅读 2020-04-22 14:13:48
    ARM Cortex-M架构的芯片的中断向...ARM Cortex-M手册规定在片上闪存起始地址处需要有一个有效的中断向量表。芯片上电或复位后首先从中向量表中读出入口函数地址和栈指针。将入口函数地址和栈指针装载入寻址寄存器...
  • 中断向量表) 另外,之前0号地址只能存储两条指令,如果需要更多指令怎么办?(地址的位置以及对应程序大小应该更灵活) 注意,中断服务程序包含(保存现场,调用处理方法(主体),恢复现场) 我们在遇到中断之后...
  • 嵌入式杂谈之中断向量表

    千次阅读 多人点赞 2020-04-05 10:00:32
    至于为什么会提到中断向量表,主要是因为我自己在学习嵌入式Linux开发的过程中,好像学到的所有开始阶段都是要通过汇编完成的,好像没有汇编程序,整套系统就无法运行,那作为一套完整的系统,究竟从上电开始程序...
  • 9.2 中断向量表的结构

    千次阅读 2019-09-20 21:02:56
    9.2 中断向量表的结构 我现在已经知道了,在运算的时候 一旦遇到了异常情况,就翻到第一页的第一行开始写的这些操作的指示,开始往下执行。开始往下执行,这就能解决问题了。但是问题在于这段操作,解决的是我那个...
  • 来源:公众号【鱼鹰谈单片机】作者:鱼鹰OspreyID :emOsprey在有 boot 的情况下,一般需要重新设置 app 的中断向量表,使得中断向量表从 boot 切换到 APP ...
  • 汇编语言常用的一些中断指令: 中断 向量表 希望有点用处
  • 中断入口和中断向量表

    千次阅读 2019-11-14 15:08:09
    中断向量表和中断入口两个概念 中断向量表的位置在启动文件中startup_stm32f10x_hd.s中,可以看到定义了很多的中断函数, 这些函数是依次排列的,那就是依次给它们分配了空间。这些空间地址就是中断入口,如果想改...
  • 今天痞子衡给大家分享的是Cortex-M中断向量表原理及其重定向方法。  接着前文 《嵌入式Cortex-M裸机环境下临界区保护的三种实现》 继续聊,嵌入式代码设计里有时候一些特殊操作(比如 XIP 下 Flash 擦写、低功耗模式...
  • TMS320F28335中断向量表

    千次阅读 2020-06-29 11:14:05
    在 F28335 中采用 PIE 中断向量表来解决上述问题,通过 PIE 中断向量表使得 96 个可能产生的中断都有各自独立的 32 位入口地址。PIE 向量表由 256X16B的 SRAM 内连续存放,如果这部分空间不用作 PIE 模块时,可用作...
  • 1.实模式下中断向量表 如图,每个中断在向量表中占两个字; 8259传来中断号、软中断指明中断号=>中断号*4得到中断处理程序入口地址; 2.BIOS中断 BIOS中断是软中断,是在加电之后,BIOS程序执行期间建立起来的...
  • 问题背景 项目使用STM32F030,需要通过IAP进行固件升级,在FLASH里面要烧录两份代码:一个Boot loader,一个用户应用...但在STM32F0xx系列以Cortex-M0为内核的单片机中却怎么也找不到这个设置中断向量表的寄存器,用
  • STM32中断向量表的偏移量设置方法

    万次阅读 2020-09-28 09:35:13
    STM32中断向量偏移 总结一下在IAP升级中APP程序的中断向量表的偏移 讲解中断偏移之前先看一下程序的启动流程 STM32F4 的内部闪存...序完成启动,而这张“中断向量表”的起始地址是 0x08000004,当中断来临,ST
  • ARM中断向量表的简单分析

    千次阅读 2018-01-10 20:38:43
    一般编写arm的裸机程序的时候,创建中断向量表就把它放在0x00000000~0x0000001c中,一般都放在这个位置上。但是中断向量表也可以放在0xffff0000~0xffff001c中,知道这是怎么设置的么?开始看到的时候真的有点奇怪,...
  • ARM中的异常与中断总共有7种按响应优先级从高到低按中断向量表顺序复位复位数据中止未定义指令中断FIQSWIIRQ预取指令中止预取指令中止数据中止异常未定义指令、SWIIRQFIQARM要求中断向量表必须放置在从0地址开始,...
  • 此外STM32其内部通过一张“中断向量表”来响应中断,程序启动后,将首先从“中断向量表”取出复位中断向量执行复位中断程序完成启动,而这张“中断向量表”的起始地址是0x08000004,当中断来临, STM32 的内部硬件...
  • Linux内核ARM架构异常中断向量表

    千次阅读 2020-07-18 13:21:34
    Linux内核ARM架构异常中断向量表说明ARM中异常中断的种类ARM异常中断向量表内核异常向量表异常向量表跳转vector_srub宏内核启动建立异常向量表   当异常中断发生时,系统执行完当前指令后,将跳转到相应的异常中断...
  • 80x86 中断向量表

    千次阅读 2017-06-07 12:23:29
     系统刚引导时,内存0x00000到0x0003FF共1KB的空间用于存放中断向量表。每个中断向量占用4个字节,共可存储256个中断向量。 2. 系统引导时,处在实模式下,只可寻址1MB,为什么要用4个字节来寻址中断呢处理程序? ...
  • 问:What is interrupt? 百度百科:中断是指在计算机执行程序的过程中,当出现异常情况或者特殊请求时,计算机停止现行的程序的运行,转而对这些异常处理...中断向量地址:内存中存放中断服务程序入口地址地址 ...
  • 以下是自己近期学习的理解, 1.一般ARM处理器都是从地址0x00000000开始执行指令,imx6ul的0x...3.启动程序首先要配置中断向量表,即按照手册的中断向量表的顺序完成中断向量表定义,汇编语言每条指令占用4个字节的地址
  • Linux Kernel arm64中断向量表的定义 (linux/arch/arm64/kernel/entry.S) /* * Exception vectors. */ .pushsection ".entry.text", "ax" .align 11 SYM_CODE_START(vectors) kernel_ventry 1, sync_invalid ...
  • 中断之中断向量表IDT的初始化

    千次阅读 2016-08-25 21:54:48
    中断的初始化是在哪里完成的呢?是在start_kernel()中: 512 trap_init(); 535 /* init some links before init_ISA_irqs() */ 536 early_irq_init();  537 init_IRQ();...中断向量表的初始化分为

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 14,448
精华内容 5,779
关键字:

中断向量表的地址空间

友情链接: Api创建浏览器.zip