mini2440中断处理

中断:以读取按键为例。

单片机的处理方式:

1、按键按下

2、cpu发生中断,跳到异常向量入口执行

3、b function

         function处理过程:

        3.1 保存被中断的现场

        3.2 执行中断处理函数

        3.3 恢复现场、清中断

所以代码中必须先设置异常向量入口。

Linux中的中断处理方式:

内核在start_kernel函数中调用trap_init,init_IRQ函数来设置异常的处理函数。

void __init trap_init(void)
{
......
    memcpy((void *)vectors, __vectors_start, __vectors_end - __vectors_start);
    memcpy((void *)vectors + 0x200, __stubs_start, __stubs_end - __stubs_start);
......
}
/***********************************/
____.globl____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

____.globl____vectors_end
__vectors_end:
/***********************************/
/*vector_stub_irq:宏需要展开来看,展开后得到一个vector_irq函数,调用下面的函数irq_usr*/
____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
____.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

/***********************************/
____.macro__vector_stub, name, mode, correction=0             
____.align__5

vector_\name:
____.if \correction
____sub_lr, lr, #\correction
____.endif

____@
____@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
____@ (parent CPSR)
____@
____stmia___sp, {r0, lr}________@ save r0, lr
____mrs_lr, spsr
____str_lr, [sp, #8]________@ save spsr

____@
____@ Prepare for SVC32 mode.  IRQs remain disabled.
____@
____mrs_r0, cpsr
____eor_r0, r0, #(\mode ^ SVC_MODE)
____msr_spsr_cxsf, r0

____@
____@ the branch table must immediately follow this code
____@
____and_lr, lr, #0x0f
____mov_r0, sp
____ldr_lr, [pc, lr, lsl #2]
____movs____pc, lr__________@ branch to handler in SVC mode
____.endm
/***********************************/

__irq_usr->

                  ____usr_entry    /*保存寄存器内容到栈中*/

                   irq_handler->____bne_asm_do_IRQ

/*                                                                             
 * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not                 
 * come via this function.  Instead, they should provide their                 
 * own 'handler'                                                               
 */                                                                            
asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs) 
{                                                                              
____struct pt_regs *old_regs = set_irq_regs(regs);                             
____struct irq_desc *desc = irq_desc + irq;                                    
                                                                               
____/*                                                                         
____ * Some hardware gives randomly wrong interrupts.  Rather                  
____ * than crashing, do something sensible.                                   
____ */                                                                        
____if (irq >= NR_IRQS)                                                        
________desc = &bad_irq_desc;                                                  
                                                                               
____irq_enter();                                                               
                                                                               
____desc_handle_irq(irq, desc);                                                
                                                                               
____/* AT91 specific workaround */                                             
____irq_finish(irq);                                                           
                                                                               
____irq_exit();                                                                
____set_irq_regs(old_regs);                                                    
}                                                                              

在asm_do_IRQ中会根据中断号(irq)来查找irq_desc结构。

asm_do_IRQ()

{

......

        struct irq_desc *desc = irq_desc + irq;

        desc_handle_irq(irq, desc);

......

}

static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc)
{
____desc->handle_irq(irq, desc); /*执行中断号对应的中断处理函数*/
}

irq_desc全局的结构体在哪注册的?

__set_irq_handler()函数会注册irq_desc。

例如:s3c24xx_init_irq->set_irq_handler(irqno, handle_edge_irq)->__set_irq_handler()


void
__set_irq_handler(unsigned int irq, irq_flow_handler_t handle, int is_chained,
________  const char *name)
{
......
 ____desc = irq_desc + irq;
......
 ____desc->handle_irq = handle;
 ____desc->name = name;
......
}

static inline void
set_irq_handler(unsigned int irq, irq_flow_handler_t handle)
{
______set_irq_handler(irq, handle, 0, NULL);                
}

void __init s3c24xx_init_irq(void)
{
......
 ____for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
 ________irqdbf("registering irq %d (ext int)\n", irqno);
 ________set_irq_chip(irqno, &s3c_irq_eint0t4);
 ________set_irq_handler(irqno, handle_edge_irq);          
 ________set_irq_flags(irqno, IRQF_VALID);
 ____}
......
}

/*以handler(handle_edge_irq)为例分析*/
void fastcall                                           
handle_edge_irq(unsigned int irq, struct irq_desc *desc)
{
......
 ____/* Start handling the irq */
 ____desc->chip->ack(irq);       /*清中断*/
......
________action_ret = handle_IRQ_event(irq, action);/*中断处理*/
......
}

/**                                                                     
 * handle_IRQ_event - irq action chain handler                          
 * @irq:____the interrupt number                                        
 * @action:_the interrupt action chain for this irq                     
 *                                                                      
 * Handles the action chain of an irq event                             
 */                                                                     
irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action)
{                                                                                                     
......                                                                        
____do {                                                                
________ret = action->handler(irq, action->dev_id);                     
________if (ret == IRQ_HANDLED)                                         
____________status |= action->flags;                                    
________retval |= ret;                                                  
________action = action->next;                                          
____} while (action);                                                   
......                                                                                                                                                
____return retval;                                                      
}                                                                       

总结:

1、按键按下

2、cpu进入异常模式

__vectors_start:

      b  vertor_irq + stubs_offset

3、___irq_usr

____usr_entry

____irq_handler

        bne_asm_do_IRQ

                ____desc_handle_irq(irq, desc);

                              ____desc->handle_irq(irq, desc);/*根据中断号查找对应的desc,执行中断处理函数*/

4、s3c24xx_init_irq初始化具体中断号所对应的中断处理函数以及中断号对应的中断引脚

中断处理函数:

set_irq_chip(irqno, &s3c_irq_eint0t4);/*初始化中断号对应的底层中断管脚*/

static struct irq_chip s3c_irq_eint0t4 = {
____.name_______= "s3c-ext0",             
____.ack________= s3c_irq_ack,            
____.mask_______= s3c_irq_mask,           
____.unmask_____= s3c_irq_unmask,         
____.set_wake___= s3c_irq_wake,           
____.set_type___= s3c_irqext_type,        
};                                       

set_irq_handler(irqno, handle_edge_irq);/*初始化中断号对应的中断处理函数*/

handle_edge_irq

{

____desc->chip->ack(irq);       /*清中断*/
________action_ret = handle_IRQ_event(irq, action);/*中断处理*/

}

5、

int request_irq(unsigned int irq, irq_handler_t handler,          
________unsigned long irqflags, const char *devname, void *dev_id)


{

____action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);

......

action->handler = handler;

 ____action->name = devname;
 ____action->next = NULL;    
 ____action->dev_id = dev_id;

.......

____retval = setup_irq(irq, action);

}

int setup_irq(unsigned int irq, struct irqaction *new)

{

struct irq_desc *desc = irq_desc + irq;

......

desc->chip->set_type(); /*设置中断引脚*/

......

/*使能中断*/

if (desc->chip->startup)     
____desc->chip->startup(irq);
else                         
____desc->chip->enable(irq);

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值