Linux字符设备驱动--No.2
发布时间:2020-12-14 01:41:37 所属栏目:Linux 来源:网络整理
导读:分析中断注册函数: request_irq 1 int butsOpen( struct inode *p, struct file * f) 2 { 3 4 int irq; 5 int i; 6 int err = 0 ; 7 printk(KERN_EMERG " butsOpenrn " ); 8 for (i = 0 ; i ARRAY_SIZE(buttons); i++ ) { 9 if (! buttons[i].gpio) 10 co
分析中断注册函数:request_irq 1 int butsOpen(struct inode *p,struct file *f) 2 { 3 4 int irq; 5 int i; 6 int err = 0; 7 printk(KERN_EMERG"butsOpenrn"); 8 for (i = 0; i < ARRAY_SIZE(buttons); i++) { 9 if (!buttons[i].gpio) 10 continue; 11 12 irq = gpio_to_irq(buttons[i].gpio); 13 err = request_irq(irq,button_interrupt,IRQ_TYPE_EDGE_BOTH,14 buttons[i].name,(void *)&buttons[i]); 15 if (err) 16 break; 17 } 18 19 if (err) { 20 i--; 21 for (; i >= 0; i--) { 22 if (!buttons[i].gpio) 23 continue; 24 25 irq = gpio_to_irq(buttons[i].gpio); 26 disable_irq(irq); 27 free_irq(irq,(void *)&buttons[i]); 28 } 29 30 return -EBUSY; 31 } 32 return 0; 33 } 1 request_irq(unsigned int irq,irq_handler_t handler,unsigned long flags,2 const char *name,void *dev) 3 { 4 return request_threaded_irq(irq,handler,NULL,flags,name,dev); 5 } 1 /** 2 * request_threaded_irq - 分配中断线路函数 3 * @irq: Interrupt line to allocate 4 * @handler: Function to be called when the IRQ occurs. 5 * Primary handler for threaded interrupts 6 * If NULL and thread_fn != NULL the default 7 * primary handler is installed 8 * @thread_fn: Function called from the irq handler thread 9 * If NULL,no irq thread is created 10 * @irqflags: Interrupt type flags 11 * @devname: An ascii name for the claiming device 12 * @dev_id: A cookie passed back to the handler function//作为hanler的一个参数 13 * 14 * This call allocates interrupt resources and enables the 15 * interrupt line and IRQ handling. From the point this 16 * call is made your handler function may be invoked. Since 17 * your handler function must clear any interrupt the board 18 * raises,you must take care both to initialise your hardware 19 * and to set up the interrupt handler in the right order. 20 * 21 * If you want to set up a threaded irq handler for your device 22 * then you need to supply @handler and @thread_fn. @handler ist 23 * still called in hard interrupt context and has to check 24 * whether the interrupt originates from the device. If yes it 25 * needs to disable the interrupt on the device and return 26 * IRQ_WAKE_THREAD which will wake up the handler thread and run 27 * @thread_fn. This split handler design is necessary to support 28 * shared interrupts. 29 * 30 * Dev_id must be globally unique. Normally the address of the 31 * device data structure is used as the cookie. Since the handler 32 * receives this value it makes sense to use it. 33 * 34 * If your interrupt is shared you must pass a non NULL dev_id 35 * as this is required when freeing the interrupt. 36 * 37 * Flags: 38 * 39 * IRQF_SHARED Interrupt is shared 40 * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy 41 * IRQF_TRIGGER_* Specify active edge(s) or level 42 * 43 */ 1 struct irqaction { 2 irq_handler_t handler; 3 unsigned long flags; 4 void *dev_id; 5 struct irqaction *next; 6 int irq; 7 irq_handler_t thread_fn; 8 struct task_struct *thread; 9 unsigned long thread_flags; 10 unsigned long thread_mask; 11 const char *name; 12 struct proc_dir_entry *dir; 13 } ____cacheline_internodealigned_in_smp; 1 /** 2 * struct irq_desc - interrupt descriptor 3 * @irq_data: per irq and chip data passed down to chip functions 4 * @timer_rand_state: pointer to timer rand state struct 5 * @kstat_irqs: irq stats per cpu 6 * @handle_irq: highlevel irq-events handler 7 * @preflow_handler: handler called before the flow handler (currently used by sparc) 8 * @action: the irq action chain 9 * @status: status information 10 * @core_internal_state__do_not_mess_with_it: core internal status information 11 * @depth: disable-depth,for nested irq_disable() calls 12 * @wake_depth: enable depth,for multiple irq_set_irq_wake() callers 13 * @irq_count: stats field to detect stalled irqs 14 * @last_unhandled: aging timer for unhandled count 15 * @irqs_unhandled: stats field for spurious unhandled interrupts 16 * @lock: locking for SMP 17 * @affinity_hint: hint to user space for preferred irq affinity 18 * @affinity_notify: context for notification of affinity changes 19 * @pending_mask: pending rebalanced interrupts 20 * @threads_oneshot: bitfield to handle shared oneshot threads 21 * @threads_active: number of irqaction threads currently running 22 * @wait_for_threads: wait queue for sync_irq to wait for threaded handlers 23 * @dir: /proc/irq/ procfs entry 24 * @name: flow handler name for /proc/interrupts output 25 */ 26 struct irq_desc { 27 struct irq_data irq_data; 28 struct timer_rand_state *timer_rand_state; 29 unsigned int __percpu *kstat_irqs; 30 irq_flow_handler_t handle_irq; 31 #ifdef CONFIG_IRQ_PREFLOW_FASTEOI 32 irq_preflow_handler_t preflow_handler; 33 #endif 34 struct irqaction *action; /* IRQ action list */ 35 unsigned int status_use_accessors; 36 unsigned int core_internal_state__do_not_mess_with_it; 37 unsigned int depth; /* nested irq disables */ 38 unsigned int wake_depth; /* nested wake enables */ 39 unsigned int irq_count; /* For detecting broken IRQs */ 40 unsigned long last_unhandled; /* Aging timer for unhandled count */ 41 unsigned int irqs_unhandled; 42 raw_spinlock_t lock; 43 #ifdef CONFIG_SMP 44 const struct cpumask *affinity_hint; 45 struct irq_affinity_notify *affinity_notify; 46 #ifdef CONFIG_GENERIC_PENDING_IRQ 47 cpumask_var_t pending_mask; 48 #endif 49 #endif 50 unsigned long threads_oneshot; 51 atomic_t threads_active; 52 wait_queue_head_t wait_for_threads; 53 #ifdef CONFIG_PROC_FS 54 struct proc_dir_entry *dir; 55 #endif 56 const char *name; 57 } ____cacheline_internodealigned_in_smp; 44 int request_threaded_irq(unsigned int irq, 45 irq_handler_t thread_fn,unsigned long irqflags, 46 const char *devname,void *dev_id) 47 { 48 struct irqaction *action; 49 struct irq_desc *desc; 50 int retval; 51 52 /* 53 * Sanity-check: shared interrupts must pass in a real dev-ID, 54 * otherwise we‘ll have trouble later trying to figure out 55 * which interrupt is which (messes up the interrupt freeing 56 * logic etc). 57 */ 58 if ((irqflags & IRQF_SHARED) && !dev_id)//若终端标志是共享中断,则设备号dev_id不允许为空 59 return -EINVAL; 60 61 desc = irq_to_desc(irq); 62 if (!desc) 63 return -EINVAL; 64 65 if (!irq_settings_can_request(desc)) 66 return -EINVAL; 67 68 if (!handler) { 69 if (!thread_fn) 70 return -EINVAL; 71 handler = irq_default_primary_handler; 72 } 73 74 action = kzalloc(sizeof(struct irqaction),GFP_KERNEL); 75 if (!action) 76 return -ENOMEM; 77 78 action->handler = handler; 79 action->thread_fn = thread_fn; 80 action->flags = irqflags; 81 action->name = devname; 82 action->dev_id = dev_id; 83 84 chip_bus_lock(desc); 85 retval = __setup_irq(irq,desc,action); 86 chip_bus_sync_unlock(desc); 87 88 if (retval) 89 kfree(action); 90 91 #ifdef CONFIG_DEBUG_SHIRQ_FIXME 92 if (!retval && (irqflags & IRQF_SHARED)) { 93 /* 94 * It‘s a shared IRQ -- the driver ought to be prepared for it 95 * to happen immediately,so let‘s make sure.... 96 * We disable the irq to make sure that a ‘real‘ IRQ doesn‘t 97 * run in parallel with our fake. 98 */ 99 unsigned long flags; 100 101 disable_irq(irq); 102 local_irq_save(flags); 103 104 handler(irq,dev_id); 105 106 local_irq_restore(flags); 107 enable_irq(irq); 108 } 109 #endif 110 return retval; 111 } 1 #define irq_to_desc(irq) (&irq_desc[irq]) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |