精华内容
下载资源
问答
  • <p:colorscheme colors="#ffffff,#000000,#00007d,#000000,#9999ff,#9999cc,#666699,#...发生IRQ中断处理过程: 1.正在执行用户程序; <p:colorscheme colors="#ffffff,#000000,#00007d...
         
    <p:colorscheme colors="#ffffff,#000000,#00007d,#000000,#9999ff,#9999cc,#666699,#cccce6"></p:colorscheme>
     
    
    发生IRQ中断处理过程:
    1.正在执行用户程序;
    <p:colorscheme colors="#ffffff,#000000,#00007d,#000000,#9999ff,#9999cc,#666699,#cccce6"></p:colorscheme>  
    2.外部中断0发生中断;
    <p:colorscheme colors="#ffffff,#000000,#00007d,#000000,#9999ff,#9999cc,#666699,#cccce6"></p:colorscheme>  
    3.VIC硬件将中断服务程序地址装入VICVectAddr寄存器;
    <p:colorscheme colors="#ffffff,#000000,#00007d,#000000,#9999ff,#9999cc,#666699,#cccce6"></p:colorscheme>  
    4.程序跳转至异常向量表中IRQ入口0x0018处;
    <p:colorscheme colors="#ffffff,#000000,#00007d,#000000,#9999ff,#9999cc,#666699,#cccce6"></p:colorscheme>  
    5.执行指令跳转至VICVectAddr寄存器中的中断服务地址;
    <p:colorscheme colors="#ffffff,#000000,#00007d,#000000,#9999ff,#9999cc,#666699,#cccce6"></p:colorscheme>  
    6.中断服务程序执行完毕,返回被中断的用户程序继续执行被中断的代码。
    展开全文
  • A: 从栈地址开始,栈顶为AT91SAM7S64的16K片内RAM尽头0x00204000IRQ_STACK_SIZE = 3*8*4FIQ_STACK_SIZE = 0x004ABT_STACK_SIZE = 0x004UND_STACK_SIZE = 0x004SVC_STACK_SIZE = 0x800SYS_STACK_SIZE = 0x400...

    A: 从栈地址开始,栈顶为AT91SAM7S64的16K片内RAM尽头0x00204000
    IRQ_STACK_SIZE = 3*8*4
    FIQ_STACK_SIZE = 0x004
    ABT_STACK_SIZE = 0x004
    UND_STACK_SIZE = 0x004
    SVC_STACK_SIZE = 0x800
    SYS_STACK_SIZE = 0x400

    irq栈为什么用3*8*4=96B呢?因为irq最多8级嵌套,ARM字长4B,而3,是由于每次进栈均破坏了3个寄存器r0、spsr、lr,所以需要压栈保存的也就是3。计算十分精准,没有一个字浪费,这是AT第一牛X的地方。

    当irq发生时,下列操作处理器自动完成:
    1。r14(irq)=返回地址
    2。spsr(irq)=cpsr(中断发生前的模式)
    3。改cpsr,成模式为irq,禁止irq中断。
    4。设pc,跳转到0x00000018去

    下面看中断0x00000018指向的irq_handle代码:

    ;因为要继续调用函数,lr会被冲掉,所以压irq栈
    sub lr,lr,#4
    stmfd sp!,{lr}

    ;将r0和spsr压irq栈,因为下面用到r0,spsr
    mrs r14,spsr
    stmfd sp!,{r0,r14}

    ;写IVR,支持保护模式,普通模式无效
    ;释放NIRQ,清除保护模式下中断源
    ldr r14,=AT91C_BASE_AIC
    ldr r0,[r14,#AIC_IVR]
    str r14,[r14, #AIC_IVR]

    ;允许中断嵌套,由irq模式切换入svc模式
    msr cpsr_c, #ARM_MODE_SVC

    ;保存scratch和被使用到的寄存器、lr入svc堆栈
    stmfd sp!, {r1-r3, r12, r14}

    ;跳转到AIC_IVR指向的中断服务程序地址
    mov r14,pc
    bx r0

    ;恢复scratch、被用到的寄存器、lr
    ldmia sp!,{r1-r3, r12, r14}

    ;禁止irq中断嵌套,由svc切换到irq模式。
    msr cpsr_c,#I_BIT | ARM_MODE_IRQ

    ;写AIC_EOICR
    ldr r14,=AT91C_BASE_AIC
    str r14,[r14, #AIC_EOICR]

    ;恢复spsr、r0
    ldmia sp!,{r0, r14}
    msr spsr_cxsf, r14

    ;中断返回
    ldmia sp!, {pc}^

    以上就是全部,让我惊叹的是如上做法支持了中断嵌套,想了想,自己以前搞的东西还真是全部回避回去了,也就是说,以前各个中断并没有优先级区分,进了中断就关门i->I。中断服务程序执行完了再打开,优点是简单明了,缺点是中断服务程序必须迅速处理完.

    转载于:https://www.cnblogs.com/shangdawei/p/4538994.html

    展开全文
  • ARM异常处理(IRQ中断处理)总结1

    千次阅读 2019-02-26 19:46:34
    还有要从硬件角度理解的是在CPU设计的时候这些异常就已经定义好了在发生相应的异常时候CPU就自动的转到在异常向量表里的地址处去执行这个过程是不需要软件干预的因此就简单了我们只要把出现相应的异常时候处理过程的...

    ARM A8的异常处理表如下
    ARM异常处理(IRQ中断处理)总结1
    可以看到vector table的基地址是不固定的但是所有异常的偏移地址是固定的。这张表也为了体现这个偏移量,还有要从硬件角度理解的是在CPU设计的时候这些异常就已经定义好了在发生相应的异常时候CPU就自动的转到在异常向量表里的地址处去执行这个过程是不需要软件干预的因此就简单了我们只要把出现相应的异常时候处理过程的函数名(函数名就是这个函数体的指针)放在相应的地址里边就可以执行了举例说明。以三星S5PV210为例,我们根据官方的Application Node可以查到在iROM中定义的Exeception vector table的基地址是0xD003_7400(其实这个地址在移植操作系统后会更改)那么我们就根据上图中的偏移地址可以把定义好的异常处理函数直接放在相对应的地址上代码可以写成
    #define Exception_base 0xd0037400
    #defien Exception_rest (Exception_base + 0x00)

    #define rException_rest ((volatile unsigned int)Exception_rest)

    假如用C语言定义了一个void ex_rest(void)函数那么就可以rException_rest=ex_rest;
    这样的话就可以在产生REST异常的时候直接跳转到ex_rest这个函数执行了。
    但是中断就要不一样一些因为中断是需要返回的因此需要考虑的问题是如何保存CPU的上下文,这个一般都在汇编中实现(其实也是格式化了的已经)一般的写法都是
    ldr sp, =IRQ_STACK
    sub lr, lr, #4
    stmfd sp!, {r0-r12, lr}
    bl irq_handler
    ldmfd sp!, {r0-r12, pc}^
    这个段代码要理解需要了解三个知识点:
    第一:ldr sp, =IRQ_STACK这是在给C语言提供栈的保障可以让C语言运行。
    第二:sub lr, lr, #4和 stmfd sp!, {r0-r12, lr}
    先要了解下面这张图
    ARM异常处理(IRQ中断处理)总结1
    我们现在要从SVC转换模式到IRQ因此需要保存的寄存器是R0~R12因为是共用的这两个模式之间,还有一个就是SVC下的PC(在模式跳转的时候硬件会把SVC下的PC直接保存到IRQ下的lr里边)因为不保存这个就没办法返回了但是要减4个字节这是因为ARM的流水线的缘故(大概了解流水线反正你记住ARM的流水线都是提前4个字节就可以了)这条语句就把所有的需要保存的数据都保存到了IRQ下的栈里边了,其实同时CPU也帮你把CPSR保存到了SPSR里边去了这个过程是自动的。
    第三: ldmfd sp!, {r0-r12, pc}^
    这个过程和上面的压栈过程正好是相反的这个好理解主要是后边的‘^’符号的作用这个符号就是把SPSR里的内容直接回复给CPSR这样就完全回到了SVC模式中断完美返回了。

    转载于:https://blog.51cto.com/13638458/2355263

    展开全文
  • linux irq中断过程解析(基于ARM处理器)

    千次阅读 2017-08-10 08:17:11
    ARM linux irq中断处理流程。

    linux irq中断过程解析(基于ARM处理器)

    1、中断向量

    1.1、__vectors_start

            .section .vectors, "ax", %progbits
    __vectors_start:
            W(b)    vector_rst
            W(b)    vector_und
            W(ldr)  pc, __vectors_start + 0x1000
            W(b)    vector_pabt
            W(b)    vector_dabt
            W(b)    vector_addrexcptn
             W(b)    vector_irq // irq中断向量入口
            W(b)    vector_fiq

    1.2、vector_stub

     

            .macro  vector_stub, name, mode, correction=0
            .align  5
    
    
    vector_\name:   
            .if \correction
    sub     lr, lr, #\correction //中断返回地址修正,ARM处理器有取指、译码、执行等多级流水线,pc指向取值的指令地址,硬件中断会将pc-4存在lr,此时lr指向译码指令地址而不是正在执行的指令地址,因此需要再修正中断返回地址
            .endif
    
    
            @
            @ Save r0, lr_<exception> (parent PC) and spsr_<exception>
            @ (parent CPSR)
            @
     stmia   sp, {r0, lr}            @ save r0, lr // 保存r0, lr到irq栈
    mrs     lr, spsr // 保存中断前的cpsr(中断时硬件自动将中断前的cpsr保存到spsr)
    str     lr, [sp, #8]            @ save spsr // 保存cpsr到irq栈,此时irq栈的内容为r0,lr,cpsr
    
    
            @
            @ Prepare for SVC32 mode.  IRQs remain disabled.
            @
            mrs     r0, cpsr // 此时IRQs仍然处于禁止状态(中断的时候由硬件禁止)
            eor     r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE) // 设置svc状态位
            msr     spsr_cxsf, r0 // 保存cpsr到spsr
    
    
            @
            @ the branch table must immediately follow this code
            @
    and     lr, lr, #0x0f // 前面已经将中断前的cpsr保存到lr,此处获取中断前的模式,用于判断是用户态被中断还是内核态被中断
     THUMB( adr     r0, 1f                  )
     THUMB( ldr     lr, [r0, lr, lsl #2]    )
            mov     r0, sp // sp保存到r0,切换模式后sp会改变成对应模式的sp,栈里面已经保存了部分中断上下文r0,lr,cpsr
     ARM(   ldr     lr, [pc, lr, lsl #2]    ) 
     movs    pc, lr                  @ branch to handler in SVC mode // irq/fiq中断向量表正好紧接当前指令之后,即pc等价于irq/fiq中断向量表基地址,lr为中断前模式,pc + lr * 4即得到对应模式的中断入口函数地址,例如__irq_usr、__irq_svc,从不同模式进入中断,处理流程有所不同,此处跳转到对应模式的中断处理程序
    ENDPROC(vector_\name)
    

    1.3、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) // svc模式进入中断
            .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

    2、中断处理

    2.1、__irq_usr(用户模式进入中断)

    2.1.1、usr_entry

     
            .macro  usr_entry, trace=1, uaccess=1
     UNWIND(.fnstart        )
     UNWIND(.cantunwind     )       @ don't unwind the user space                                                                                                                                     
            sub     sp, sp, #S_FRAME_SIZE // 预留72字节保留中断上下文
     ARM(   stmib   sp, {r1 - r12}  ) // 1.2中已经保存了r0,lr,cpsr
     THUMB( stmia   sp, {r0 - r12}  )
    
    
     ATRAP( mrc     p15, 0, r7, c1, c0, 0)
     ATRAP( ldr     r8, .LCcralign)
    
    
            ldmia   r0, {r3 - r5} // r0为切换模式前的sp,sp栈里面保存了中断前的r0,lr,cpsr,即中断上下文的一部分寄存器,将r0,lr,cpsr装载到r3-r5
            add     r0, sp, #S_PC           @ here for interlock avoidance // sp + pc偏移 -> r0,r0指向栈地址用于保存中断返回地址pc
            mov     r6, #-1                 @  ""  ""     ""        "" // r6 = 0xffffffff
    
    
            str     r3, [sp]                @ save the "real" r0 copied // 将中断前的r0寄存器值保存到但前栈,当前栈内容变为r0-r12
                                            @ from the exception stack
    
    
     ATRAP( ldr     r8, [r8, #0])
    
    
            @
            @ We are now ready to fill in the remaining blanks on the stack:
            @
            @  r4 - lr_<exception>, already fixed up for correct return/restart
            @  r5 - spsr_<exception>
            @  r6 - orig_r0 (see pt_regs definition in ptrace.h)
            @
            @ Also, separately save sp_usr and lr_usr
            @
            stmia   r0, {r4 - r6} // r4-r6从pc地址开始入栈,r4-r6的内容依次为lr(pc),cpsr,0xffffffff
     ARM(   stmdb   r0, {sp, lr}^                   ) // r0指向了pc保存地址,sp、lr保存地址介于r0-r12及pc之间,stmdb将用户态的sp、lr保存在栈中间,保存之后栈内容依次是r0-r12,sp,lr,pc,cpsr,0xffffffff,此时中断前的寄存器等都已经保存到栈里面了
     THUMB( store_user_sp_lr r0, r1, S_SP - S_PC    )
    
    
            .if \uaccess
            uaccess_disable ip
            .endif
    
    
            @ Enable the alignment trap while in kernel mode
     ATRAP( teq     r8, r7)
     ATRAP( mcrne   p15, 0, r8, c1, c0, 0)
    
    
            @
            @ Clear FP to mark the first stack frame
            @
            zero_fp
    
    
            .if     \trace
    #ifdef CONFIG_TRACE_IRQFLAGS
            bl      trace_hardirqs_off
    #endif
            ct_user_exit save = 0
            .endif
            .endm

     

    2.1.2、irq_handler

            .macro  irq_handler
    #ifdef CONFIG_MULTI_IRQ_HANDLER
            ldr     r1, =handle_arch_irq // 处理器相关中断处理函数地址
            mov     r0, sp // sp栈保存了中断上下文
            badr    lr, 9997f // handler_arch_irq返回地址,即irq_handler的下一条指令地址,__irq_usr中的get_thread_info tsk指令
            ldr     pc, [r1] // 跳转到irq中断处理函数
    #else
            arch_irq_handler_default
    #endif
    9997:
            .endm

     

    2.1.3、ret_to_user_from_irq

    ENTRY(ret_to_user_from_irq)
            ldr     r1, [tsk, #TI_FLAGS]
            tst     r1, #_TIF_WORK_MASK // 检查是否有挂起的待处理任务,用户进程被中断后有可能需要重新调度等
            bne     slow_work_pending // 处理挂起的待处理任务
    no_work_pending:
            asm_trace_hardirqs_on save = 0
    
    
            /* perform architecture specific actions before user return */
            arch_ret_to_user r1, lr
            ct_user_enter save = 0
    
            restore_user_regs fast = 0, offset = 0
    ENDPROC(ret_to_user_from_irq)

     

    2.1.4 restore_user_regs

            .macro  restore_user_regs, fast = 0, offset = 0
            uaccess_enable r1, isb=0
    #ifndef CONFIG_THUMB2_KERNEL
            @ ARM mode restore
            mov     r2, sp // sp保存了中断上下文,即用户态寄存器、返回地址等信息
            ldr     r1, [r2, #\offset + S_PSR]      @ get calling cpsr // 获取保存的用户态cpsr(里面已经设置了用户态模式标志位)
            ldr     lr, [r2, #\offset + S_PC]!      @ get pc // 获取中断返回地址,用户模式被中断的指令执行地址
            msr     spsr_cxsf, r1                   @ save in spsr_svc // 用户态cpsr保存到spsr
    #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
            @ We must avoid clrex due to Cortex-A15 erratum #830321
            strex   r1, r2, [r2]                    @ clear the exclusive monitor
    #endif
            .if     \fast
            ldmdb   r2, {r1 - lr}^                  @ get calling r1 - lr
            .else
            ldmdb   r2, {r0 - lr}^                  @ get calling r0 - lr // sp栈里面保存的数据恢复到用户态r0-lr (有部分寄存器svc模式与usr模式不共用)
            .endif
            mov     r0, r0                          @ ARMv5T and earlier require a nop
                                                    @ after ldm {}^
            add     sp, sp, #\offset + S_FRAME_SIZE // 释放sp中断上下文所占用的内存
            movs    pc, lr                          @ return & move spsr_svc into cpsr // 跳转到被中断的用户态指令地址,并且恢复spsr到cpsr(cpu模式切换)
    ......
    #endif  /* !CONFIG_THUMB2_KERNEL */
            .endm

     

    2.1.5、__irq_usr

            .align  5
    __irq_usr:                                                                                                                                                                                        
            usr_entry // 保存用户态寄存器到栈里面(保存中断上下文)
            kuser_cmpxchg_check
            irq_handler // 调用irq中断处理函数
            get_thread_info tsk //- 获取当前进程/线程的thread_info地址
            mov     why, #0
            b       ret_to_user_from_irq // 从irq模式返回到用户模式(中断并没有改变mmu,因此不需要切换mmu)
     UNWIND(.fnend          )
    ENDPROC(__irq_usr)

     

    2.2、__irq_svc(svc模式进入中断)

    2.2.1、__irq_svc

            .align  5
    __irq_svc:                                                                                                                                                                                        
            svc_entry // 保存中断上下文,与用户模式不同的是,中断前后处于同一模式,使用同一套寄存器,保存中断上下文方法稍微有些不同,此处不过多解释
            irq_handler // 中断处理,与从用户模式进入中断是一样的
    
    
    #ifdef CONFIG_PREEMPT
            get_thread_info tsk
            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 // 内核态抢占(需要打开CONFIG_PREEMPT开关)
    #endif
    
    
            svc_exit r5, irq = 1                    @ return from exception // svc_entry已经将中断前的cpsr保存在r5寄存器中
     UNWIND(.fnend          )
    ENDPROC(__irq_svc)

     

    2.2.2、svc_exit

      
            .macro  svc_exit, rpsr, irq = 0
            .if     \irq != 0
    ......
            .else
            @ IRQs off again before pulling preserved data off the stack
            disable_irq_notrace
    #ifdef CONFIG_TRACE_IRQFLAGS
            tst     \rpsr, #PSR_I_BIT
            bleq    trace_hardirqs_on
            tst     \rpsr, #PSR_I_BIT
            blne    trace_hardirqs_off
    #endif
            .endif
            uaccess_restore
    
    
    #ifndef CONFIG_THUMB2_KERNEL
            @ ARM mode SVC restore
            msr     spsr_cxsf, \rpsr // 中断前cpsr保存到spsr
    #if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_32v6K)
            @ We must avoid clrex due to Cortex-A15 erratum #830321
            sub     r0, sp, #4                      @ uninhabited address
            strex   r1, r2, [r0]                    @ clear the exclusive monitor
    #endif
            ldmia   sp, {r0 - pc}^                  @ load r0 - pc, cpsr // 从栈里面恢复中断上下文,并且恢复cpsr
    #else
    ......
    #endif
            .endm

     

    展开全文
  • 本文主要以ARM体系结构下的中断处理为例,讲述整个中断处理过程中的硬件行为和软件动作。文中大量参考了这篇博文:https://www.cnblogs.com/hpunix/articles/6213708.html,为了更好的理解这部分内容,也做了一些...
  • linux中断处理过程

    2017-11-20 09:24:38
    参考:http://www.uml.org.cn/embeded/201304021.asp Linux中的中断处理 ...与Linux设备驱动中中断处理相关的首先是申请与释放IRQ的API request_irq()和free_irq(), request_irq
  • linux系统下驱动中,中断异常的处理过程,与裸机开发中断处理过程非常类似。通过简单的回顾裸机开发中断处理部分,来参考学习linux系统下中断处理流程。 一、ARM裸机开发中断处理过程 以S3C2440的裸机开发启动...
  • Linux中断处理过程

    2010-07-08 19:32:00
    3.PIC将中断向量由INT发送到CPU,进入软件中断处理。 软件处理的一般过程: 1.初始化阶段向linux内核注册中断处理程序。 2.中断发生时,通过中断描述符表IDT获取中断服务例程(ISR)链表入口。 3.调用do_irq()程序,...
  • 本文主要以ARM体系结构下的中断处理为例,讲述整个中断处理过程中的硬件行为和软件动作。具体整个处理过程分成三个步骤来描述: 1、第二章描述了中断处理的准备过程 2、第三章描述了当发生中的时候,ARM硬件的行为...
  • s5pv210中断处理过程

    2017-08-10 13:48:57
    一、异常处理的两个过程第一,异常向量表的跳转第二,进入异常处理程序中二、异常处理中的第一个...2、中断处理要先在汇编文件中进行,主要的过程是保护现场和恢复现场保护现场:主要是设置IRQ栈、保存LR和保存r0...
  • 参考文档: (1)http://blog.chinaunix.net/uid-23769728-id-3079164.html... 第四部分:中断的处理过程-C语言部分 中断处理的整体框图 按照x86处理器在外部中断发生时的硬件逻辑,在do_IRQ被调用时,处理器已经屏...
  • 4.调用irq_desc[irq]->handle 5.irq_desc[irq]->handle过程s3c_irqext_ack(unsigned int irqno)主要清中断{ mask = __raw_readl(S3C24XX_EINTMASK);读中断掩码__raw_writel(bit, S3C24XX_EINTPEND);清零req = __raw_...
  • 在wince中断处理过程一文中我们知道在驱动中如何申请系统中断号、如何将中断和事件关联起来等,但是并不知道这些操作更底层的实现方式。在这里我们来对wince中断机制做一个更深入的理解,以zc702运行的wince7为例。 ...
  • linux中断系统那些事之----中断处理过程 以外部中断irq为例来说明,当外部硬件产生中断时,linux的处理过程。首先先说明当外部中断产生时,硬件处理器所做的工作如下: R14_irq = address of next instruction ...
  • 当发生中断之后,linux系统在汇编阶段经过一系列跳转,最终...linux驱动中断处理C程序部分,主要涉及linux中断系统数据结构的初始化和C程序的具体执行跳转。 一、中断处理数据结构 linux内核将所有的中断统一编...
  • 转自:... 以外部中断irq为例来说明,当外部硬件产生中断时,linux的处理过程。首先先说明当外部中断产生时,硬件处理器所做的工作如下: R14_irq = address of next instruction to be executed...
  • s3c2440处理IRQ过程

    2013-12-13 16:51:09
    注意ucos代码(也就是main函数中的代码)和启动代码都是在Supervisor模式下工作的。而IRQ是工作在外部中断模式下的,这两种模式用的寄存器组是...(1):如果让CPU能够处理中断,即不屏蔽IRQ中断,则需用户手动设定CRPS中
  • // arch/x86/kernel/irqinit.c void __init init_IRQ(void) ... * On cpu 0, Assign ISA_IRQ_VECTOR(irq) to IRQ 0..15. * If these IRQ's are handled by legacy interrupt-controllers like PIC, ...
  • 本章主要讲中断的注册过程 //待填坑
  • 中断处理过程

    千次阅读 2011-06-23 14:21:00
    在这里主要谈外部中断处理过程,其中异常,陷阱的处理过程比较简单(相比外部中断,没有中断控制器,没有中断的注册,管理简单)。 中断号(irq号):在实地址模式时,irq号就是中断向量号。i386最多有256个中断...

空空如也

空空如也

1 2 3 4 5 ... 15
收藏数 296
精华内容 118
关键字:

irq中断处理过程