IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 【f1c200s/f1c100s】不带中断引脚采用扫描的方式实现input子系统 -> 正文阅读

[系统运维]【f1c200s/f1c100s】不带中断引脚采用扫描的方式实现input子系统

【f1c200s/f1c100s】不带中断引脚采用扫描的方式实现input

发现问题

最近画了一块f1c200s/f1c100s开发板,暂且叫它mango-pi。原理图和PCB可以参考mago-pi
由于引脚资源有限,将按键输入引脚设计到了PA0和PA1引脚。
在这里插入图片描述
直接使能内核自带的gpio-key功能后,内核输出不能请求irq中断。查看gpio_keys.c源码发现在文件开始就说了这个驱动只针对能够产生中断的引脚。
在这里插入图片描述
后面查阅f1c200s参考手册发现PA端口居然不带GPIO中断!!!!!PD、PE、PF都有,就没有PA。所以这块板子不能使用内核自带的gpio-keys功能。
在这里插入图片描述

解决问题

先贴代码,占坑,后续补充。

// SPDX-License-Identifier: GPL-2.0-only
/*
 * Driver for keys on GPIO lines capable of not generating interrupts.
 *
 * Copyright 2022 Lorenzo
 * Copyright 2022, 2022 Lorenzo <liangtaozhong@gmail.com>
 */

#include <linux/module.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/slab.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/gpio_keys.h>
#include <linux/workqueue.h>
#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/spinlock.h>
#include <dt-bindings/input/gpio-keys.h>
#include <linux/fs.h>
#include <linux/timer.h>
#include <linux/cdev.h>
#include <linux/errno.h>
#include <linux/of_gpio.h>
#include <linux/input.h>
#include <linux/semaphore.h>

#define KEYINPUT_NAME "keyinput"
#define DELAY_MS 50
static int nbuttons;
static bool rep;
struct key_dev {
    dev_t devid;
    struct cdev cdev;
    struct class *class;
    struct device *device;
    struct device_node *nd;
    struct timer_list timer;
    struct input_dev *inputdev;
};

struct key_desc {
    int gpio;
    u32 code;
    const char *label;
};

static struct key_desc* key = NULL;
static struct key_dev key_dev;

void timer_func(struct timer_list* timer) {
    int i = 0;
    struct key_desc *pkey = NULL;
    pkey = key;
    for (i = 0; i < nbuttons; ++i, ++pkey) {
        if (gpio_get_value(pkey->gpio) == 0) {
            mdelay(10);
            if (gpio_get_value(pkey->gpio) == 0) {
                input_report_key(key_dev.inputdev, pkey->code, 1);
                input_sync(key_dev.inputdev);
            } 
        } else {
            input_report_key(key_dev.inputdev, pkey->code, 0);
            input_sync(key_dev.inputdev);
        }
    }

    mod_timer(&key_dev.timer, jiffies + msecs_to_jiffies(DELAY_MS));

}


static const struct of_device_id gpio_keys_of_match[] = {
    {.compatible = "gpio-keys-scan"},
    { },
};

static int key_probe(struct platform_device *pdev) {
    struct device *dev = &pdev->dev;
    struct device_node *np = dev->of_node;
    struct device_node *next;
    int i = 0;
    int ret;
    nbuttons = of_get_child_count(np);
    printk("having %d buttons\r\n", nbuttons);
    if (!nbuttons)
        return ERR_PTR(-ENODEV);
    key = devm_kzalloc(dev, nbuttons * sizeof(struct key_desc), 
        GFP_KERNEL);
    if (key == NULL) {
        return -ENOMEM; 
    }
    struct key_desc* pkey = key;

    rep = of_property_read_bool(np, "autorepeat");
    printk("rep : %d\n", rep);

    for_each_child_of_node(np, next) {
        
        of_property_read_string(next, "label", &(pkey->label));
        of_property_read_u32(next, "linux,code", &(pkey->code));
        printk("name: %s, label: %s, code: %d\n", next->name, 
            pkey->label, pkey->code);
        pkey->gpio = of_get_named_gpio(next, "gpios", 0);
        if (pkey->gpio < 0) {
            printk("can't request gpio: %s\r\n", pkey->label);
            return -ENODEV;
        }
        gpio_request(pkey->gpio, pkey->label);
        gpio_direction_input(pkey->gpio);
        pkey++;
    }

    key_dev.inputdev = input_allocate_device();
    if (NULL == key_dev.inputdev)
    {
            printk(KERN_ERR "input_allocate_device error");
            return -1;
    }

    key_dev.inputdev->name = KEYINPUT_NAME;
    key_dev.inputdev->evbit[0] = BIT_MASK(EV_KEY);
    if (rep) {
        key_dev.inputdev->evbit[0] = BIT_MASK(EV_REP);
    }

    for (i = 0, pkey = key; i < nbuttons; ++i, ++pkey) {
        input_set_capability(key_dev.inputdev, EV_KEY, pkey->code);
    }

    ret = input_register_device(key_dev.inputdev);
    if (ret) {
        printk("register input device failed\n");
        for (i = 0, pkey = key; i < nbuttons; ++i, ++pkey) {
            gpio_free(pkey->gpio);
        }
        input_unregister_device(key_dev.inputdev);
        return ret;
    }
    /*
     * Use timer to scan all buttons
     */
    timer_setup(&key_dev.timer, timer_func, 0);
    mod_timer(&key_dev.timer, jiffies + msecs_to_jiffies(DELAY_MS));
    return 0;
}

static int key_remove(struct platform_device *dev) {
    input_unregister_device(key_dev.inputdev);
    input_free_device(key_dev.inputdev);
    del_timer_sync(&key_dev.timer);

    return 0;
}


static struct platform_driver gpio_keys_scan_driver = {
    .driver = {
        .name = "scan-keys",
        .of_match_table = gpio_keys_of_match,
    },
    .probe = key_probe,
    .remove = key_remove,
};

static int  __init keydriver_init(void) {
    return platform_driver_register(&gpio_keys_scan_driver);
}

static void __exit keydriver_exit(void) {
    platform_driver_unregister(&gpio_keys_scan_driver);
}


module_init(keydriver_init);
module_exit(keydriver_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lorenzo <liangtaozhong@gmail.com>");
MODULE_DESCRIPTION("Keyboard driver for GPIOs");
MODULE_ALIAS("platform:gpio-keys-scan");
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-04-27 11:41:37  更:2022-04-27 11:42:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 20:54:51-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码