嵌入式开发记录-day46 设备树按键中断例程

1、在上一节的基础上,可以获取GPIO的编号,进一步,可以根据GPIO的编号,获取该管脚对应的中断编号;

  中断发生后,需要有相应的中断服务函数,来处理该中断;

2、中断简单例程的实现流程

  前面通过 of_get_named_gpio 能够获取GPIO的编号。
  介绍过在设备树中GPIO lib的API仍然保留,那么通过 gpio_to_irq 函数即可获取中断号。
  linux驱动中申请中断request_irq,只需要从平台文件或者设备树文件中传输过来中断号。

  那么中断的程序可以通过以下方式实现:
  of_get_named_gpio获取GPIO编号;
  gpio_to_irq获取中断号;
  使用request_irq申请中断函数

3、设备树部分

  仍然使用HOME按键的GPIO。

...
itop_inter {
compatible = "itop4412,inter_pin";
status = "okay";
inter_gpio = <&gpx1 1 0>;
};
...

4、驱动代码

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_gpio.h>

#include <linux/miscdevice.h>
#include <linux/fs.h>

#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio_keys.h>
#include <linux/of_irq.h>

#define DRIVER_NAME "itop4412,inter_pin"

int inter_pin = 0;

// 中断服务函数
static irqreturn_t eint_interrupt(int irq, void *dev_id) {

        printk("%s(%d)\n", __FUNCTION__, __LINE__);
        printk("HOME KEY HIGH TO LOW!\n");
        
        return IRQ_HANDLED;
}

static int inter_probe(struct platform_device * pdev)
{
    struct device_node *node = pdev->dev.of_node;
    int ret,irq;
    
    printk("inter init\n");
    
    inter_pin = of_get_named_gpio(node, "inter_gpio", 0);
    if (inter_pin < 0)
        printk("inter_pin is not available \n");
    
    ret = gpio_request(inter_pin, "home-key-inter");
    if (ret) {
        printk("%s: request GPIO %d failed, ret = %d\n", DRIVER_NAME,inter_pin, ret);
        return ret;
    }
    gpio_direction_input(inter_pin);
    gpio_free(inter_pin);
    
    irq = gpio_to_irq(inter_pin);  // 获取中断号
    ret = request_irq(irq, eint_interrupt,IRQ_TYPE_EDGE_FALLING, "home-key-inter", pdev);
    if (ret < 0) {
            printk("Request IRQ %d failed, %d\n", irq,ret);
            return -1;
    }
    printk("inter ok\n");
    
    return 0;
}

static int inter_remove(struct platform_device * pdev)
{
    free_irq(gpio_to_irq(inter_pin),pdev);
    
    printk(KERN_ALERT "Goodbye, curel world, this is remove\n");
    
    return 0;
}

static const struct of_device_id of_inter_dt_match[] = {
    {.compatible = DRIVER_NAME},
    {},
};

MODULE_DEVICE_TABLE(of,of_inter_dt_match);

static struct platform_driver inter_driver = {
    .probe     = inter_probe,
    .remove = inter_remove,
    .driver = {
        .name = DRIVER_NAME,
        .owner = THIS_MODULE,
        .of_match_table = of_inter_dt_match,
        },
};

static int inter_init(void)
{
    printk(KERN_ALERT "Hello, world\n");
    return platform_driver_register(&inter_driver);
    return 0;
}

static void inter_exit(void)
{
    printk(KERN_ALERT "Goodbye, curel world\n");
    platform_driver_unregister(&inter_driver);
}

