修改设备树及上机操作

查看原理图确定按键引脚

在这里插入图片描述
我们只需要指定GPIO信息,表示使用哪个GPIO即可。

gpio_keys_winter {
    compatible = "winter,gpio_key";
    gpios = <&gpiog 2 GPIO_ACTIVE_LOW
             &gpiog 3 GPIO_ACTIVE_LOW>;
};

在这里插入图片描述
把原来的GPIO按键节点禁止掉 :

status = “disabled”;

在这里插入图片描述
重新编译设备树

make dtbs

在这里插入图片描述
使用前面编译出来的驱动
在这里插入图片描述
在这里插入图片描述

测试

cat /proc/mounts

在这里插入图片描述
这里没问题,如果不是/boot分区,重新挂载

mount /dev/mmcblk2p2 /boot

在这里插入图片描述
把编译出来的设备树文件拷贝到/boot目录下
在这里插入图片描述
reboot重启

安装驱动,按按键测试,按下是0,松开是1
在这里插入图片描述
哎呀,好像不对,需要的是,按下是1,松开是0,重新在驱动文件中设置。完成驱动代码:

#include <linux/module.h>
 
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/stat.h>
#include <linux/init.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
#include <linux/gfp.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/slab.h>
 
 
 
// 封装一个结构体
struct gpio_key  {
	int gpio;						// gpio编号
	int irq;						// 中断号
	enum of_gpio_flags flag;		// flag
	struct gpio_desc *gpiod;		// 描述
};
 
// 结构体指针
static struct gpio_key* p_gpio_keys;
 
 
// 中断服务程序,
static irqreturn_t gpio_key_irq_winter(int irq, void* dev_id)
{
	struct gpio_key *gpio_key = dev_id;
	int val;
	val = gpiod_get_value(gpio_key->gpiod);
	printk("key %d %d\n", gpio_key->gpio, val);
	return IRQ_HANDLED;
}
 
// probe函数
/* 1. 从platform_device获得GPIO
 * 2. gpio=>irq,gpio资源转换成中断号
 * 3. request_irq
 */
static int gpio_keys_probe(struct platform_device* pdev)
{
	int count, i;
	int err;
	unsigned flags = GPIOF_IN;
	struct device_node* node = pdev->dev.of_node;
	enum of_gpio_flags flag;
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	// 1获得gpio
	count = of_gpio_count(node);
	if (!count)
	{
		printk("%s %s line %d, there isn't any gpio available\n", __FILE__, __FUNCTION__, __LINE__);
		return -1;
	}
	
	// 分配空间,分配好了,内存情况k:kernel,z:zero
	p_gpio_keys = kzalloc(count * sizeof(struct gpio_key), GFP_KERNEL);
 
	for (i = 0; i < count; i++)
	{
		// 把设备结点中gpio的每个引脚都取出来,再转换成中断号
		// 转换成中断号
		p_gpio_keys[i].gpio = of_get_gpio_flags(node, i, &flag);
		if (p_gpio_keys[i].gpio < 0)
		{
			printk("%s %s line %d, of_get_gpio_flags fail\n", __FILE__, __FUNCTION__, __LINE__);
			return -1;
		}
		p_gpio_keys[i].gpiod = gpio_to_desc(p_gpio_keys[i].gpio);
		p_gpio_keys[i].flag = flag & OF_GPIO_ACTIVE_LOW; // 设备树中的flag:GPIO_ACTIVE_LOW & OF_GPIO_ACTIVE_LOW
 
		if (flag & OF_GPIO_ACTIVE_LOW)
		{
			flags |= GPIOF_ACTIVE_LOW;
		}
		err = devm_gpio_request_one(&pdev->dev, p_gpio_keys[i].gpio, flags, NULL);
		p_gpio_keys[i].irq  = gpio_to_irq(p_gpio_keys[i].gpio);
	}
	for (i = 0; i < count; i++)
	{
		// 双边沿触发,当发生irq中断时,内核会调用gpio_key_irq_winter中断处理函数,同时会把&p_gpio_keys[i])参数传进去
		err = request_irq(p_gpio_keys[i].irq, gpio_key_irq_winter, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, "winter_gpio_key", &p_gpio_keys[i]);
	}
	return 0;
}
 
// remove函数-释放
int gpio_keys_remove(struct platform_device* pdev)
{
	struct device_node* node= pdev->dev.of_node;
	int count, i;
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	count = of_gpio_count(node);
	for (i = 0; i < count; i++)
	{
		free_irq(p_gpio_keys[i].irq, &p_gpio_keys[i]);		
	}
	// 释放空间
	kfree(p_gpio_keys);
	return 0;
}
 
// 资源。compatible的数据和设备树结点的数据匹配后,就会调用probe函数
static const struct of_device_id winter_gpio_keys[] = {
	{ .compatible = "winter,gpio_key", },
	{ },
};
 
 
// 1定义一个platform_driver结构体
static struct platform_driver gpio_key_driver = {
	.probe		= gpio_keys_probe,
	.remove		= gpio_keys_remove,
	.driver		= {
		.name	= "winter_gpio-keys",
		.of_match_table = winter_gpio_keys,
	}
};
 
 
 
// 2入口函数
static int __init gpio_keys_init(void)
{
	int err;
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	// 注册platform_driver结构体
	err = platform_driver_register(&gpio_key_driver);
	return 0;
}
 
// 出口函数
static void __exit gpio_keys_exit(void)
{
	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
	platform_driver_unregister(&gpio_key_driver);
}
 
module_init(gpio_keys_init);
module_exit(gpio_keys_exit);
MODULE_LICENSE("GPL");

测试,按下1,松开0
在这里插入图片描述

  • 7
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值