设为首页 加入收藏

TOP

TQ2440按键点亮LED驱动程序(二)
2014-11-23 19:49:11 来源: 作者: 【 】 浏览:80
Tags:TQ2440 按键 点亮 LED 驱动程序
tatic int buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)
{
unsigned long err;
//if (!ev_press) //如果没有按键按下
while(!ev_press) //如果没有按键按下
{
if (filp->f_flags & O_NONBLOCK) //如果是非阻塞读取设备,那么程序就直接返回 -EAGAIN
return -EAGAIN; //不阻塞,下次再来read
else
wait_event_interruptible(button_waitq, ev_press); //阻塞读取设备
}
ev_press = 0;
//把按键值的信息从内核空间复制到用户空间
err = copy_to_user(buff, (const void *)key_values, min(sizeof(key_values), count));
memset((void *)key_values, 0, sizeof(key_values));//清零
return err -EFAULT : min(sizeof(key_values), count);
}

//select方法
static unsigned int buttons_poll( struct file *file, struct poll_table_struct *wait)
{
unsigned int mask = 0;
poll_wait(file, &button_waitq, wait); //将等待队列添加到poll_table中
if (ev_press)
mask |= POLLIN | POLLRDNORM; //设备可读的掩码
return mask; //返回设备可读的掩码
}

//定义ioctl方法
static int leds_ioctl( struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
if(arg > 4)
{
return -EINVAL;
}
switch(cmd)
{
case LED_ON: //如果是点亮
s3c2410_gpio_setpin(led_table[arg], 0);//LED控制引脚输出低电平,此时灯亮
return 0;
case LED_OFF://如果是熄灭
s3c2410_gpio_setpin(led_table[arg], 1);//LED控制引脚输出高电平,此时灯灭
return 0;
default:
return -EINVAL;
}
return 0;
}

//定义file_operations方法
static struct file_operations buttons_fops =
{
.owner = THIS_MODULE,
.open = buttons_open,
.release = buttons_close,
.read = buttons_read,
.poll = buttons_poll,
.ioctl = leds_ioctl,
};

//声明自动创建设备文件的类
static struct class *button_class;

//驱动程序加载函数的实现
static int __init buttons_init(void)
{
int ret;
int i;
printk("TQ2440/SKY2440 LEDS!\n"); //输出初始化信息
ret = register_chrdev(DEVICE_MAJOR, DEVICE_NAME, &buttons_fops); //注册设备
if (ret)
{
printk(DEVICE_NAME " can't register major number\n");
return ret;
}
//设备节点文件自动创建的实现
button_class = class_create(THIS_MODULE, DEVICE_NAME);//注册一个类,使mdev可以在"/dev/"目录下面建立设备节点
if(IS_ERR(button_class))
{
printk("Err: failed in Button_leds class. \n");
return -1;
}
device_create(button_class, NULL, MKDEV(DEVICE_MAJOR, 0), NULL, DEVICE_NAME);//创建一个设备节点,节点名为DEVICE_NAME
for(i=0;i<4;++i) //熄灭4盏LED灯
{
s3c2410_gpio_cfgpin(led_table[i],led_cfg_table[i]); //配置LED的控制引脚为输出模式
s3c2410_gpio_setpin(led_table[i],1); //使LED控制引脚输出高电平,灯灭
}
printk(DEVICE_NAME " initialized\n");//打印信息,内核中的打印用printk函数
return 0;
}

//驱动程序卸载函数的实现
static void __exit buttons_exit(void)
{
unregister_chrdev(DEVICE_MAJOR, DEVICE_NAME);//注销设备
device_destroy(button_class, MKDEV(DEVICE_MAJOR, 0)); //删掉设备节点
class_destroy(button_class); //注销类
}

module_init(buttons_init);//驱动模块加载声明,执行“insmod tope-buttons.ko”命令时调用的函数
module_exit(buttons_exit); //驱动模块加载声明,执行“rmmod tope-buttons”命令时调用的函数
MODULE_LICENSE("GPL");//遵循的协议


源码分析:


1.程序的一开始我们定义了一个按键中断的结构体,我们可以将这个结构体看做是本程序要处理的按键中断的数据类型。然后我们分别对四个按键进行初始化。这里要说明下实现cpu引脚工作在中断模式下的宏S3C2410_GPF1_EINT1,S3C2410_GPF4_EINT4 ,S3C2410_GPF2_EINT2 和S3C2410_GPF0_EINT0 ,他们定义在在Regs-gpio.h中,源码路径:arch/arm/mach-s3c2410/include/mach/regs-gpio.h ,我们来看下宏S3C2410_GPF1_EINT1:#define S3C2410_GPF1_EINT1 (0x02 << 2) ,我们分析可以知道这里实际上就是将GPF1的寄存器二进制位的第3位和第2位设置成为1和0,从而使得GPF1工作在中断模式下。接着定义LED灯的控制引脚的数组和将LED控制引脚设置成为输出模式的宏,这里不做解释,因为前面我写过一篇TQ2440LED灯的驱动程序的文章,不懂请看那篇文章。


2.设置中断处理函数,当发生中断时就调用这个中断处理函数来处理中断,这之后是定义设备的open方法,对于本文的程序open方法主要的职责是:设置cpu的中断控制引脚工作在中断模式下并且申请中断;设置LED的cpu控制引脚工作在输出模式下。


3.定义设备

首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇STL之pair类型详细分析 下一篇STL之iterator(迭代器)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: