首页 > 其他分享 >rk3288不改内核情况下采用中断方式挂载按键驱动(各种错误提示)

rk3288不改内核情况下采用中断方式挂载按键驱动(各种错误提示)

时间:2023-07-21 10:11:09浏览次数:26  
标签:irq dev buttons 内核 KEY rk3288 挂载 include desc

内核不是开源的,只能选择.ko文件加载驱动

主板:么么厂家的rk3288,非瑞芯微官方板子

瑞芯微官网下载SDK,编译后的内核写进板子,板子无法启动,显然厂家在瑞芯微的基础上改硬件了

把GPIO_KEY驱动修改成模块,然后加载,提示

log: version magic '4.4.192 mod_unload ARMv5 ' should be '4.4.154 mod_unload ARMv5 '

内核版本不一致,网上有各种方法,直接修改版本编号为4.4.154,只要重新编译内核,肯定恢复成192

 

最好直接修改Makefile文件

Kernel/Makefile文件里的:
#KERNELRELEASE = $(shell cat include/config/kernel.release 2> /dev/null)
KERNELRELEASE = 4.4.154

然后挂载的时候再出错:Error: Driver 'gpio-keys' is already registered, aborting...

下面的错误是不能直接修改GPIO_KEY驱动,必须自己写一个input输入驱动

 

不想用设备树,直接在代码里写死


找到IO口的pin编号:
我的是
GPIO0_C1 17
GPIO0_C2 18
GPIO8_A0 248
GPIO8_A1 249


定义按键结构,并初始化

struct pin_desc{
int irq;
char *name;
unsigned int pin;
unsigned int key_val;
};

struct pin_desc pins_desc[4] = {
{65, "S4", ESC_GPIO, KEY_ESC},
{66, "S3", UP_GPIO, KEY_UP},
{67, "S2", DOWN_GPIO, KEY_DOWN},
{68, "S1", ENTER_GPIO, KEY_ENTER},
};

一开始我在这里初始化中断为65,66,67,68
结果没反应,中断没产生
原来3288的GPIO_pin指定了特定中断,直接使用就好
用gpio_to_irq获取gpio_pin编号的指定中断
我这里是:

for (i = 0; i < 4; i++)
{
    pins_desc[i].irq=gpio_to_irq(pins_desc[i].pin);
    ret = request_irq(pins_desc[i].irq, buttons_irq,           
    IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 
    pins_desc[i].name, &pins_desc[i]);
}    

上报按键事件

    pinval = gpio_get_value(pindesc->pin);

    if (pinval)
    {
        /* 松开 : 最后一个参数: 0-松开, 1-按下 */
        input_event(buttons_dev, EV_KEY, pindesc->key_val, 0);
        input_sync(buttons_dev);
        //printk("buttons_dev EV_KEY 0\r\n");
    }
    else
    {
        /* 按下 */
        input_event(buttons_dev, EV_KEY, pindesc->key_val, 1);
        input_sync(buttons_dev);
        //    printk("buttons_dev EV_KEY 1\r\n");
    }

让QT支持键盘消息:
export QT_QPA_GENERIC_PLUGINS=evdevkeyboard
insmod my_key.ko

全部代码如下:

#include <linux/module.h>
#include <linux/version.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/sched.h>
#include <linux/pm.h>
#include <linux/sysctl.h>
#include <linux/proc_fs.h>
#include <linux/delay.h>
#include <linux/platform_device.h>
#include <linux/input.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/of.h>
#include <linux/of_platform.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/spinlock.h>
#define ESC_GPIO 248
#define UP_GPIO 249
#define DOWN_GPIO 17
#define ENTER_GPIO 18
struct pin_desc{
    int irq;
    char *name;
    unsigned int pin;
    unsigned int key_val;
};

