【ARM】-IRQ 和 FIQ 异常中断处理程序的返回

这篇具有很好参考价值的文章主要介绍了【ARM】-IRQ 和 FIQ 异常中断处理程序的返回。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

处理流程

通常处理器执行完当前指令后,查询 IRQ 中断引脚及 FIQ 中断引脚,并且查看系统是否允许 IRQ 中断及 FIQ中断。
如果有中断引脚有效,并且系统允许该中断产生,处理器将产生 IRQ 异常中断或 FIQ 异常中断。
当 IRQ 和 FIQ 异常中断产生时,程序计数器 PC 的值已经更新,它指向当前指令后面第 3 条指令(对于 ARM 系统来说它指向当前指令地址加 12 个字节的位置,对于 Thumb 指令来说,它指向当前指令加 6 个字节的位置)。
当 IRQ 和 FIQ 异常中断发生时,处理器将 PC-4 的值保存到异常模式下的寄存器 LR_mode 中,这时 LR_mode 中的值即为PC-4 ,即指向当前指令后的第二条指令。因此返回操作需要将 LR_mode - 4(指向当前指令的下一条指令) 赋给 PC,可以通过下面的指令来实现:

SUBS PC, LR, #4  // 注意 S ,指定了 S 意味着同时将SPSR 拷贝到 CPSR

该指令将寄存器 LR 中的值减 4 后,复制到程序计数器 PC 中,实现程序返回,同时将 SPSR_mode 寄存器内容复制到 CPSR 中。
当异常中断处理程序中使用了数据栈时,可以通过下面的指令在异常中断处理程序时保存被中断程序的执行现场,在退出异常中断处理程序时恢复被中断程序的执行现场。异常中断处理程序中使用的数据栈由用户提供。

subs lr, lr, #4
stmdb sp!, {r0-r12, lr}   // 保存现场 r0-r12 - reg_list
// user code
ldmia sp!, {r0-r12, pc}^  // 恢复现场 r0-r12 - reg_list

在上述指令中,reg_list 是异常中断处理程序中使用的寄存器列表。标识符 ^ 指示将 SPSR_mode 寄存器内容复制到 CPSR 寄存器中,该指令只能在特权模式下使用。

示例

arm irq,# qemu ARMv7-A 篇,arm,irq,fiq
1、假设在 instruction+0 指令执行完成后发生 irq/frq 异常
2、此时 PC 值 已经更新,指向 instruction+3
3、进入 irq/frq 异常后,LR_mode = PC -4,所以此时 LR 指向 instruction+2
4、irq/frq 异常处理完成之后,程序需要返回到 instruction+1 处执行,所以将此时的 LR_mode 寄存器的值 -4 赋给 PC。

代码实现

IRQ_Handler 汇编函数中,需要做下面

  • 上文保存
  • 获取中断号
  • 中断服务函数跳转到 C 中,并将中断号作为参数 0 传递
  • 中断完成
  • 下文恢复

不支持中断嵌套

不支持中断嵌套,在 IRQ 模式下处理中断

    .align 2
    .arm
    .weak IRQ_Handler
    .type IRQ_Handler, %function