module_init(inter_init);
module_exit(inter_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("rty");
MODULE_DESCRIPTION("topeet4412_regiter_dev_drv");

5、待测试

 6、其他例子

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_gpio.h>

#include <linux/miscdevice.h>
#include <linux/fs.h>

#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio_keys.h>
#include <linux/of_irq.h>

#define DRIVER_NAME "itop-4412,gpio-keys"


static irqreturn_t eint_interrupt(int irq, void *dev_id) {

        printk("%s(%d)\n", __FUNCTION__, __LINE__);
        printk("HOME KEY HIGH TO LOW!\n");
        
        return IRQ_HANDLED;
}

static int inter_probe(struct platform_device * pdev)
{
    struct device_node *node = pdev->dev.of_node;
    int ret,irq[2];
    
    printk("inter init\n");
    
    irq[0] = irq_of_parse_and_map(node,0);
    printk("irq number is %d\n",irq[0]);
    
    irq[1] = irq_of_parse_and_map(node,1);
    printk("irq number is %d\n",irq[1]);
    
    printk("inter ok\n");
    
    return 0;
}

static int inter_remove(struct platform_device * pdev)
{
    printk(KERN_ALERT "Goodbye, curel world, this is remove\n");
    
    return 0;
}

static const struct of_device_id of_inter_dt_match[] = {
    {.compatible = DRIVER_NAME},
    {},
};

MODULE_DEVICE_TABLE(of,of_inter_dt_match);

static struct platform_driver inter_driver = {
    .probe     = inter_probe,
    .remove = inter_remove,
    .driver = {
        .name = DRIVER_NAME,
        .owner = THIS_MODULE,
        .of_match_table = of_inter_dt_match,
        },
};

static int inter_init(void)
{
    printk(KERN_ALERT "Hello, world\n");
    return platform_driver_register(&inter_driver);
    return 0;
}

static void inter_exit(void)
{
    printk(KERN_ALERT "Goodbye, curel world\n");
    platform_driver_unregister(&inter_driver);
}

module_init(inter_init);
module_exit(inter_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("rty");
MODULE_DESCRIPTION("topeet4412_regiter_dev_drv");
View Code

7、设备树中的其他API例子

#include <linux/init.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/of_gpio.h>

#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/gpio_keys.h>
#include <linux/of_irq.h>
#include <linux/gpio.h>
#include <linux/property.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <linux/slab.h>
#include <linux/device.h>

#define DRIVER_NAME "itop4412,tree-sum"

static int treesum_probe(struct platform_device * pdev)
{
    struct fwnode_handle *child;
    const char *p1,*p2[3];
    u32 p3[2],value;
    u8 testmac[6];
    int i=0;
    
    
    printk("*************treesum_probe init***************\n");
//*************more of base function "include/linux/property.h" ************//
    device_property_read_string(&pdev->dev,"test-string",&p1);
    printk("itop4412-tree-sum  test-string is: %s\n",p1);
    
    device_property_read_string_array(&pdev->dev, "test-strings", p2, 3);
    printk("itop4412-tree-sum  test-strings is: %s%s%s\n",p2[0],p2[1],p2[2]);
    
    device_property_read_u32(&pdev->dev,"test-u32",&value);
    printk("itop4412-tree-sum  test-u32 is: <%d>\n",value);
    
    device_property_read_u32_array(&pdev->dev, "test-u32s", p3, 2);
    printk("itop4412-tree-sum  test-u32s is: <%d>,<%d>\n",p3[0],p3[1]);
    
    device_property_read_u8_array(&pdev->dev,"test-u8s",testmac,6);
    printk("itop4412-tree-sum  test-u32s is: [%x,%x,%x,%x,%x,%x]\n",testmac[0],testmac[1],testmac[2],testmac[3],testmac[4],testmac[5]);
    
    device_property_read_string(&pdev->dev,"compatible",&p1);
    printk("itop4412-tree-sum  compatible is: %s\n",p1);
    
    device_property_read_string(&pdev->dev,"status",&p1);
    printk("itop4412-tree-sum  status is: %s\n",p1);

// get child property value
// Loop get childnode value
//*************more of base function "include/linux/property.h" "linux/gpio/consumer.h"************//
    device_for_each_child_node(&pdev->dev, child){
        printk("*************childnode%d*************\n",i++);        
        fwnode_property_read_string(child,"test-string",&p1);
        printk("childnode test-string is: %s\n",p1);
        
        fwnode_property_read_string_array(child,"test-strings",p2,3);
        printk("childnode  test-strings is: %s%s%s\n",p2[0],p2[1],p2[2]);
        
        fwnode_property_read_u32_array(child,"test-u32",&value,1);
        printk("childnode test-u32 is: <%d>\n",value);
        
        fwnode_property_read_u32_array(child,"test-u32s",p3,2);
        printk("childnode  test-u32s is: <%d>,<%d>\n",p3[0],p3[1]);
        
        fwnode_property_read_u8_array(child,"test-u8s",testmac,6);
        printk("childnode test-u32s is: [%x,%x,%x,%x,%x,%x]\n",testmac[0],testmac[1],testmac[2],testmac[3],testmac[4],testmac[5]);    
    }    
    
    printk("treesum_probe over\n");
    return 0;
}

static int treesum_remove(struct platform_device * pdev)
{
    printk(KERN_ALERT "Goodbye, curel world, this is remove\n");

    return 0;
}

static const struct of_device_id of_treesum_dt_match[] = {
    {.compatible = DRIVER_NAME},
    {},
};

MODULE_DEVICE_TABLE(of,of_treesum_dt_match);

static struct platform_driver treesum_driver = {
    .probe     = treesum_probe,
    .remove = treesum_remove,
    .driver = {
        .name = DRIVER_NAME,
        .owner = THIS_MODULE,
        .of_match_table = of_treesum_dt_match,
        },
};

static int treesum_init(void)
{
    int num=0,i=0,value;
    const char *p1;
    struct device_node *node1,*childnode1;
    u32 p2[2];
    u8 testmac[6];

    printk("*************treesum init***************\n");    
//***************************************************************//        
//*************more of base function "include/linux/of.h" ************//
//get "itop4412-tree-sum" device node  
    node1 = of_find_node_by_path("/itop4412-tree-sum");
    if(node1 == NULL){
        printk("of_find_node_by_path failed\n");
        return -ENODEV;
    }
    printk("of_find_node_by_path ok\n");

//read string    
    of_property_read_string(node1, "test-string", &p1);
    printk("itop4412-tree-sum  test-string is: %s\n",p1);
//code: if((num = of_property_count_strings(node1, "test-strings"))<0) num =0 ? why? I don't know!
//read strings num and strings
    num = of_property_count_strings(node1, "test-strings");
    printk("itop4412-tree-sum  test-strings num is: %d\n",num);
    
    printk("itop4412-tree-sum  test-strings is:");
    for(i=0;i<num;i++){
        of_property_read_string_index(node1,"test-strings",i,&p1);
        printk("%s",p1);
    }
//read string "compatible"
    of_property_read_string(node1, "compatible", &p1);
    printk("itop4412-tree-sum  compatible is: %s\n",p1);
//read string "status"
    of_property_read_string(node1, "status", &p1);
    printk("itop4412-tree-sum  status is: %s\n",p1);
//read u32 "test-u32"
    //of_property_read_u32_array(node1,"test-u32",&value,1);
    of_property_read_u32(node1,"test-u32",&value);
    printk("itop4412-tree-sum  test-u32 is: <%d>\n",value);
//read     u32s test-u32s 
    of_property_read_u32_array(node1, "test-u32s", p2, 2);
    printk("itop4412-tree-sum  test-u32s is: <%d>,<%d>\n",p2[0],p2[1]);
//read u8s test-u8s
    of_property_read_u8_array(node1, "test-u8s", testmac, 6);
    printk("itop4412-tree-sum  test-u8s is: <%x>,<%x>,<%x>,<%x>,<%x>,<%x>\n",testmac[0],testmac[1],testmac[2],testmac[3],testmac[4],testmac[5]);

//***************************************************************//    
//***************************************************************//    
//get "itop-child-node1" device node  
    childnode1 = of_get_child_by_name(node1,"itop-child-node1");
    if(childnode1 == NULL){
        printk("of_get_child_by_name failed\n");
        return -ENODEV;
    }
    printk("of_get_child_by_name ok\n");
//We can get child-node info with childnode1 like node1
//e.g
    of_property_read_string(childnode1, "test-string", &p1);
    printk("itop-child-node1  test-string is: %s\n",p1);
//The code above also can run in "xx_probe{...}" and anywhere in driver code
    
    return platform_driver_register(&treesum_driver);
}

static void treesum_exit(void)
{
    printk(KERN_ALERT "Goodbye, curel world\n");
    platform_driver_unregister(&treesum_driver);
}

module_init(treesum_init);
module_exit(treesum_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("rty");
MODULE_DESCRIPTION("itop4412,tree-sum");
View Code

8、设备树小结

设备树,主要是学习设备树如何在驱动中获取设备树的数据,前面演示的例程,只是获取设备树数据API的一部分。

作者后面给大家提供例程这个里面的API尽量多的用到设备树头文件中的函数。

  include/linux/gpio/consumer.h
  include/linux/property.h

 


posted @ 2020-09-13 16:40  笑不出花的旦旦  阅读(252)  评论(0)    收藏  举报