struct pin_desc pins_desc[4] = {
    {65,  "S4", ESC_GPIO,   KEY_ESC},
    {66,  "S3", UP_GPIO,   KEY_UP},
    {67, "S2", DOWN_GPIO,   KEY_DOWN},
    {68, "S1",  ENTER_GPIO, KEY_ENTER},
};

static struct input_dev *buttons_dev;
static struct pin_desc *irq_pd;
static struct timer_list buttons_timer;

irqreturn_t  buttons_irq(int irq, void *dev_id)
//irqreturn_t  buttons_irq(int irq,void *dev_id,struct myint_dev * intd)
{
        /* 10ms后启动定时器 */
    irq_pd = (struct pin_desc *)dev_id;
    mod_timer(&buttons_timer, jiffies+HZ/100);
    return IRQ_HANDLED;
}
static void buttons_timer_function(unsigned long data)
{
    struct pin_desc * pindesc = irq_pd;
    unsigned int pinval;

    if (!pindesc)
        return;
    
    pinval = gpio_get_value(pindesc->pin);

    if (pinval)
    {
        /* 松开 : 最后一个参数: 0-松开, 1-按下 */
        input_event(buttons_dev, EV_KEY, pindesc->key_val, 0);
        input_sync(buttons_dev);
        //printk("buttons_dev EV_KEY 0\r\n");
    }
    else
    {
        /* 按下 */
        input_event(buttons_dev, EV_KEY, pindesc->key_val, 1);
        input_sync(buttons_dev);
        //    printk("buttons_dev EV_KEY 1\r\n");
    }
}

static int buttons_init(void)
{
    int i,ret;
    gpio_direction_input(pins_desc[0].pin);
    gpio_direction_input(pins_desc[1].pin);
    gpio_direction_input(pins_desc[2].pin);
    gpio_direction_input(pins_desc[3].pin);
    
    /* 1. 分配一个input_dev结构体 */
    buttons_dev = input_allocate_device();;

    /* 2. 设置 */
    /* 2.1 能产生哪类事件 */
    set_bit(EV_KEY, buttons_dev->evbit);
    set_bit(EV_REP, buttons_dev->evbit);
    
    /* 2.2 能产生这类操作里的哪些事件: L,S,ENTER,LEFTSHIT */
    set_bit(KEY_ESC, buttons_dev->keybit);
    set_bit(KEY_UP, buttons_dev->keybit);
    set_bit(KEY_DOWN, buttons_dev->keybit);
    set_bit(KEY_LEFT, buttons_dev->keybit);

    /* 3. 注册 */
    ret = input_register_device(buttons_dev);
    
    /* 4. 硬件相关的操作 */
    init_timer(&buttons_timer);
    buttons_timer.function = buttons_timer_function;
    add_timer(&buttons_timer);
    
    for (i = 0; i < 4; i++)
    {
        pins_desc[i].irq=gpio_to_irq(pins_desc[i].pin);
        ret = request_irq(pins_desc[i].irq, buttons_irq,   IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, pins_desc[i].name, &pins_desc[i]);
    }
    
    return 0;
}

static void buttons_exit(void)
{
    int i;
    for (i = 0; i < 4; i++)
    {
        free_irq(pins_desc[i].irq, &pins_desc[i]);
    }

    del_timer(&buttons_timer);
    input_unregister_device(buttons_dev);
    input_free_device(buttons_dev);    
}

module_init(buttons_init);

module_exit(buttons_exit);

MODULE_LICENSE("GPL");

 

标签:irq,dev,buttons,内核,KEY,rk3288,挂载,include,desc
From: https://www.cnblogs.com/sankye/p/17570529.html