IRQ_Handler:
    /* 执行到这里之前:
    * 1. lr_irq 保存有被中断模式中的下一条即将执行的指令的地址
    * 2. SPSR_irq 保存有被中断模式的 CPSR
    * 3. CPSR 中的 M4-M0 被设置为 10010, 进入到 irq 模式
    * 4. 跳到 0x18 的地方执行程序
    */

    /* 保存现场 */
    /* 在 irq 异常处理函数中有可能会修改 r0-r12, 所以先保存 */
    /* lr-4 是异常处理完后的返回地址, 也要保存 */
    sub lr, lr, #4
    stmfd sp!, {r0-r12, lr}

    ldr r1, =0x00a00000         /* imx6ull 的 GIC 基地址为 0x00a00000 */
    add r1, r1, #0X2000         /* GIC 基地址加 0X2000,也就是 GIC 的 CPU 接口端基地址 */
    ldr r0, [r1, #0XC]          /* GIC 的 CPU 接口端基地址加 0X0C 就是 GICC_IAR 寄存器,
                                    * GICC_IAR 寄存器保存这当前发生中断的中断号,我们要根据
                                    * 这个中断号来绝对调用哪个中断服务函数
                                    */

    push {r0, r1}               /* 保存 r0,r1 */
    bl system_irqhandler        /* 运行 C 语言中断处理函数,带有一个参数,保存在 R0 寄存器中 */
    pop {r0, r1}
    str r0, [r1, #0X10]         /* r0 存放当前中断号,
                                 * 中断执行完成,将中断号写如 GIC->EOIR(End Of Interrupt Register offset 0x10)
                                 */

    /* 恢复现场 */
    ldmfd sp!, {r0-r12, pc}^  /* ^会把 spsr_irq 的值恢复到 cpsr 里 */

支持中断嵌套

支持中断嵌套,在 SVC 模式下处理中断

    .align 2
    .arm
    .weak IRQ_Handler
    .type IRQ_Handler, %function

IRQ_Handler:
    push {lr}                   /* 保存lr地址 */
    push {r0-r3, r12}           /* 保存r0-r3,r12寄存器 */

    mrs r0, spsr                /* 读取spsr寄存器 */
    push {r0}                   /* 保存spsr寄存器 */

.if 0 /* on qemu platform it always return 0, i don't know why */
    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
                                */
.else
    ldr r1, =0x00a00000
.endif
    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 */

C 语言执行中断服务函数

由于在 IRQ_Handler 汇编函数中,对上文保存,下文恢复等都做了处理,所以 C 语言处理中断服务函数时,只需要执行对应的中断回调即可,文章来源地址https://www.toymoban.com/news/detail-721678.html

void system_irqhandler(unsigned int giccIar)
{

    uint32_t intNum = giccIar & 0x3FFUL;

    /* 检查中断号是否符合要求 */
    if ((intNum == 1023) || (intNum >= NUMBER_OF_INT_VECTORS))
    {
        return;
    }

    irqNesting++; /* 中断嵌套计数器加一 */

    /* 根据传递进来的中断号,在irqTable中调用确定的中断服务函数*/
    irqTable[intNum].irqHandler(intNum, irqTable[intNum].userParam);

    irqNesting--; /* 中断执行完成,中断嵌套寄存器减一 */
}

附录源码

.equ Mode_USR,        0x10
.equ Mode_FIQ,        0x11
.equ Mode_IRQ,        0x12
.equ Mode_SVC,        0x13
.equ Mode_MON,        0x16
.equ Mode_ABT,        0x17
.equ Mode_HYP,        0x1A
.equ Mode_UND,        0x1B
.equ Mode_SYS,        0x1F

.equ Stack_size,      0x400
.equ Stack_Start,     0x80200000

.equ Mode_USR_Stack,  Stack_Start + Stack_size
.equ Mode_FIQ_Stack,  Mode_USR_Stack + Stack_size
.equ Mode_IRQ_Stack,  Mode_FIQ_Stack + Stack_size
.equ Mode_SVC_Stack,  Mode_IRQ_Stack + Stack_size
.equ Mode_MON_Stack,  Mode_SVC_Stack + Stack_size
.equ Mode_ABT_Stack,  Mode_MON_Stack + Stack_size
.equ Mode_HYP_Stack,  Mode_ABT_Stack + Stack_size
.equ Mode_UND_Stack,  Mode_HYP_Stack + Stack_size
.equ Mode_SYS_Stack,  Mode_UND_Stack + Stack_size

    /* 定义一个 .isr_vector 段,链接脚本中定义相应的段来存放该段的数据 */
    .section .isr_vector, "a"
    .arm
    .align 2
    .globl __isr_vector
__isr_vector:
    ldr     pc, =Reset_Handler           /* Reset                  */
    ldr     pc, =Undefined_Handler       /* Undefined instructions */
    ldr     pc, =SVC_Handler             /* Supervisor Call        */
    ldr     pc, =PrefAbort_Handler       /* Prefetch abort         */
    ldr     pc, =DataAbort_Handler       /* Data abort             */
    .word   0                            /* RESERVED               */
    ldr     pc, =IRQ_Handler             /* IRQ interrupt          */
    ldr     pc, =FIQ_Handler             /* FIQ interrupt          */

    /* 余下的指令的放在 .text 中,所以用 .text 指定段 */
/* Reset Handler */
    .text
    .arm
    .align 2
    .globl   Reset_Handler
    .weak    Reset_Handler
    .type    Reset_Handler, %function
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, =0x80000000

    dsb
    isb
    mcr p15, 0, r0, c12, c0, 0
    dsb
    isb
#endif

    /* 模式切换并设置 sp 地址 */
    cps     #Mode_FIQ
    ldr     sp, =Mode_FIQ_Stack

    cps     #Mode_IRQ
    ldr     sp, =Mode_IRQ_Stack

    cps     #Mode_SVC
    ldr     sp, =Mode_SVC_Stack

    cps     #Mode_MON
    ldr     sp, =Mode_MON_Stack

    cps     #Mode_ABT
    ldr     sp, =Mode_ABT_Stack

    cps     #Mode_HYP
    ldr     sp, =Mode_HYP_Stack

    cps     #Mode_UND
    ldr     sp, =Mode_UND_Stack

    /* sys mode and user have common sp register */
    cps     #Mode_SYS
    ldr     sp, =Mode_SYS_Stack

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

    /* clear bss */
    ldr r1, =__bss_start__
    ldr r2, =__bss_end__
    mov    r0, #0
bss_loop:
    cmp     r1, r2
    itt     lt
    strlt   r0, [r1], #4
    blt    bss_loop


    /* 使能IRQ中断 */
    mrs r0, cpsr        /* 读取cpsr寄存器值到r0中 */
    bic r0, r0, #0x80   /* 将r0寄存器中bit7清零,也就是CPSR中的I位清零,表示允许IRQ中断 */
    msr cpsr, r0        /* 将r0重新写入到cpsr中 */

swi_code:
    swi 0x123  /* 执行此命令, 触发SWI异常, 进入0x8执行 */

und_code:
    nop              /* for debug */
    .word 0xeeadc0de /* undefine instruction */
    nop              /* for debug */
    .word 0xFFFFFFFF /* undefine instruction */
    nop              /* for debug */

    ldr   r0, =main
    bx    r0


    .align 2
    .arm
    .weak Undefined_Handler
    .type Undefined_Handler, %function
Undefined_Handler:
    /* 执行到这里之前:
    * 1. lr_und 保存有被中断模式中的下一条即将执行的指令的地址
    * 2. SPSR_und 保存有被中断模式的CPSR
    * 3. CPSR 中的 M4-M0 被设置为 11011, 进入到 und 模式
    * 4. 跳到 0x4 的地方执行程序
    */

    /* 在 und 异常处理函数中有可能会修改 r0-r12, 所以先保存 */
    /* lr 是异常处理完后的返回地址, 也要保存 */
    stmdb sp!, {r0-r12, lr}

    /* 保存现场 */
    /* 处理 und 异常 */
    mrs r0, cpsr
    ldr r1, =und_string
    bl printException

    /* 恢复现场 */
    ldmia sp!, {r0-r12, pc}^  /* ^ 会把 spsr 的值恢复到 cpsr 里 */

und_string:
    .string "undefined instruction exception"

    .align 2
    .arm
    .weak SVC_Handler
    .type SVC_Handler, %function
SVC_Handler:
    /* 执行到这里之前:
    * 1. lr_svc 保存有被中断模式中的下一条即将执行的指令的地址
    * 2. SPSR_svc 保存有被中断模式的 CPSR
    * 3. CPSR 中的 M4-M0 被设置为 10011, 进入到 svc 模式
    * 4. 跳到 0x08 的地方执行程序
    */

    /* 保存现场 */
    /* 在 swi 异常处理函数中有可能会修改 r0-r12, 所以先保存 */
    /* lr 是异常处理完后的返回地址, 也要保存 */
    stmdb sp!, {r0-r12, lr}

.if 0
    mov r4, lr /* LR 由硬件自动保存软中断指令下一条指令的地址 */

    /* 处理swi异常 */
    mrs r0, cpsr
    ldr r1, =swi_string
    bl printException

    sub r0, r4, #4 /* LR 为硬件自动保存 SWI xxx 指令的下一条指令地址,LR – 4 就是 SWI 指令地址,由 SWI 指令编码知识可知,SWI 指令低 24 位保存有软中断号 */
    bl printSWIVal
.else
    ldr r4,[lr, #-4] /* LR 由硬件自动保存软中断指令下一条指令的地址,指令地址存放的是指令的操作码,将操作码取出,低 24 位置,即为软中断号 */
    bic r0, r4, #0xff000000 /* LR 为硬件自动保存 SWI xxx 指令的下一条指令地址,LR – 4 就是 SWI 指令地址,由 SWI 指令编码知识可知,SWI 指令低 24 位保存有软中断号 */
    push {r0}

    /* 处理swi异常 */
    mrs r0, cpsr
    ldr r1, =swi_string
    bl printException

    pop {r0}

    bl printSWIVal
.endif

    /* 恢复现场 */
    ldmia sp!, {r0-r12, pc}^  /* ^ 会把 spsr 的值恢复到 cpsr 里 */

swi_string:
    .string "swi exception"


    .align 2
    .arm
    .weak PrefAbort_Handler
    .type PrefAbort_Handler, %function
PrefAbort_Handler:
    ldr r0, =PrefAbort_Handler
    bx r0

    .align 2
    .arm
    .weak DataAbort_Handler
    .type DataAbort_Handler, %function
DataAbort_Handler:
    ldr r0, =DataAbort_Handler
    bx r0

.if 1
    /* 不支持中断嵌套,在 IRQ 模式下处理中断 */
    .align 2
    .arm
    .weak IRQ_Handler
    .type IRQ_Handler, %function

IRQ_Handler:
    /* 执行到这里之前:
    * 1. lr_irq 保存有被中断模式中的下一条即将执行的指令的地址
    * 2. SPSR_irq 保存有被中断模式的 CPSR
    * 3. CPSR 中的 M4-M0 被设置为 10010, 进入到 irq 模式
    * 4. 跳到 0x18 的地方执行程序
    */

    /* 保存现场 */
    /* 在 irq 异常处理函数中有可能会修改 r0-r12, 所以先保存 */
    /* lr-4 是异常处理完后的返回地址, 也要保存 */
    sub lr, lr, #4
    stmfd sp!, {r0-r12, lr}

    ldr r1, =0x00a00000         /* imx6ull 的 GIC 基地址为 0x00a00000 */
    add r1, r1, #0X2000         /* GIC 基地址加 0X2000,也就是 GIC 的 CPU 接口端基地址 */
    ldr r0, [r1, #0XC]          /* GIC 的 CPU 接口端基地址加 0X0C 就是 GICC_IAR 寄存器,
                                    * GICC_IAR 寄存器保存这当前发生中断的中断号,我们要根据
                                    * 这个中断号来绝对调用哪个中断服务函数
                                    */

    push {r0, r1}               /* 保存 r0,r1 */
    bl system_irqhandler        /* 运行 C 语言中断处理函数,带有一个参数,保存在 R0 寄存器中 */
    pop {r0, r1}
    str r0, [r1, #0X10]         /* r0 存放当前中断号,
                                 * 中断执行完成,将中断号写如 GIC->EOIR(End Of Interrupt Register offset 0x10)
                                 */

    /* 恢复现场 */
    ldmfd sp!, {r0-r12, pc}^  /* ^会把 spsr_irq 的值恢复到 cpsr 里 */

.else
    /* 支持中断嵌套,在 SVC 模式下处理中断 */
    .align 2
    .arm
    .weak IRQ_Handler
    .type IRQ_Handler, %function

IRQ_Handler:
    push {lr}                   /* 保存lr地址 */
    push {r0-r3, r12}           /* 保存r0-r3,r12寄存器 */

    mrs r0, spsr                /* 读取 spsr 寄存器 */
    push {r0}                   /* 保存 spsr 寄存器 */

.if 0 /* it always return 0, i don't know why */
    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
                                */
.else
    ldr r1, =0x00a00000         /* imx6ull 的 GIC 基地址为 0x00a00000 */
.endif
    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]         /* r0 存放当前中断号,
                                 * 中断执行完成,将中断号写如 GIC->EOIR(End Of Interrupt Register offset 0x10)
                                 */

    pop {r0}
    msr spsr_cxsf, r0           /* 恢复 spsr */

    pop {r0-r3, r12}            /* r0-r3,r12出栈 */
    pop {lr}                    /* lr出栈 */
    subs pc, lr, #4             /* 将lr-4赋给pc */

.endif /* 中断嵌套宏判断 */

    .align 2
    .arm
    .weak FIQ_Handler
    .type FIQ_Handler, %function
FIQ_Handler:
    ldr r0, =FIQ_Handler
    bx r0


    .end

到了这里,关于【ARM】-IRQ 和 FIQ 异常中断处理程序的返回的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ARM处理器有哪些工作模式和寄存器?各寄存器作用是什么?ARM异常中断处理流程?

    快速学习嵌入式开发其他基础知识? 返回专栏总目录 《嵌入式工程师自我修养/C语言》 Tip📌:鼠标悬停双虚线/句,可获得更详细的描述   ARM处理器有多种工作模式,如下表所示。应用程序正常运行时,ARM处理器工作在 用户模式(User mode) ,当程序运行出错或有中

    2024年02月21日
    浏览(113)
  • IRQ Handler 的使用——以USART串口接收中断分别在标准库与HAL库版本下的举例

     前言: 1.中断系统及EXTI外部中断知识点见我的博文: 9.中断系统、EXTI外部中断_eirq-CSDN博客 文章浏览阅读301次,点赞7次,收藏6次。EXTI(Extern Interrupt)外部中断EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决

    2024年02月01日
    浏览(33)
  • ARM实验6-基于中断的按键处理程序实验

    一、实验名称:基于中断的按键处理程序实验 二、实验目的:         1.掌握ARM处理器的中断处理过程。         2.掌握ARM处理器中断服务程序的编写方法。         3.通过该编程实验,进一步巩固和强化学生ARM汇编编程的能,ARM应用程序框架,培养学生实际应用的

    2024年02月08日
    浏览(42)
  • 【ARM】-异常与中断

    中断(Interrupt)机制,即处理器在顺序执行程序指令流的过程中突然被别的请求打断而中止执行当前的程序,转而去处理别的事情,待其处理完了别的事情,然后重新回到之前程序中断的点继续执行之前的程序指令流,其要点如下 中断请求、中断源 打断处理器执行程序指令流的

    2024年02月12日
    浏览(38)
  • 【ARM】-进入和退出异常中断的过程

    ARM 指令为三级流水线:取地,译码和执行 进入中断的时候 LR = PC -4 当出现异常时,ARM 内核自动执行以下操作 将 cpsr 寄存器的值保存到 spsr_mode 寄存器中,备份寄存器指明了当前处理器的操作模式 将程序返回地址存放在 lr_mode 寄存器中 将CPSR模式位修改为与异常类型相关联的

    2024年02月14日
    浏览(59)
  • ARM-进入和退出异常中断的过程(六)

    ARM 指令为三级流水线:取地,译码和执行 进入中断的时候 LR = PC -4 当出现异常时,ARM 内核自动执行以下操作 将 cpsr 寄存器的值保存到 spsr_mode 寄存器中,备份寄存器指明了当前处理器的操作模式 将程序返回地址存放在 lr_mode 寄存器中 将CPSR模式位修改为与异常类型相关联的

    2024年02月11日
    浏览(43)
  • [ARM 汇编]进阶篇—数据处理指令—2.2.3 子程序调用和返回指令

    在 ARM 汇编中,子程序(也称为函数)是一段可重用的代码,用于执行特定任务。子程序调用和返回指令用于控制程序从一个位置跳转到子程序,执行子程序后再返回到跳转前的位置继续执行。在本节中,我们将详细介绍 ARM 汇编中的子程序调用和返回指令,并通过实例帮助你

    2024年02月07日
    浏览(52)
  • ARM裸机 - 中断处理编程实战_arm断电文件内容丢失

    #define exception_vector_table_base 0xD0037400 #define exception_reset (exception_vector_table_base + 0x00) #define exception_undef (exception_vector_table_base + 0x04) #define exception_sotf_int (exception_vector_table_base + 0x08) #define exception_prefetch (exception_vector_table_base + 0x0C) #define exception_data (exception_vector_table_base + 0x10) #de

    2024年04月16日
    浏览(80)
  • ARM单片机中断处理过程解析

    前言 中断,在单片机开发中再常见不过了。当然对于中断的原理和执行流程都了然于胸,那么对于ARM单片机中断的具体处理行为,你真的搞清楚了吗? 今天来简单聊一聊,ARM单片机中断处理过程中的具体行为是什么样的,搞清楚了这些,让你彻底理解中断是如何执行的。 掌

    2024年02月06日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包