树莓派3B+驱动开发(6)- 中断实验
github主页:https://github.com/snqx-lqh
本项目github地址:https://github.com/snqx-lqh/RaspberryPiDriver
本项目硬件地址:https://oshwhub.com/from_zero/shu-mei-pai-kuo-zhan-ban
欢迎交流
笔记说明
用按键来测试GPIO中断相关的实验,使用gpio子系统控制电平,使用gpiod的api。
主要参考的文章
正点原子《I.MX6U 嵌入式 Linux 驱动开发指南 V1.81》
韦东山《01_嵌入式Linux应用开发完全手册V5.1_IMX6ULL_Pro开发板》
本节源码路径02_Firmware/07_key_drv_irq
设备树
中断设备,主要配置按键相关,然后配置的gpio主要需要说明的就是加了interrupt-parent和interrupts,interrupts分别需要填写的就是中断的引脚,和中断的方式,2,是下降沿中断。可以使用,
的方式多加几个引脚。这里为了减少篇幅,只是添加了按键相关的,完整的看项目源代码。
// Definitions for gpio-key module
/dts-v1/;
/plugin/;
/ {
compatible = "brcm,bcm2835";
fragment@0{
target-path = "/";
__overlay__ {
shb_key: shb_key@0{
compatible = "shb-key";
pinctrl-names = "default";
pinctrl-0 = <&shb_key_pins>;
status = "okay";
key1-gpios = <&gpio 26 0>;
key2-gpios = <&gpio 21 0>;
key3-gpios = <&gpio 20 0>;
interrupt-parent = <&gpio>;
interrupts = <26 2>,<21 2>,<20 2>;
};
};
};
fragment@1 {
// Configure the gpio pin controller
target = <&gpio>;
__overlay__ {
shb_key_pins: shb_key_pins@0 {
brcm,pins = <26 21 20>; // gpio number
brcm,function = <0 0 0>; // 0 = input, 1 = output
brcm,pull = <2 2 2>; // 0 = none, 1 = pull down, 2 = pull up
};
};
};
};
驱动编写
为了方便,关于按键这一节的代码,我全部都是使用的misc设备,方便注册。
比较核心的代码就是中断的注册和中断服务函数的编写,如下:
先获取中断引脚,然后转到中断设备号,再注册中断。
中断服务函数可以传入参数。在释放的时候需要释放中断号。
typedef struct{
int key_num;
struct gpio_desc *key_gpiod;
int key_irq;
}key_gpio_t;
typedef struct{
dev_t devid; /* 设备号 */
struct cdev cdev; /* cdev */
struct device_node *node; /* KEY 设备节点 */
key_gpio_t key_gpio[3];
}key_dev_t;
static key_dev_t key_dev;
static irqreturn_t gpio_key_isr(int irq, void *dev_id)
{
key_gpio_t *gpio_key = dev_id;
int val;
val = gpiod_get_value(gpio_key->key_gpiod);
printk("key %d %d\n", gpio_key->key_num, val);
return IRQ_RETVAL(IRQ_HANDLED);
}
static int key_probe(struct platform_device *dev)
{
int ret;
//读节点信息
key_dev.key_gpio[0].key_gpiod = gpiod_get(&dev->dev, "key1", 0);
key_dev.key_gpio[1].key_gpiod = gpiod_get(&dev->dev, "key2", 0);
key_dev.key_gpio[2].key_gpiod = gpiod_get(&dev->dev, "key3", 0);
key_dev.key_gpio[0].key_num = 1;
key_dev.key_gpio[1].key_num = 2;
key_dev.key_gpio[2].key_num = 3;
/* 初始化key相关 */
ret = gpiod_direction_input(key_dev.key_gpio[0].key_gpiod);
ret = gpiod_direction_input(key_dev.key_gpio[1].key_gpiod);
ret = gpiod_direction_input(key_dev.key_gpio[2].key_gpiod);
key_dev.key_gpio[0].key_irq = gpiod_to_irq(key_dev.key_gpio[0].key_gpiod);
key_dev.key_gpio[1].key_irq = gpiod_to_irq(key_dev.key_gpio[1].key_gpiod);
key_dev.key_gpio[2].key_irq = gpiod_to_irq(key_dev.key_gpio[2].key_gpiod);
//注册gpio中断
ret = request_irq(key_dev.key_gpio[0].key_irq, gpio_key_isr, IRQF_TRIGGER_FALLING, "shb_gpio_key_0", &key_dev.key_gpio[0]);
ret = request_irq(key_dev.key_gpio[1].key_irq, gpio_key_isr, IRQF_TRIGGER_FALLING, "shb_gpio_key_1", &key_dev.key_gpio[1]);
ret = request_irq(key_dev.key_gpio[2].key_irq, gpio_key_isr, IRQF_TRIGGER_FALLING, "shb_gpio_key_2", &key_dev.key_gpio[2]);
/* 注册misc字符设备驱动 */
ret = misc_register(&key_miscdev);
if(ret < 0){
printk("misc device register faikey!\r\n");
return -EFAULT;
}
return 0;
}
static int key_remove(struct platform_device *dev)
{
gpiod_put(key_dev.key_gpio[0].key_gpiod);
gpiod_put(key_dev.key_gpio[1].key_gpiod);
gpiod_put(key_dev.key_gpio[2].key_gpiod);
for (int i = 0; i < 3; i++)
{
free_irq(key_dev.key_gpio[i].key_irq, &key_dev.key_gpio[i]);
}
/* 注销misc设备 */
misc_deregister(&key_miscdev);
return 0;
}
原文地址:https://blog.csdn.net/wan1234512/article/details/144305058
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!