相关文章

  • 群晖nas docker 挂载tomcat目录
    前情使用场景描述:docker安装了tomcat,想要通过tomcat部署war包,但是无法上次war包到容器,于是使用了挂载;docker容器目录挂载:我们可以在创建容器的时候,将宿主机的目录与容器内的目录进行映射,这样我们就可以实现宿主机和容器目录的双向数据自动同步; tomcat安装和挂载目录1.......
  • docker把本地文件夹挂载到容器中
    如何将本地文件夹挂载到Docker容器中1.概述在使用Docker进行应用程序开发时,经常需要将本地文件夹挂载到Docker容器中,以便在容器中进行代码的调试和测试。本文将详细介绍如何完成这个过程,并提供每一步的示例代码和解释。2.操作步骤步骤操作1创建一个本地文件夹,用于......
  • K8S-Pod挂载数据卷权限问题
    场景:需要将同一个服务的多个Pod副本的日志持久化到本地,为方便根据Pod的名称快速查看日志,在Pod挂载数据卷时,可以通过subPathExpr和env变量配合使用为每个Pod副本自动创建以Pod名称命名的文件夹故障:自动创建的文件夹属主属组为root,业务进程使用appuser启动,导致程序无法进行写操作......
  • SecureKernel 的主要目标是防止恶意软件或攻击者能够利用漏洞或恶意代码来入侵和篡改
    SecureKernel是一个操作系统内核的安全性功能,用于提供额外的保护层来抵御针对内核的攻击。它是为了增强操作系统的安全性而设计的。SecureKernel的主要目标是防止恶意软件或攻击者能够利用漏洞或恶意代码来入侵和篡改操作系统内核。通过实施一系列安全策略和措施,SecureKernel......
  • Linux内核的USB 框架
    Linux内核的USB框架是管理USB设备的核心组件之一,它负责处理与USB设备相关的请求和操作,并提供了一些通用的函数和数据结构,以简化设备驱动程序的开发。在Linux内核的USB框架中,最重要的两个结构体是usb_driver和usb_device。usb_driver定义了USB设备驱动程序的基本操作函数,比如设备的......
  • k8s中,secret中有多条数据,如何将某条数据挂载为一个单独的文件?
    secrete中,包含以下两条数据db-password,原内容是123456db-username,原内容是:admin 这里都是base64编码的结果。 在pod中,volumemounts中,subPath指定某个数据项的key值mountPath:为具体的某个文件的名字这样挂载之后,就是具体的文件了,文件的内容,就是key对应的值。......
  • 在 Windows Server 2022 中,可以通过调整注册表来修改内核参数。以下是一些常见的内核
    在WindowsServer2022中,可以通过调整注册表来修改内核参数。以下是一些常见的内核参数调整在WindowsServer2022中,可以通过修改注册表来调整TCP/IP栈参数、TCP策略和文件系统缓存。请注意,对注册表的更改需要谨慎操作,建议在进行更改之前备份注册表以及系统状态。调整线......
  • TCP的Keep-Alive机制:链接存在但是没有数据传输,内核怎么处理
    服务端会定期发送探测报文来检测客户端的存活状态。由三个内核参数控制:首次发送探测报文时间:net.ipv4.tcp_keepalive_time有报文传输时重置探测报文的发送间隔:net.ipv4.tcp_keepalive_intvl探测报文的最大重试次数:net.ipv4.tcp_keepalive_probes#sysctl-a|grep......
  • chrome内核的开发者工具搜索功能的一点欠缺
    最近学习点东西,需要一些人名等数据,就想随便找lol里的人物做例子。比如:name黑暗之女--title安妮--roles法师。在英雄列表页面中可看到其name黑暗之女,但并没有显示title与roles,只有点击进入详情页面后,才能看到安妮和法师的信息。按照经验,推断即使在英雄列表也可能会有相关信息。......
  • React18内核探秘:手写React高质量源码迈向高阶开发
    第1章课程简介试看1节|8分钟导学介绍课程内容,及你所获得~第2章登高望远,手写源码前的思想准备8节|54分钟建立全局观,为后续在源码中吸取精华做好思想准备,避免就源码而分析源码。第3章原始版-初始化渲染:实现最原始的渲染过程11节|122分钟实现初次渲染的基础逻辑,初步体验......