21,597
社区成员
发帖
与我相关
我的任务
分享
//头文件
#include <linux/module.h>
#include <linux/types.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <asm/io.h>
#include <asm/system.h>
#include <asm/uaccess.h>
#include <linux/poll.h>
#include <linux/signal.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/sysdev.h>
#include <asm/hardware/vic.h>
#include <plat/regs-irqtype.h>
#include <mach/map.h>
#include <plat/cpu.h>
#include <plat/pm.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/regs-gpio.h>
#include <mach/irqs.h>
#include <mach/gpio-bank.h>
#include <linux/delay.h>
#include <asm/delay.h>
#include <asm/param.h>
#include <linux/io.h>
#include <linux/sysdev.h>
#include <mach/map.h>
#define DEVICE_NAME "menu_test"
//#define IRQ_NO (IRQ_EINT(16))
struct menu_dev {
struct cdev cdev;
};
struct menu_dev *menu_devp;//设备结构体指针
int IRQ_NO;//定义中断号
//函数声明
static int menu_major = 250;
static void menu_setup_cdev(struct menu_dev * , int );
static int menu_init(void);
static int menu_open(struct inode * , struct file *);
static int menu_release(struct inode * ,struct file *);
static void init_gpio(void);
//中断处理函数
irqreturn_t menu_interrupt(int irq, void *dev_id)
{
printk("menu_interrupt start.....!\n");
disable_irq_nosync(irq);//关中断
udelay(5);//延迟5ms,消除毛刺信号
printk("i am interrup handler\n");
init_gpio();
enable_irq(irq);//开中断
printk("menu_interrupt over.......!\n");
return IRQ_HANDLED;
}
//初始化配置函数
static void init_gpio(void)
{
int error;
printk("init_gpio start....\n");
error = gpio_request(S5PV210_GPH2(0),"gpio_keys");//检查gpio管脚是否被使用
if (error < 0)
printk("gpio-keys: failed to request GPIO %d \n", S5PV210_GPH2(0));
else
printk("gpio %d success!\n",S5PV210_GPH2(0));
s3c_gpio_cfgpin(S5PV210_GPH2(0),0xf); //将管脚配置为中断模式
IRQ_NO = gpio_to_irq(S5PV210_GPH2(0));//获取中断号,其实这个我也不太清楚,看别人的。
if (error < 0)
printk("gpio_to_irq: failed %d \n", S5PV210_GPH2(0));
else
printk("gpio_to_irq %d success!\n",S5PV210_GPH2(0));
//配置为输出 且为低电平
s3c_gpio_cfgpin(S5PV210_GPH3(0),S3C_GPIO_OUTPUT);//配置为输出,低电平 EINT24号管脚 参照原理图上的。
s3c_gpio_setpin(S5PV210_GPH3(0),1);
s3c_gpio_cfgpin(S5PV210_GPH3(1),S3C_GPIO_OUTPUT);//配置为输出,低电平 EINT25号管脚
s3c_gpio_setpin(S5PV210_GPH3(1),1);
//设置下降沿触发
set_irq_type(IRQ_NO,IRQ_TYPE_EDGE_FALLING);
printk("init_gpio successed!\n");
}
static int menu_open(struct inode *inode , struct file *filp)
{
int ret;
init_gpio();//对相关端口初始化
ret = request_irq(IRQ_NO, menu_interrupt, IRQF_SHARED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, DEVICE_NAME, NULL);
if(ret < 0){
printk("request_irq failer\n");
return -EFAULT;
}
else
printk("request_irq success !\n");
return ret;
}
static int menu_release(struct inode *inode ,struct file *filp)
{
printk("this is release\n");
free_irq(IRQ_NO,NULL);
return 0;
}
static struct file_operations menu_fops = {
.owner = THIS_MODULE,
.open = menu_open,
.release = menu_release,
};
static void menu_setup_cdev(struct menu_dev *dev, int minor)
{
int err;
int devno = MKDEV(menu_major,minor);
cdev_init(&dev->cdev,&menu_fops);
dev -> cdev.owner = THIS_MODULE;
err = cdev_add(&dev->cdev, devno, 1);
if(err){
printk("error %d adding menu %d \n",err,minor);
}
printk("menu_setup_cdev over!\n");
}
static int menu_init(void)
{
int ret = 0;
dev_t dev = MKDEV(menu_major , 0);
if(menu_major)
ret = register_chrdev_region(dev, 1, DEVICE_NAME);
else{
ret = alloc_chrdev_region(&dev, 0, 1, DEVICE_NAME);
menu_major = MAJOR(dev);
}
if(ret < 0){
printk("unable to get major %d \n",menu_major);
return ret;
}
menu_devp = kmalloc(sizeof(struct menu_dev),GFP_KERNEL);
if(!menu_devp)
{
ret = -ENOMEM;
}
memset(menu_devp,0,sizeof(struct menu_dev));
menu_setup_cdev(menu_devp, 0 );
printk("menu driver initialized\n");
return 0;
}
//驱动卸载
void menu_exit(void)
{
cdev_del(&menu_devp->cdev);
unregister_chrdev_region(MKDEV(menu_major,0),1);
printk("menu driver unistalled \n");
}
module_init(menu_init);
module_exit(menu_exit);
MODULE_LICENSE("Dual BSD/GPL");