文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>Uclinux中断追踪

Uclinux中断追踪

时间:2006-03-17  来源:shizhi21cn

 最近在做uclinux设备驱动实验时,涉及到I2c总线的驱动。程序主要采取中断方试读写I2c数据。而uclinux中中断主要采用函数 request_irqrequest_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
   unsigned long irq_flags, const char * devname, void *dev_id)
申请获得中断号并注册中断函数。那么这个函数时到底如何管理中断的呢,它又是怎样管理ARM下的中断资源呢。本文将带你追踪如下:
首先,这个函数的源定义如下:  request_irq(unsigned int irq, void (*handler)(int, void *, struct pt_regs *),
   unsigned long irq_flags, const char * devname, void *dev_id)
{
 unsigned long retval;
 struct irqaction *action;
 if (irq >= NR_IRQS || !irq_desc[irq].valid || !handler ||
     (irq_flags & SA_SHIRQ && !dev_id))
  return -EINVAL;
 action = (struct irqaction *)kmalloc(sizeof(struct irqaction), GFP_KERNEL);    
 if (!action)
  return -ENOMEM;
 action->handler = handler;
 action->flags = irq_flags;
 action->mask = 0;
 action->name = devname;
 action->next = NULL;      
 action->dev_id = dev_id;
 retval = setup_arm_irq(irq, action);  if (retval)
  kfree(action);
 return retval;
} 程序首先检查所要申请中断号是否越界,中断处理函数是否有效,并对中断标志和设备名称是否为空做出判断。注意还有irq_desc[irq].valid,关于这一项的意义,后面将给出解释。 接着,向内核申请一个irqaction结构,并且填充这个结构。最后调用函数setup_arm_irq()。  下面先来解释一下irqaction结构,其完整定义如下: struct irqaction {
        void (*handler)(int, void *, struct pt_regs *);  //中断处理函数
        unsigned long flags;                             //中断管理有关的位掩码
        unsigned long mask;
        const char *name;                             //中断拥有者名称
        void *dev_id;                                  //用于共享的中断信号线
        struct irqaction *next;                         //构成链表
};
irqaction结构包含中断申请者的所有信息,而request_irq函数填充一个中断申请者结构,然后通过函数setup_arm_irq向系统申请中断。在解释函数setup_arm_irq之前先来解释一下irqdesc结构 struct irqdesc {
        unsigned int     nomask   : 1;          /* IRQ does not mask in IRQ   */   
        unsigned int     enabled  : 1;          /* IRQ is currently enabled   */      
        unsigned int     triggered: 1;          /* IRQ has occurred           */      
        unsigned int     probing  : 1;          /* IRQ in use for a probe     */     
        unsigned int     probe_ok : 1;          /* IRQ can be used for probe  */       
        unsigned int     valid    : 1;          /* IRQ claimable              */       
        unsigned int     noautoenable : 1;      /* don't automatically enable IRQ */
        unsigned int     unused   :25;
        void (*mask_ack)(unsigned int irq);     /* Mask and acknowledge IRQ   */      
        void (*mask)(unsigned int irq);         /* Mask IRQ                   */       
        void (*unmask)(unsigned int irq);       /* Unmask IRQ                 */       
        struct irqaction *action;
        /*
         * IRQ lock detection
         */
        unsigned int     lck_cnt;
        unsigned int     lck_pc;
        unsigned int     lck_jif;
};
irqdesc包含了中断的基本信息,并且还包含了一个中段申请者的指针。程序在初始化时定义了一个全局的irqdesc数组 irqdesc irq_desc[];  下面来看函数
int setup_arm_irq(int irq, struct irqaction * new)
{
 int shared = 0;         //判断中断是否被共享
 struct irqaction *old, **p;
 unsigned long flags;
 struct irqdesc *desc;
 /*
  * Some drivers like serial.c use request_irq() heavily,
  * so we have to be careful not to interfere with a
  * running system.
  */
 if (new->flags & SA_SAMPLE_RANDOM) {
  /*
   * This function might sleep, we want to call it first,
   * outside of the atomic block.
   * Yes, this might clear the entropy pool if the wrong
   * driver is attempted to be loaded, without actually
   * installing a new handler, but is this really a problem,
   * only the sysadmin is able to do this.
   */
         rand_initialize_irq(irq);
 }
 /*
  * The following block of code has to be executed atomically
  */
 desc = irq_desc + irq;   //desc就是irq_desc[irq]
 spin_lock_irqsave(&irq_controller_lock, flags);
 p = &desc->action;
 if ((old = *p) != NULL) {    
  /* Can't share interrupts unless both agree to */
  if (!(old->flags & new->flags & SA_SHIRQ)) {
   spin_unlock_irqrestore(&irq_controller_lock, flags);
   return -EBUSY;
  }
  /* add new interrupt at end of irq queue */
  do {
   p = &old->next;
   old = *p;
  } while (old);
  shared = 1;
 }
 *p = new;  if (!shared) {
  desc->probing = 0;
  desc->running = 0;
  desc->pending = 0;
  desc->disable_depth = 1;
  if (!desc->noautoenable) {
   desc->disable_depth = 0;
   desc->unmask(irq);
  }
 }
 spin_unlock_irqrestore(&irq_controller_lock, flags);
 return 0;
}
以上函数其本功能时根据irq中断号,来申请irq_desc[irq]这个中断结构,如果这个结构没被其他的设备占用,则申请成功,并且填充这个结构。这个结构是系统中断管理最重的结构。最后内核是如何利用这个结构来进行中断函数调用呢,我将继续追踪
相关阅读 更多 +
排行榜 更多 +
勇敢的哈克中文版

勇敢的哈克中文版

飞行射击 下载
HTX交易所app2025版

HTX交易所app2025版

金融理财 下载
黑神话悟空像素版6.0版本下载

黑神话悟空像素版6.0版本下载

飞行射击 下载