本人使用的调试平台是荣品的rv1126开发板,最近在调试按键中断。经过查看原理图,发现竟然没有一个空闲的IO,所以使用UART1的RX作为按键中断引脚。

驱动部分:

因为UART1原先已经在设备树中已经有了定义,需要将 kernel/arch/arm/boot/dts/rongpin/rv1126_1109_common.dtsi 中的uart1去掉

//&uart1 {
//  pinctrl-names = "default";
//  pinctrl-0 = <&uart1m0_xfer>;
//  status = "okay";
//};

并在kernel/arch/arm/boot/dts/rp-rv1126.dts 中的rp_gpio,加入该IO:

 rp_gpio {status = "okay";compatible = "rp_gpio";gpio0b7{gpio_num = <&gpio0 RK_PB7 IRQ_TYPE_EDGE_FALLING>; gpio_function = <2>;};......

设备树修改完毕,下面开始编写代码。

rv1126的gpio采用的是gpiolib架构,工程师可以不必查阅寄存器即可完成配置,在kernal/drivers/rongpin/rp_gpio.c中修改。

1、修改probe:

static int rp_gpio_probe(struct platform_device *pdev) {struct device_node *np = pdev->dev.of_node;struct device_node *child_np;static struct proc_dir_entry *root_entry_gpio;enum of_gpio_flags  gpio_flags;int ret = 0;int gpio_cnt = 0; char gpio_name_num[GPIO_NUM_MAX];int gpio_in_cnt = 0;gpio_data = devm_kzalloc(&pdev->dev, sizeof(struct rp_gpio_data),GFP_KERNEL);if (!gpio_data) {dev_err(&pdev->dev, "failed to allocate memory\n");return -ENOMEM;}gpio_data->gpio_dts_num = of_get_child_count(np);printk("rp_gpio prepare build %d gpio\n",gpio_data->gpio_dts_num);if (gpio_data->gpio_dts_num == 0){dev_info(&pdev->dev, "no gpio defined\n");}/* create node */root_entry_gpio = proc_mkdir("rp_gpio", NULL);for_each_child_of_node(np, child_np){/* parse dts */gpio_data->rp_gpio_num[gpio_cnt].gpio_num = of_get_named_gpio_flags(child_np, "gpio_num", 0, &gpio_flags);if (!gpio_is_valid(gpio_data->rp_gpio_num[gpio_cnt].gpio_num)){return -1;}      gpio_data->rp_gpio_num[gpio_cnt].gpio_name = (char*)child_np -> name;gpio_data->rp_gpio_num[gpio_cnt].action = gpio_flags;gpio_data->rp_gpio_num[gpio_cnt].gpio_ctrl = gpio_cnt;of_property_read_u32(child_np, "gpio_function", &(gpio_data->rp_gpio_num[gpio_cnt].gpio_function));printk("rp_gpio request %s\n",gpio_data->rp_gpio_num[gpio_cnt].gpio_name);switch(gpio_data->rp_gpio_num[gpio_cnt].gpio_function) {case GPIO_FUNCTION_INPUT :     /* init input gpio */ret = gpio_request(gpio_data->rp_gpio_num[gpio_cnt].gpio_num, "gpio_num");if (ret < 0){printk("gpio%d request error\n",gpio_data->rp_gpio_num[gpio_cnt].gpio_num);}else{printk("success request gpio %d in\n",gpio_data->rp_gpio_num[gpio_cnt].gpio_num);//gpio_set_value(gpio_data->rp_gpio_num[gpio_cnt].gpio_num,!gpio_data->rp_gpio_num[gpio_cnt].action);gpio_direction_input(gpio_data->rp_gpio_num[gpio_cnt].gpio_num);event_flag = gpio_flags;of_property_read_u32(child_np, "send_mode", &(gpio_data->rp_gpio_num[gpio_cnt].send_mode));of_property_read_u32(child_np, "gpio_event", &(gpio_data->rp_gpio_num[gpio_cnt].gpio_event));gpio_in_cnt++;}break;
#if 1case GPIO_FUNCTION_IRQ :       /* init input gpio */ret = gpio_request(gpio_data->rp_gpio_num[gpio_cnt].gpio_num, "gpio_num");if (ret < 0){printk("gpio%d request error\n",gpio_data->rp_gpio_num[gpio_cnt].gpio_num);}else{printk("success request gpio %d irq\n",gpio_data->rp_gpio_num[gpio_cnt].gpio_num);//gpio_set_value(gpio_data->rp_gpio_num[gpio_cnt].gpio_num,!gpio_data->rp_gpio_num[gpio_cnt].action);printk("gpio_to_irq(gpio_data->rp_gpio_num[gpio_cnt].gpio_num) = %d\n",gpio_to_irq(gpio_data->rp_gpio_num[gpio_cnt].gpio_num));irq_gpio = gpio_data->rp_gpio_num[gpio_cnt].gpio_num;gpio_direction_input(gpio_data->rp_gpio_num[gpio_cnt].gpio_num);ret  = request_irq(gpio_to_irq(gpio_data->rp_gpio_num[gpio_cnt].gpio_num),button_irq_handler,//IRQ_TYPE_EDGE_FALLING,IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISING,"key_irq",NULL);//1、分配一个input_dev结构体buttons_dev = input_allocate_device();if(!buttons_dev){printk("input_allocate_device error!\n");return -ENOMEM;}buttons_dev->name = "input_key";buttons_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);input_set_capability(buttons_dev, EV_KEY, KEY_0);ret = input_register_device(buttons_dev);if (ret) {printk("register input device failed!\r\n");return ret;}//初始化定时器,用于按键消抖timer_setup(&buttons_timer,my_buttons_timer_function,0);buttons_timer.expires = jiffies + msecs_to_jiffies(20);add_timer(&buttons_timer);}break;
#endifcase GPIO_FUNCTION_OUTPUT :       /* init output gpio */ret = gpio_request(gpio_data->rp_gpio_num[gpio_cnt].gpio_num, "gpio_num");if (ret < 0){printk("gpio%d request error\n",gpio_data->rp_gpio_num[gpio_cnt].gpio_num);//return ret;}else{gpio_direction_output(gpio_data->rp_gpio_num[gpio_cnt].gpio_num,!gpio_data->rp_gpio_num[gpio_cnt].action);printk("success request gpio%d out\n",gpio_data->rp_gpio_num[gpio_cnt].gpio_num);}break;case GPIO_FUNCTION_FLASH :ret = gpio_request(gpio_data->rp_gpio_num[gpio_cnt].gpio_num, "gpio_num");if (ret < 0){printk("gpio%d request error\n",gpio_data->rp_gpio_num[gpio_cnt].gpio_num);//return ret;}else{gpio_direction_output(gpio_data->rp_gpio_num[gpio_cnt].gpio_num,!gpio_data->rp_gpio_num[gpio_cnt].action);printk("success request gpio%d flash\n",gpio_data->rp_gpio_num[gpio_cnt].gpio_num);gpio_in_cnt++;}break;}sprintf(gpio_name_num,gpio_data->rp_gpio_num[gpio_cnt].gpio_name,gpio_cnt);proc_create(gpio_name_num, 0666 , root_entry_gpio , &gpio_ops);gpio_cnt++;}gpio_wq = create_singlethread_workqueue("gpio_wq");INIT_WORK(&gpio_work, gpio_work_func);platform_set_drvdata(pdev, gpio_data);    return 0;
}

代码中的case GPIO_FUNCTION_IRQ是新增加的,主要是申请IO、设置IO方向、注册中断函数、配置输入子系统、初始化定时器。其中定时器是用来消抖的。按键信号通过输入子系统传递到应用程序。

2、增加外部中断以及定时器服务函数。


unsigned irq_gpio;
static struct input_dev *buttons_dev;
static struct timer_list buttons_timer;static irqreturn_t button_irq_handler(int irq, void *dev_id)
{mod_timer(&buttons_timer, jiffies+msecs_to_jiffies(20));return IRQ_HANDLED;
}//定时器中断处理函数
static void my_buttons_timer_function(struct timer_list* list)
{int gpio_value = 0;gpio_value = gpio_get_value(irq_gpio);if(gpio_value == 0){input_report_key(buttons_dev, KEY_0, 1);input_sync(buttons_dev);}if(gpio_value == 1){input_report_key(buttons_dev, KEY_0, 0);input_sync(buttons_dev);}
}

应用程序:

        编写应用程序之前,先使用cat /proc/bus/input/devices 确定驱动使用了哪个输入子系统的event。

        应用程序比较简单。

检测输入子系统信号采用一个线程,以下函数为线程函数:

void *scan_key_main(void *data)
{int fd = 0;struct input_event buttons_event;unsigned long cur_ms = 0;data = data;//fd = open("/dev/event0", O_RDWR | O_NONBLOCK);fd = open("/dev/input/event3", O_RDWR);if (fd < 0){printf("can't open!\n");}while (1){read(fd, &buttons_event, sizeof(struct input_event));//        if(buttons_event.type == EV_SYN)
//            continue;cur_ms = (buttons_event.time.tv_sec * 1000) + (buttons_event.time.tv_usec/1000);//打印时间,事件类型,事件码,事件值printf("cur_ms:%ld type:0x%x code:%d value:%d\n",cur_ms,buttons_event.type,buttons_event.code,buttons_event.value);}
}

如果在调试过程中出现问题,可以使用hexdump /dev/input/eventX命令辅助调试。

RV1126按键中断驱动和应用调试相关推荐

  1. ARM(IMX6U)ARM Cortex-A7中断系统(GPIO按键中断驱动蜂鸣器)

    参考:Linux之ARM Cortex-A7 中断系统详解 作者:一只青木呀 发布时间: 2020-09-16 16:07:22 网址:https://blog.csdn.net/weixin_453 ...

  2. mt6762添加gpio按键方法与问题调试

    mt6762添加gpio按键方法与问题调试 1 配置dts文件.定义gpio87为拍照键,对于keycode = 212. gpio_keys:gpio_keys {         compatib ...

  3. 伦茨8400变频器面板按键说明_变频器调试笔记

    笔者于年后换了家工作单位,有机会跟踪学习了一条汽车生产线总装车间设备的安装调试.其中有几个典型的变频器调试案例,笔者整理整理笔记,来和大家分享一下. 案例一:问题描述:从底盘线转往综合线的空中EMS的 ...

  4. Linux键盘按键中断驱动示例

    Linux下中断驱动中最典型的就是键盘驱动了,在初始化的时候调用request_irq注册中断,在退出的时候free_irq释放中断.下面是示例: keyboardInt.h #ifndef _KEY ...

  5. 龙芯2k按键中断驱动_外部中断按键驱动

    我的开发板上一共有四个按键,分别影射到GPF0.GPF2.GPG3.GPG11,当按下按键时分别产生0.2.11.19号外部中断.由于没有安装驱动,当按下按键时,没有任何反应.所以需要编写一个驱动,将 ...

  6. 龙芯2k按键中断驱动_字符设备驱动-高级篇按键中断程序驱动

    驱动源码: #include "linux/module.h" #include"linux/kernel.h" #include"linux/fs. ...

  7. mtk 按键中断驱动

    static irqreturn_t kpd_irq_handler(int irq, void *dev_id) {int value;value = mt_get_gpio_in(BUTTONT_ ...

  8. 龙芯2k按键中断驱动_龙芯2k1000的中断处理逻辑

    龙芯2k1000的中断设计 1.前言 2.龙芯2k1000的中断描述 2.1mips设计上的通用中断处理 2.2龙芯中断的设计 3.龙芯2k1000中断的产生与处理 4.龙芯2k1000中断处理概述 ...

  9. 龙芯2k按键中断驱动_龙芯2k1000的中断设计

    龙芯2k1000的中断设计 1.前言 2.龙芯2k1000的中断描述 2.1 mips设计上的通用中断处理 2.2 龙芯中断的设计 3.龙芯2k1000中断的产生与处理 4.龙芯2k1000中断处理概 ...

最新文章

  1. finecms设置伪静态后分享到微信不能访问怎么处理
  2. textrank4zh是_GitHub - 997666901/TextRank4ZH: 从中文文本中自动提取关键词和摘要
  3. 深入理解 __doPostBack
  4. 使用Silverlight for Embedded开发绚丽的界面(2)
  5. Fedora中允许mysql远程访问的几种方式
  6. 深入理解Java类加载机制
  7. nodejs里socket.on和socket.once的单步调试
  8. STL运用的C++技术(6)——函数对象
  9. python创建和删除文件
  10. 说说设计模式~桥梁模式(Bridge)
  11. Hbase shell练习题
  12. 矩阵分析 (八) 矩阵的直积
  13. 关于Eclipse(MyEclipse)中一次性批量导入多个项目Project.
  14. 项目实习(三)操作系统设计
  15. maven for Mac配置,idea 配置maven
  16. junit5 入门系列教程-13-junit5 测试接口及默认方法
  17. android实现登录页面视频播放背景
  18. C#键盘钩子之局部钩子和全局钩子
  19. python怎么对数用log,python中的对数log函数表示及用法
  20. mysql插入微信名称中的特殊字符

热门文章

  1. python项目一:外星人入侵:(一)武装飞船
  2. Python 时间整点判断
  3. (附源码)node.js华联招聘网站 毕业设计 011229
  4. intel cpu计算机硬件架构,intel的cpu分类介绍
  5. Android NFC标签写入应用包名,感应到标签自动打开应用
  6. 中班音乐活动计算机反思,幼儿园音乐教学反思(精选6篇)
  7. 鲍尔默:微软发展来自对八个核心领域持续投资 (作者:三张 | 出处:网易科技 )
  8. 电脑计算机可以删掉什么影响,drivers文件夹是否可以删除?电脑删除drivers文件夹的注意事项...
  9. PLUTO SDR入门系列之八:LimeSDR公司荣誉出品”PothosSDR”-内置“gqrx”,GNU radio以及CubicSDR
  10. C++编程练习——五子棋游戏