|
本帖最后由 sunbeyond 于 2014-11-7 22:06 编辑
Cubiebaord 按键设备驱动(中断)
根据按键原理。本例子让 PI11 口 pin 脚接地模拟按键按下。只需要有根电线就行不要真正的按键。
说明:
gpio_request(unsigned gpio, const char *label)第一个参数 gpio 标号是如何获取。是根据
script.fex 中的 gpio_para 中子键 gpio_pin_1,gpio_pin_2,gpio_pin_3....对应的顺序 GPIO 标号依次是
1,2,3。
1 首先修改 scipt.fex 配置,这里以 PI11 作为按键中断口。对应的 gpio 标号原理跟上面讲的一样。
可知此处对应的标号也为 1。
[gpio_para]
gpio_used = 1
gpio_num = 2
gpio_pin_1 = portI11<0><1><default><default> ------》 PH11 对应 GPIO 标号 num = 1
gpio_pin_2 = portH21<1><default><default><1>
2 驱动代码:(红色部分为 GPIO 中断使用重点)- button_drv.c
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/device.h>
- #include <linux/cdev.h>
- #include <linux/uaccess.h>
- #include <linux/interrupt.h>
- #include <linux/wait.h>
- #include <asm/io.h>
- #include <linux/irq.h>
- #include <asm/irq.h>
- #include <mach/irqs.h>
- #include <plat/sys_config.h>
- #include <mach/system.h>
- #include <linux/slab.h>
- #include <linux/gpio.h>
- #include <linux/init.h>
- #include <linux/fs.h>
- #include <asm/atomic.h>
- #include <linux/kthread.h>
- //分配 cdev
- struct cdev btn_cdev;
- wait_queue_head_t btn_wq; //分配等待队列头
- Copyright © Cubietech Limited. All right reserved Website: http://cubieboard.org
- E-mail: s upport@cubiete ch.com
- //主设备号
- static int major;
- //设备类
- static struct class *cls;
- //按键操作标志
- static int is_press; // 1:按键操作 0:无按键操作
- static unsigned char key_val;
- //按按键按下次数
- int press_num = 1;
- //GPIO 标号,非常重要,通过 script.fex 中的 gpio_para 配置顺序。从上往下对应的 gpio 标号依次是
- 1,2,3......
- int num = 1;
- //中断号
- int irq ;
- static int button_open(struct inode *inode,
- struct file *file)
- {
- return 0;
- }
- static int button_close(struct inode *inode,
- struct file *file)
- {
- return 0;
- }
- static ssize_t button_read(struct file *file,
- char __user *buf,
- size_t count,
- loff_t *ppos)
- {
- /*.判断按键是否有操作,如果有,进行读取
- 键值,然后上报给用户,如果没有操作,
- 进程休眠
- */
- wait_event_interruptible(btn_wq, is_press != 0);
- is_press = 0;
- /*3.上报键值*/
- copy_to_user(buf, &key_val, sizeof(key_val));
- return count;
- }
- //设备的操作集合
- static struct file_operations btn_fops = {
- .owner = THIS_MODULE,
- .open = button_open,
- Copyright © Cubietech Limited. All right reserved Website: http://cubieboard.org
- E-mail: s upport@cubiete ch.com
- .release = button_close,
- .read = button_read
- };
- static irqreturn_t button_isr(int irq,
- void *dev_id)
- {
- unsigned long status;
- /*1. 获取按键状态*/
- status = gpio_get_value(num);
- /*2. 更新按键键值 key_val*/
- if (status == 1) {
- //松开
- key_val = 0x50;
- } else if (status == 0)
- //按下
- key_val = 0x51;
- /*3. 唤醒休眠的进程*/
- wake_up_interruptible(&btn_wq);
- is_press = 1;
- return IRQ_HANDLED;
- }
- static int button_init(void)
- {
- dev_t dev_id;
- /*1.申请设备号*/
- if (major) {
- dev_id = MKDEV(major, 0);
- register_chrdev_region(dev_id, 1, "button");
- } else {
- alloc_chrdev_region(&dev_id, 0, 1, "button");
- major = MAJOR(dev_id);
- }
- /*2.分配初始化 cdev*/
- /*2.2 初始化 cdev*/
- cdev_init(&btn_cdev, &btn_fops);
- //初始化等待队列头
- init_waitqueue_head(&btn_wq);
- /*3.注册 cdev*/
- cdev_add(&btn_cdev, dev_id, 1);
- /*4.自动创建设备节点*/
- Copyright © Cubietech Limited. All right reserved Website: http://cubieboard.org
- E-mail: s upport@cubiete ch.com
- cls = class_create(THIS_MODULE, "button");
- device_create(cls, NULL, dev_id, NULL, "button");
- /*5.申请 GPIO 资源*/
- if (gpio_request(num,"gpio_pin")){
- printk("request gpio error\n");
- }
- /*6.获取中断号*/
- irq = gpio_to_irq(num);
- /*7 注册中断*/
- int error = request_irq(irq,button_isr,IRQF_TRIGGER_FALLING|
- IRQF_TRIGGER_RISING,"key_1",&press_num);
- if(error){
- printk("request irq error\n");
- }
- return 0;
- }
- static void button_exit(void)
- {
- dev_t dev_id = MKDEV(major, 0);
- /*释放中断*/
- /*释放 GPIO 资源*/
- free_irq(irq, &press_num);
- gpio_free(num);
- /*删除设备节点*/
- device_destroy(cls, dev_id);
- class_destroy(cls);
- /*删除 cdev*/
- cdev_del(&btn_cdev);
- /*释放设备号*/
- unregister_chrdev_region(dev_id, 1);
- }
- module_init(button_init);
- module_exit(button_exit);
- MODULE_LICENSE("GPL");
复制代码 测试代码:button_test.c - 测试代码: button_test.c
- #include
- #include
- #include
- #include
- <stdio.h>
- <sys/types.h>
- <sys/stat.h>
- <fcntl.h>
- int main(int argc, char *argv[])
- {
- int fd;
- unsigned char key_val;
- fd = open("/dev/button", O_RDWR);
- if (fd < 0) {
- printf("open failed.\n");
- return -1;
- }
- while(1) {
- read(fd, &key_val, sizeof(key_val));
- printf("key_val = %#x\n", key_val);
- }
- close(fd);
- return 0;
- }
复制代码 3 加载驱动,运行测试代码:
$ insmod button_drv.ko
根据按键原理。可让 PI11 口 pin 脚接地模拟按键按下。
$ ./button_test (有按键按下返回 0x51,松开按键返回 0x50)
|
|