可以学设备树的课程:https://edu.csdn.net/course/detail/9511?utm_source=blog2edu
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