Linux设备树实战

版权声明:转载请声明 https://blog.csdn.net/qq_40732350/article/details/83716374

1 简单配置

先配置编译:参考https://blog.csdn.net/flappy_boy/article/details/73752860

参考:origen的设备树文件

cp     arch/arm/boot/dts/exynos4210-origen.dts         arch/arm/boot/dts/test.dts

添加新文件需要更改Makefile才能编译

vim arch/arm/boot/dts/Makefile        //在CONFIG_ARCH_EXYNOS后添加内容
test.dtb

编译设备树文件

make dtbs

拷贝内核和设备树文件到/tftpboot/下

cp    arch/arm/boot/dts/test.dtb   /tftpboot/

设置启动参数

bootargs=root=/dev/nfs nfsroot=192.168.43.30:/home/liu/ARM/rootfs/rootfs2 ip=192.168.43.10:192.168.43.30:192.168.43.1:255.255.255.0::eth0:off init=/linuxrc console=ttySAC2,115200
bootcmd=tftp 30008000 zImage;     tftp 30008020 test.dtb;     bootm 30008000 - 30008020

2 编写自己的设备节点

test_node@12345678{
		compatible = "farsight,tst";
		reg = <0x12345678 0x12
		       0x87654321 0x34>;
		tesprop,mytest;
		test_list_string = "red fish", "fly fish", "blue, fish";
}

查看添加的设备节点:

#cd /proc/
#ls
    device-tree
#cd device-tree/
#ls
	test_node@12345678
#cd test_node@12345678
#ls
	compatible reg name 
	testprop,mytest test_list_string
#cat name
	test_node

注意:这下可以在驱动中放心去拿到信息

3 重要结构体

每一个dts文件中的节点会被系统构造成一个设备节点

struct device_node {
	const char *name;
	const char *type;
	phandle phandle;
	char	*full_name;

	struct	property *properties;
	struct	property *deadprops;	/* removed properties */
	struct	device_node *parent;
	struct	device_node *child;
	struct	device_node *sibling;
	struct	device_node *next;	/* next device of same type */
	struct	device_node *allnext;	/* next in list of all nodes */
	struct	proc_dir_entry *pde;	/* this node's proc directory */
	struct	kref kref;
	unsigned long _flags;
	void	*data;
#if defined(CONFIG_SPARC)
	char	*path_component_name;
	unsigned int unique_id;
	struct of_irq_controller *irq_trans;
#endif
};

每个节点的属性对应一个结构体

struct property {
	char	*name;
	int	length;
	void	*value;
	struct property *next;
	unsigned long _flags;
	unsigned int unique_id;
};

4 编写驱动——读取compatible

#include <of.h>

struct device_node *node_test =NULL;
struct property    *node_test_prop = NULL;

static int __init test_node_init(void)
{   
	printk(KERN_INFO "module init\n");

	/*get the device node*/
	node_test = of_find_node_by_path("/test_node@12345678");
	if(node_test){
		printk(KERN_INFO "node name = %s\n", node_test->name);
		printk(KERN_INFO "node full name = %s\n", node_test->full_name);
	}else{
		printk(KERN_ERR "test_node not found\n");
		return ENXIO;
	}

	/*gte node property "compatible"*/
	node_test_prop = of_find_property(node_test, "compatible", NULL);
	if(node_test_prop){
		printk(KERN_INFO "node compatible name = %s\n", node_test_prop->name);
		printk(KERN_INFO "node compatible value = %s\n", (char *)node_test_prop->value);		
	}else{
		printk(KERN_ERR "test_node compatible not found\n");
		return ENXIO;
	}

	/*判断节点中是否有一个属性是这个字符串"farsight,test"*/
	if(of_device_is_compatible(node_test, "farsight,test")){
		printk(KERN_INFO "farsight,test belon to node_test\n");
	}else{
		printk(KERN_ERR "ON farsight,test\n");
	}
        return 0;
}

static void __exit test_node_exit(void)
{
	printk(KERN_INFO "module exit\n");
}

module_init(test_node_init);
module_exit(test_node_exit);

MODULE_LICENSE("GPL");

输出结果:

node name = test_node
node full name = test_node@12345678
node compatible name = compatible
node compatible value = farsight,tst
farsight,test belong to node_test

5 编写驱动——读取reg

#include <of.h>

#define REG_LEN 4


struct device_node *node_test =NULL;
struct property    *node_test_prop = NULL;
unsigned int 	    reg_array[REG_LEN] = {0};

static int __init test_node_init(void)
{ 
	int ret = -1;
        int i;
	printk(KERN_INFO "module init\n");

	/*get the device node*/
	node_test = of_find_node_by_path("/test_node@12345678");
	if(node_test){
		printk(KERN_INFO "node name = %s\n", node_test->name);
		printk(KERN_INFO "node full name = %s\n", node_test->full_name);
	}else{
		printk(KERN_ERR "test_node not found\n");
		return ENXIO;
	}

	ret = of_property_read_u32_array(node_test, "reg", reg_array, REG_LEN)
	if(!ret){
		for(i = 0; i < REG_LEN; i++)
		{
			printk(KERN_INFO "regdata[%d] = 0x%x\n", i, reg_array[i]);			
		}	
	}else{
		printk(KERN_ERR "get property reg fail\n");
		return ENXIO;
	}
}

static void __exit test_node_exit(void)
{
	printk(KERN_INFO "module exit\n");
}

module_init(test_node_init);
module_exit(test_node_exit);

MODULE_LICENSE("GPL");

运行结果:

node name = test_node
node full name = test_node@12345678
regdata[0] = 0x12345678
regdata[1] = 0x12
regdata[2] = 0x87654321
regdata[3] = 0x34

6 编写驱动——读取字符串

#include <of.h>

#define REG_LEN 4
#define STR_LEN 3

struct device_node *node_test =NULL;
struct property    *node_test_prop = NULL;
unsigned int 	    reg_array[REG_LEN] = {0};
const char         *str_array[STR_LEN] = {0};

static int __init test_node_init(void)
{ 
	int ret = -1;
	int i;
	printk(KERN_INFO "module init\n");

	/*get the device node*/
	node_test = of_find_node_by_path("/test_node@12345678");
	if(node_test){
		printk(KERN_INFO "node name = %s\n", node_test->name);
		printk(KERN_INFO "node full name = %s\n", node_test->full_name);
	}else{
		printk(KERN_ERR "test_node not found\n");
		return ENXIO;
	}
	
	for(i = 0; i < STR_LEN; i++)
	{
		ret = of_property_read_string_index(node_test, "test_list_string", i, &str_array);
		if(!ret){
			printk(KERN_INFO "strdata[%d] = %s\n", i, str_array[i]);	
		}else{
			printk(KERN_ERR "NO strdata[%d]\n", i);
			return ENXIO;
		}
	}

	return 0;
}

static void __exit test_node_exit(void)
{
	printk(KERN_INFO "module exit\n");
}

module_init(test_node_init);
module_exit(test_node_exit);

MODULE_LICENSE("GPL");

运行结果:

node name = test_node
node full name = test_node@12345678
strdata[0] = red fish
strdata[1] = fly fish
strdata[2] = blue, fish

6 编写驱动——读取GPIO

test_node@12345678{
		compatible = "farsight,tst";
		reg = <0x12345678 0x12
			   0x87654321 0x34>;
		tesprop,mytest;
		test_list_string = "red fish", "fly fish", "blue, fish";
		interrupt-parent = <&gpx1>;
		gpios = <&gpx1 1 1    //gpx1_1 高电平有效
			 &gpx1 2 1
			 &gpx3 2 1>;
}

#include <of.h>

#define GPIO_NUM 3

struct device_node *node_test =NULL;
static unsigned int gpio_array[GPIO_NUM] = {0};

static int __init test_node_init(void)
{ 
	int ret = -1;
	int i;
	printk(KERN_INFO "module init\n");

	/*get the device node*/
	node_test = of_find_node_by_path("/test_node@12345678");
	if(node_test){
		printk(KERN_INFO "node name = %s\n", node_test->name);
		printk(KERN_INFO "node full name = %s\n", node_test->full_name);
	}else{
		printk(KERN_ERR "test_node not found\n");
		return ENXIO;
	}

	for (i = 0; i < GPIO_NUM; i++) {
		gpio_array[i] = of_get_gpio(test_node, i);
		if (gpio_is_valid(gpio)) {
			printk(KERN_INFO "gpio[%d]: %d\n", i, gpio_array[i]);
		}

		ret = gpio_request(gpio_array[i], "key");
		if (ret) {
			printk(KERN_ERR "gpio [%d] request failed\n", i);
			return ENXIO;
		}
	}
	return 0;
}

static void __exit test_node_exit(void)
{
	printk(KERN_INFO "module exit\n");
}

module_init(test_node_init);
module_exit(test_node_exit);

MODULE_LICENSE("GPL");

7 编写驱动——读取中断

test_node@12345678{
		compatible = "farsight,tst";
		reg = <0x12345678 0x12
			   0x87654321 0x34>;
		tesprop,mytest;
		test_list_string = "red fish", "fly fish", "blue, fish";
		interrupts = <&gpx1 2 3>,  //对应gpx1_2 ,上升沿和下降沿触发
			     <&gpx1 3 3>,  //对应gpx1_3 ,上升沿和下降沿触发
			     <&gpx3 2 3>;  //对应gpx3_2 ,上升沿和下降沿触发
}
gpx1: gpx1 {
		gpio-controller;
		#gpio-cells = <2>;
		interrupt-controller;
		interrupt-parent = <&gic>;
		interrupts = <0 136 0>,   //gpx1_0
			     <0 137 0>,   //gpx1_2
			     <0 138 0>;   //gpx1_3
		#interrupt-cells = <3>;
};
gpx3: gpx3 {
		gpio-controller;
		#gpio-cells = <2>;
		interrupt-controller;
		interrupt-parent = <&gic>;
		interrupts = <0 156 0>,   //gpx3_0
			     <0 157 0>,   //gpx3_1
			     <0 158 0>;   //gpx3_2
		#interrupt-cells = <3>;
};	

gpx节点驱动工程师不用写,SOC厂商会写好,这里只是方便读

#include <of.h>

#define INTR_NUM 3

struct device_node *node_test =NULL;
static unsigned int intr_arrary[INTR_NUM] = {0};

static int __init test_node_init(void)
{ 
	int ret = -1;
	int i;
	printk(KERN_INFO "module init\n");

	/*get the device node*/
	node_test = of_find_node_by_path("/test_node@12345678");
	if(node_test){
		printk(KERN_INFO "node name = %s\n", node_test->name);
		printk(KERN_INFO "node full name = %s\n", node_test->full_name);
	}else{
		printk(KERN_ERR "test_node not found\n");
		return ENXIO;
	}

	for(i = 0; i < INTR_NUM; i++)
	{
		intr_arrary[i] = irq_of_parse_and_map(test_node, i);//得到中断号
		printk(KERN_INFO "intr[%d] = %d\n", i, intr_arrary[i]);
	}

	return 0;
}

static void __exit test_node_exit(void)
{
	printk(KERN_INFO "module exit\n");
}

module_init(test_node_init);
module_exit(test_node_exit);

MODULE_LICENSE("GPL");

运行结果:

node name = test_node
node full name = test_node@12345678
intr[0] = 137
intr[1] = 138
intr[2] = 157

可以参考这个:

https://blog.csdn.net/u011583798/article/details/70940954

猜你喜欢

转载自blog.csdn.net/qq_40732350/article/details/83716374