• 【linux kernel】 中断处理-中断上半部


     

     

    欢迎转载,转载时需保留作者信息,谢谢。

    邮箱:tangzhongp@163.com

    博客园地址:http://www.cnblogs.com/embedded-tzp

    Csdn博客地址:http://blog.csdn.net/xiayulewa

     

    环境: http://www.cnblogs.com/embedded-tzp/p/4443876.html

     

     

    1. arm硬件中断

    从头介绍中断原理太麻烦,一般来说看这篇文章的人对中断必然已经有了一定的认识。不管哪款处理器,中断的基本概念是一样的:

    中断向量表。

    中断优先级。

    中断现场保护与恢复。

     

    1.1. 中断向量表

     

    中断向量表,程序发生中断后会跳转到该表执行,一般在里面放置mov pc, addr_of_isr_func形式的指令,以中断向量表为跳板,跳转到中断服务程序中。

    一般处理器中断向量表地址是固定的,arm920t固定在0x00000000,或者0xFFFF0000处,其地址是通过配置CP15Register 1实现的。详细可阅读ARM920T_TRM1_S.pdf

    默认中断向量表是在0x00000000处,arm920t的中断向量表如下:

    clip_image002[4]

             clip_image004[4]

    上图为arm中断处理的流程,在程序正常运行时, 发生定时器中断,跳转到中断向量表处执行对应指令,而irq中断向量地址指令为goto irq_isr, 跳转到中断irq中断服务程序,此时首先保存现场,执行完中断逻辑后,再恢复现场,后中断返回,从之前被中断处的下一条指令继续运行。

     

     

     

    1.2. Linux内核中的中断向量表

    entry-armv.S (srcarcharmkernel)中定义中断向量表。

        .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

    W(b)    vector_fiq

     

     

    1.3. linux中断初始化配置

     

    硬件:有主中断SRCPND,子中断SUBSRCPND。主中断也可称为父中断。

     

    处理器中断初始化: MACHINE_STARTs3c2440_init_irq中初始化, 同时初始化static struct s3c_irq_intc *s3c_intc[3];变量

     

    中断(irq,abt,und)的堆栈初始化setup_arch→setup_processor→cpu_init→struct stack *stk = &stacks[cpu] (irq,abt,und)

     

    映射中断向量表:setup_arch→paging_init→devicemaps_init

     

    定义中断向量表:srcarcharmkernelentry-armv.S(其大部分定义在entry-header.S (srcarcharmkernel))__vectors_start

     

    中断方式初始化:如上升沿等,在init_s3c2440base里面定义

     

     

    1.4. Linux中断执行流程

    1.4.1. 中断入口与现场保护

    假定程序运行在用户态,中断类型为irq,则:

     

       中断发生→W(b)   vector_irq( vector_irq vector_stub irq, IRQ_MODE, 4定义)→执行宏vector_stub定义的vector_irq中断服务程序, 定义见下:

        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

     

    vector_stub的作用是保存中断现场,获取中断前处理器状态,然后将状态设置为SVC mode,后跳转到相应的中断才处理程序。 前面假定中断前为用户态,所以中断发生后,会最终跳转到__irq_usr处执行。

    1.4.2.    中断服务程序

    __irq_usr→irq_handler→handle_arch_irq(是个函数指针,全局变量=s3c24xx_handle_irq, s3c24xx_init_intc中被赋值)→s3c24xx_handle_intc→handle_IRQ→generic_handle_irqdesc->handle_irq如果是父中断,则执行s3c_irq_demux(在s3c24xx_irq_map中设置,执行chained_irq_enter→irq_ack清除主中断)→generic_handle_irq→desc->handle_irqhandle_edge_irqchip->irq_ack清除次级中断相关位,在s3c24xx_irq_map中设置)→handle_irq_event→ handle_irq_event_percpu→action->handler(request_irq申请,循环处理action = action->next)

     

    1.4.3.    中断返回与现场恢复

    __irq_usr为例:b ret_to_user_from_irqentry-common.S (srcarcharmkernel)定义)→ work_pending (在entry-common.S (srcarcharmkernel)定义)→ do_work_pending→ schedule

     

     

    handle_arch_irq赋值流程:MACHINE_STARTinit_irqs3c2440_init_irq→s3c24xx_init_intc→set_handle_irq

     

    desc->handle_irq注册流程:MACHINE_START::s3c2440_init_irq→s3c24xx_init_intc→irq_domain_add_legacy(传入 

    s3c24xx_irq_ops)ops->map(即s3c24xx_irq_ops->map,s3c24xx_irq_map→根据中断类型如果是边沿触发,则 

    desc->handle_irq=handle_edge_irq

     

     

     

        用到的变量与文件对应关系: 

    srcarcharmincludeasmUnified.h: #define PSR_ISETSTATE 0

    srcarcharmincludeasmlinkage.h: #define ENDPROC(name)

      .type name, %function;

      END(name)

    srcincludelinuxlinkage.h:#define END(name)

      .size name, .-name

    #endif

     

    Asm-offsets.c (srcarcharmkernel):  DEFINE(S_FRAME_SIZE,    sizeof(struct pt_regs))

    entry-header.S (srcarcharmkernel)) why .req   r8     @ Linux syscall (!= 0)

    Unified.h (srcarcharmincludeasm):#define BSYM(sym) sym

    srcarcharmkernelAsm-offsets.c: DEFINE(SYS_ERROR0,     0x9f0000);

     

    1.5. linux中断注册

    request_irq→request_threaded_irq→__setup_irq→new->irq = irq;   *old_ptr = new;old_ptr指向action链表的最后一项)

     

     

    1.6. linux中断地址映射

     

    linux中断地址分配:MACHINE_STARTmini2440_map_ios3c24xx_init_io →iotable_init(s3c_iodesc, ARRAY_SIZE(s3c_iodesc)); // 该函数分析详细见gpio章节。

    clip_image005[4]

    由上述可见,#define S3C_VA_IRQ  S3C_ADDR(0x00000000) irq虚拟地址为0xF6000000,且因为串口物理地址和虚拟地址对应关系确定了,irq物理地址和虚拟地址也确定了,因为PA1-PA2 = VA1-VA2

     

    1.7. linux中断数据结构

     

    clip_image006[4]

     

    由上图可见,中断号可以索引所有的中断对象。

    中断概貌:最重要的结构是全局变量struct irq_desc irq_desc[NR_IRQS]; 每一个中断号对应一个struct irq_desc, MACHINE_START中的s3c2440_init_irq主要是初始化该结构体。每个中断号和具体的irq_desc[i]对应,根据中断号就能知道该中断的所有信息,如该中断是父中断还是子中断,该中断的处理函数。父中断读取子中断源,通过desc->handle_irq = s3c_irq_demux(不一定是这个函数,为了描述方便举例的,后同)执行具体的子中断函数,子中断再执行desc->handle_irq = handle_edge_irq,最终都会

    执行desc->action->handler 总结起来 desc->handle_irq是执行函数分配,desc->action->handler执行具体的中断函数,

     

     1.4.  函数集合

    request_irq

    free_irq

     

     

     

  • 相关阅读:
    Java的“Goto”与标签
    Integer和int使用==比较的总结
    20175301李锦然《网络对抗技术》Exp9 Web安全基础
    20175301李锦然《网络对抗技术》Exp8 Web基础
    20175301李锦然《网络对抗技术》Exp7 网络欺诈防范
    2019-2020-2 20175301李锦然《网络对抗技术》Exp6 MSF基础应用
    2019-2020-2 20175301李锦然《网络对抗技术》Exp5 信息搜集与漏洞扫描
    2019-2020-2 20175301李锦然《网络对抗技术》Exp4 恶意代码分析
    2019-2020-2 20175301李锦然《网络对抗技术》Exp3 免杀原理与实践
    2019-2020-2 20175301李锦然《网络对抗技术》Exp2 后门原理与实践
  • 原文地址:https://www.cnblogs.com/embedded-tzp/p/4451354.html
Copyright © 2020-2023  润新知