【发布时间】:2013-11-18 23:17:47
【问题描述】:
我是内核模块开发的新手。我正在编写一个内核模块来处理用户按钮按下。按下用户按钮后,我需要在 LED 上发光。我如何为用户按钮编写自定义处理程序,因为它最初是由内核模块获取的。我是否需要在内核配置中禁用 GPIO 按钮并编写一个完整的模块,或者我可以注册我的自定义处理程序?
【问题讨论】:
标签: user-controls beagleboard interrupt-handling led gpio
我是内核模块开发的新手。我正在编写一个内核模块来处理用户按钮按下。按下用户按钮后,我需要在 LED 上发光。我如何为用户按钮编写自定义处理程序,因为它最初是由内核模块获取的。我是否需要在内核配置中禁用 GPIO 按钮并编写一个完整的模块,或者我可以注册我的自定义处理程序?
【问题讨论】:
标签: user-controls beagleboard interrupt-handling led gpio
您首先需要从内核中删除模块 gpio_keys。 为此使用 rmmod 命令 - $> rmmod gpio_keys
我不确定中断按钮上的 LED 是否发光,但我可以使用以下代码处理中断按钮:
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/gpio.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <asm/io.h>
#include <linux/types.h>
#include <asm/uaccess.h>
#include <asm/gpio.h>
#include <linux/platform_device.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/proc_fs.h>
#include<linux/sched.h>
#define GPIO 4
int var;
static irqreturn_t irq_handler(int irq, void *dev_id,struct pt_regs *regs)
{
var++;
printk("In the Interrupt handler, Count: %d\n", var);
return IRQ_HANDLED;
}
int read_proc(char *buf,char **start,off_t offset,int count,int *eof,void *data )
{
int len=0;
if(offset>0)
{len=0;}
else{len += sprintf(buf, "No of times button pressed: %d\n",++var);}
return len;
}
void create_new_proc_entry()
{
create_proc_read_entry("hello",0,NULL,read_proc,NULL);
}
static int __init hello_init(void)
{
int errno = 0;
printk("Hello: registered module successfully!\n");
create_new_proc_entry();
if((errno = gpio_direction_input(GPIO)) !=0)
{
printk(KERN_INFO "Can't set GPIO direction, error %i\n", errno);
gpio_free(GPIO);
return -EINVAL;
}
int irq_line = gpio_to_irq(GPIO);
printk ("IRQ Line is %d \n",irq_line);
errno = request_irq( irq_line, irq_handler, IRQF_TRIGGER_FALLING, "Interrupt", NULL );
if(errno<0)
{
printk(KERN_INFO "Problem requesting IRQ, error %i\n", errno);
}
return 0;
}
static void __exit hello_exit(void)
{
printk ("Unloading my module.\n");
remove_proc_entry("hello",NULL);
int irq_line = gpio_to_irq(GPIO);
free_irq(irq_line,NULL);
printk("Hello Example Exit\n");
return;
}
module_init(hello_init);
module_exit(hello_exit);
// do some kernel module documentation
MODULE_AUTHOR("Deadman");
MODULE_DESCRIPTION("Interrupt Module");
MODULE_LICENSE("GPL");
您可以忽略上面与 proc 文件系统相关的调用。只需检查中断处理函数。这段代码对我来说很好用。
此外,如果您想在中断处理期间使用信号量或任何额外工作 - 请点击此链接创建小任务 -
http://www.ibm.com/developerworks/library/l-tasklets/
基本上你可能想在你的中断处理程序代码中调用 tasklet_schedule。
希望这会有所帮助。
【讨论】: