• linux驱动开发 使用设备树编写一个led驱动程序



    前言

    本文将带大家学习如何使用设备树编写一个LED的驱动程序。
    我这里使用的开发板是百问网的imx6ull。

    一、设备树的配置

    1.进入设备树目录查看设备树文件
    在这里插入图片描述
    2.添加led子节点的信息
    在这里插入图片描述
    3.返回源码目录生成dtb文件
    在这里插入图片描述
    4.将生成的dtb文件拷贝到开发板的网络文件系统
    在这里插入图片描述
    5.将dtb文件拷贝到开发板的/boot目录下重新启动开发板

    二、重新启动后查看设备信息

    1.查看创建出的平台设备

    进入/sys/bus/platform/devices/目录可以查看根据设备树生成的平台设备
    在这里插入图片描述

    2.查看节点

    进入/sys/firmware/devicetree/base目录查看生成的节点
    在这里插入图片描述

    3.编写驱动程序

    #include <linux/module.h>
    #include <linux/poll.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>
    #include <linux/fcntl.h>
    #include <linux/timer.h>
    #include <linux/workqueue.h>
    #include <asm/current.h>
    #include <linux/delay.h>
    #include <linux/timex.h>
    
    
    
    int major=0;
    static struct class *led_class;
    static struct gpio_desc *led_gpio;
    
    
    static ssize_t led_read (struct file *file, char __user *buf, size_t size, loff_t *off)
    {
    	return 0;
    
    }
    
    static int led_open (struct inode *inode, struct file *file)
    {
    	gpiod_direction_output(led_gpio, 0);
    	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    	return 0;
    }
    
    static ssize_t led_write (struct file *file, const char __user *buf, size_t size, loff_t *off)
    {
    	char val;
    	int err;
    	err = copy_from_user(&val, buf, 1);
    	gpiod_set_value(led_gpio, val);
    	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    		
    	return 1;
    }
    
    
    
    static struct file_operations led_ops={
    	.owner		= THIS_MODULE,
    	.open		= led_open,
    	.read		= led_read,
    	.write		= led_write,	
    };
    
    
    static int led_probe(struct platform_device *pdev)
    {
    	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    
    	/*1.获取硬件信息*/
    	led_gpio=gpiod_get(&pdev->dev, NULL, 0);
    	if (IS_ERR(led_gpio)) {
    		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    	}
    	
    	/*2.创建设备节点*/	
    	device_create(led_class,NULL, MKDEV(major, 0), NULL, "100askled");
    
            
        return 0;
    	
    }
    
    static int led_remove(struct platform_device *pdev)
    {		
    	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    	gpiod_put(led_gpio);
    	return 0;
    }
    
    static const struct of_device_id my_led[] = {
        { .compatible = "100ask,led" },
        { },
    };
    
    
    static struct platform_driver led={
    	.driver = {
    		.name = "led",
    		.of_match_table = my_led,	
    	},
    	.probe = led_probe,
    	.remove	= led_remove,	
    };
    
    
    static int __init led_init(void)
    {
    	int err;
    	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    	/*确定主设备号*/
    	major=register_chrdev(major, "myled", &led_ops);
    	/*创建类*/
    	led_class=class_create(THIS_MODULE, "led");
    	if (IS_ERR(led_class)) {
    		printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    		unregister_chrdev(major, "myled");
    		return PTR_ERR(led_class);
    	}
    	err=platform_driver_register(&led);
    	return 0;
    }
    
    static void __exit led_exit(void)
    {
    	printk("%s %s line %d\n", __FILE__, __FUNCTION__, __LINE__);
    	device_destroy(led_class, MKDEV(major, 0));
    	class_destroy(led_class);
    	unregister_chrdev(major, "myled");
    	platform_driver_unregister(&led);
    }
    
    module_init(led_init);
    module_exit(led_exit);
    
    MODULE_LICENSE("GPL");
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144

    总结

    使用设备树来编写驱动程序极大的方便了我们写驱动程序,如果不使用设备树去编写驱动程序的话那只能使用寄存器操作硬件。
    有了设备树后操作硬件就变得非常简单了。

  • 相关阅读:
    帆软报表执行sql报SQL command not properly ended
    如何理解分布式架构和微服务架构呢
    【genius_platform软件平台开发】第七十六讲:vs预处理器定义的牛逼写法!!!!(其他组牛逼conding人员告知这么配置来取消宏定义)
    vue3.0中实现excel文件的预览
    python安装selselenium,chromedriver,秒杀脚本教程
    TVTK-SV02 数据管线简介
    编写一个GStreamer插件
    python selenium 滑动后获取动态追加的元素
    137. 只出现一次的数字 II
    JMeter分布式
  • 原文地址:https://blog.csdn.net/m0_49476241/article/details/126549589