字符设备之笔记-中断处理

来源:互联网 发布:网络漫画怎么画 编辑:程序博客网 时间:2024/05/22 17:51
 
中断处理过程:

cpu每执行一条指令之前,都会查看是否有中断发生,
如果没有中断,则执行这条指令,
如果有中断,则不执行这条指令.
然后:
1. 硬件:
1.1 CPU进行irq模式
1.2 CPU强制跳到中断向量入口地址去执行

2. 软件:
2.1 在"中断向量入口地址"那里有处理代码, 一般是一条跳转指令
2.2 保存"被中断的"现场
2.3 处理中断:
2.3.1    分辨中断源
2.3.2    调用对应的处理函数
2.4 恢复"被中断的"现场


对于LINUX, 2.1~2.4都帮我们做好了,
我们只需要事先提供"对应的处理函数"


怎么使用中断?
1. 确定中断号: linux给每个中断都编号,怎么确定你的中断是哪号?
               在内核源里搜request_irq,参考别的驱动,找到对应的宏
               以下文件里就是2410所有的中断号:
               include\asm-arm\arch-s3c2410\irqs.h

2. 写出中断处理函数
3. 注册中断: request_irq
4. 硬件相关的操作


内核中断框架:

注册中断:
request_irq

 // 分配/设置irqaction
 struct irqaction *action;
 action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
 action->handler = handler;
 action->flags = irqflags;
 action->name = devname;
 action->dev_id = dev_id;共享中断时,判别中断源

 // 把它放入irq_desc[irq]去
 retval = setup_irq(irq, action);
 
中断处理过程:
1. 保存现场
2. 处理:
2.1 分辨中断源
2.2 调用对应的处理函数
3. 恢复现场

asm_do_IRQ // 中断处理的第1个C函数
    struct irq_desc *desc = irq_desc + irq; // irq_desc[irq]
    desc_handle_irq(irq, desc);
        desc->handle_irq(irq, desc); // handle_edge_irq
            action_ret = handle_IRQ_event(irq, action);
         do {
          ret = action->handler(irq, action->dev_id);
          if (ret == IRQ_HANDLED)
           status |= action->flags;
          retval |= ret;
          action = action->next;
         } while (action);               

 

中断向量:
arch\arm\kernel\entry-armv.S

发生中断, cpu跳到0xfff0018
0xfff0018上有中断向量: memcpy((void *)vectors(0xffff0000), __vectors_start, __vectors_end - __vectors_start);

__vectors_start:
 swi SYS_ERROR0
 b vector_und + stubs_offset
 ldr pc, .LCvswi + stubs_offset
 b vector_pabt + stubs_offset
 b vector_dabt + stubs_offset
 b vector_addrexcptn + stubs_offset
 b vector_irq + stubs_offset
 b vector_fiq + stubs_offset


vector_irq在 "vector_stub irq, IRQ_MODE, 4" 这个宏里定义


__irq_usr:
 ......
 irq_handler
 ......


 .macro irq_handler
 get_irqnr_preamble r5, lr
1: get_irqnr_and_base r0, r6, r5, lr
 movne r1, sp
 @
 @ routine called with r0 = irq number, r1 = struct pt_regs *
 @
 adrne lr, 1b
 bne asm_do_IRQ  /* 中断处理的第1个C函数() */

get_irqnr_and_base (include\asm-arm\arch-s3c2410\entry-macro.S)

 .macro get_irqnr_and_base, irqnr, irqstat, base, tmp

  mov \base, #S3C24XX_VA_IRQ

  @@ try the interrupt offset register, since it is there

  ldr \irqstat, [ \base, #INTPND ]
  teq \irqstat, #0
  beq 1002f
  ldr \irqnr, [ \base, #INTOFFSET ]
  mov \tmp, #1
  tst \irqstat, \tmp, lsl \irqnr


 

原创粉丝点击