嵌入式开发记录-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");
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");
8、设备树小结
设备树,主要是学习设备树如何在驱动中获取设备树的数据,前面演示的例程,只是获取设备树数据API的一部分。
作者后面给大家提供例程,这个里面的API尽量多的用到设备树头文件中的函数。
include/linux/gpio/consumer.h
include/linux/property.h

浙公网安备 33010602011771号