1. 使用PG11引脚作为中断输入引脚
2. 如何在DTS文件中申明使用IRQ
? 如图所示便是标准的使用一个PIN的IRQ的DTS语法,个人觉得在不同的SoC中所使用的DTS语法稍微有一些不同,对于具体的使用方法需要参考官方代码中给出的标准格式。下面是我的代码中给出的:
? 我认为最重要的属性是interrupts相关的属性,其他的pincrtl可以启动辅助作用(在这里不能够通过gpio获得irq号,需要注意的是gpio_in不能被设置到目标引脚).
3. 我的驱动代码
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/miscdevice.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/of_irq.h>
#include <linux/init.h>
#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
#define DEV_NAME "button"
static ssize_t irq_open(struct inode *node, struct file *filp)
{
printk("IRQ device file opened !\n");
return 0;
}
static ssize_t irq_close(struct inode *node, struct file *filp)
{
printk("IRQ device fiel closed !\n");
return 0;
}
static irqreturn_t button_isr(int irq, void *dev)
{
printk("<kernel>: The isr for irq = %d \n", irq);
return IRQ_HANDLED;
}
static const struct file_operations f_ops = {
.owner = THIS_MODULE,
.open = irq_open,
.release = irq_close,
};
static struct miscdevice irq_misc = {
.name = DEV_NAME,
.minor = MISC_DYNAMIC_MINOR,
.fops = &f_ops
};
static int probe(struct platform_device *pdev)
{
int ret, irq;
//struct device_node *node;
// 1. get device node
/*
node = of_find_node_by_path("/irq_test");
if(node == NULL){
printk("<kernel>: Failed to get node by path! \n");
return -EINVAL;
}
printk("<kernel>: Success to get node by path !\n");
pin = of_get_named_gpio(node, "gpio", 0);
if(pin < 0){
printk("<kernel>: Failed to get pin number \n");
return -EINVAL;
}
printk("<kernel>: Success get device need pins = %d \n", pin);
// 2. transfer gpio number to irq number
irq = gpio_to_irq(pin);
if(irq < 0){
printk("<kernel>: Failed to get irq number of pin(%d) !\n", pin);
return -EINVAL;
}
printk("<kernel>: The irq of pin is %d !\n", irq);
*/
// a. through platform device get irq
irq = platform_get_irq(pdev, 0);
if(irq < 0){
printk("<kernel>: Failed to get irq number through platform device !\n");
return -EINVAL;
}
printk("<kernel>: Get irq = %d though platform !\n", irq);
ret = devm_request_irq(&pdev->dev, irq, button_isr,
IRQF_TRIGGER_RISING, DEV_NAME, &pdev->dev);
if(ret){
printk("<kernel>: Failed to request irq:%d !\n", irq);
return ret;
}
printk("<kernel>: Had register interrupt isr !\n");
ret = misc_register(&irq_misc);
if(ret != 0){
printk("<kernel>: Failed to register misc device !\n");
return ret;
}
printk("<kernel>: Success register misc device, minor = %d !\n", irq_misc.minor);
return 0;
}
static int __exit remove(struct platform_device *pdev)
{
printk("<kernel>: Deregister misc device--irq_misc !\n");
misc_deregister(&irq_misc);
return 0;
}
static const struct of_device_id irq_ids[] = {
{.compatible = "allwinner,buttons"},
{ },
};
static struct platform_driver irq_driver = {
.probe = probe,
.remove = remove,
.driver = {
.name = DEV_NAME,
.of_match_table = irq_ids,
.owner = THIS_MODULE
},
};
module_platform_driver(irq_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("weirdo");
MODULE_DESCRIPTION("This driver for Allwinner H3 irq!");
? 对于irq驱动的tasklet,workqueen这些需要读者自己去学习,我只是给出如何使用全志H3的IRQ的方法。
** 驱动测试代码 **
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<termios.h>
#include<string.h>
int main()
{
int i,fd, ret;
char dat;
fd = open("/dev/button", O_RDONLY);
if (fd == -1)
{
printf("Can not open /dev/myfile!\n");
exit(0);
}
printf("Open file success ! \n");
for(i=0;i<20;i++)
{
printf("Now the time is = %d\n", i);
sleep(1);
}
close(fd);
return 0;
}
测试结果:
原文:https://www.cnblogs.com/weirdo-xo/p/13251919.html