2014-06-19 17:59:48 strugglelg 阅读数 6986
  • 深入探究Linux/VxWorks设备树视频教程

    很多人看了很Linux多设备树的资料后,还是不会用设备树。该Linux设备树视频课程假设一个全新的电路板,上面有4个ARM核,一片中断控制器、一个UART、一个GPIO控制器、一个I2C控制器、一个SPI控制器、I2C接一个触摸屏、一个以太网控制器,并依据这个假设的电路板,从头到尾构建一个新的dts文件。并讲解整个板级、设备/驱动匹配的全细节,我们把设备树的使用彻底地变得可实践。

    5203 人正在学习 去看看 宋宝华

dts的概念,在这里就不多说了,

我这里的例子是 openwrt 的dts; cpu是7620的;


这里的power_led的gpio 44


先看右图:

有一个叫gpio2 的结构体,

gpio-base:  gpio个数的头, 基地址

num-gpios: gpio个数的尾

整个意思是 gpio40 ----- gpio72是属于gpio2这个域里面的; <=gpio39,   >=gpio73都不是这里的;



再看左图的power:

gpio = <&gpio2  4   1>;

它指定了power_led的gpio是   用上面的gpio2域,

4是 偏移地址,即40+4=44;   

1是默认高电平(即低电平触发);


2019-01-07 23:13:08 sinat_30545941 阅读数 1827
  • 深入探究Linux/VxWorks设备树视频教程

    很多人看了很Linux多设备树的资料后,还是不会用设备树。该Linux设备树视频课程假设一个全新的电路板,上面有4个ARM核,一片中断控制器、一个UART、一个GPIO控制器、一个I2C控制器、一个SPI控制器、I2C接一个触摸屏、一个以太网控制器,并依据这个假设的电路板,从头到尾构建一个新的dts文件。并讲解整个板级、设备/驱动匹配的全细节,我们把设备树的使用彻底地变得可实践。

    5203 人正在学习 去看看 宋宝华

linux 设备驱动文件在与 dts 中的设备板级硬件信息匹配的关键字是 compatible 属性。即比较驱动文件中 of_device_id 结构体元素的 .compatible 成员变量和 dts 文件中 node 中 compatible 属性两个字符串。

Rationale:

linux 启动从 lk jump 到 kernel 之后

    函数调用的深度比较深所以图比较长,其中细节部分省略,可以打开具体源码去看。

可以看到最后调用的函数

static inline int of_driver_match_device(struct device *dev,const struct device_driver *drv)
	--->of_match_device(drv->of_match_table, dev) != NULL;
		--->of_match_node(matches, dev->of_node)
			--->__of_match_node(matches, node)
				--->static const struct of_device_id *__of_match_node(const struct             
                       of_device_id *matches,
					   const struct device_node *node)
					{
						const struct of_device_id *best_match = NULL;
						int score, best_score = 0;

						if (!matches)
							return NULL;

						for (; matches->name[0] || matches->type[0] || matches->compatible[0]; matches++) {
                  //此函数将driver的of_match_table->compatible和node中的compatible比较
							score = __of_device_is_compatible(node, matches->compatible,
											  matches->type, matches->name); 
							if (score > best_score) {
								best_match = matches;
								best_score = score;
							}    
						}

						return best_match;
					}

传递到最后__of_device_is_compatible函数将driver的of_match_table->compatible和node中的compatible比较,这个比较不是单纯的比较,是一种加分制。

匹配成功之后会进行probe,如果driver 的 probe 执行不成功(比如硬件问题,或者没有挂载设备),会调用sys系列函数进行驱动卸载。

2019-05-30 15:23:05 oqqGuMu 阅读数 395
  • 深入探究Linux/VxWorks设备树视频教程

    很多人看了很Linux多设备树的资料后,还是不会用设备树。该Linux设备树视频课程假设一个全新的电路板,上面有4个ARM核,一片中断控制器、一个UART、一个GPIO控制器、一个I2C控制器、一个SPI控制器、I2C接一个触摸屏、一个以太网控制器,并依据这个假设的电路板,从头到尾构建一个新的dts文件。并讲解整个板级、设备/驱动匹配的全细节,我们把设备树的使用彻底地变得可实践。

    5203 人正在学习 去看看 宋宝华

一直想搞明白,自从linux开始使用设备树后,从哪里开始加载和bootloadt kenel之间怎么关联,然后总线驱动如何将这些设备挂上去的。

下周开始总结。

先转载一些基本概念:

 

简介
dts
硬件的相应信息都会写在.dts为后缀的文件中,每一款硬件可以单独写一份xxxx.dts,一般在Linux源码中存在大量的dts文件,对于arm架构可以在arch/arm/boot/dts找到相应的dts,另外mips则在arch/mips/boot/dts,powerpc在arch/powerpc/boot/dts。

dtsi
值得一提的是,对于一些相同的dts配置可以抽象到dtsi文件中,然后类似于C语言的方式可以include到dts文件中,对于同一个节点的设置情况,dts中的配置会覆盖dtsi中的配置

dtc
dtc是编译dts的工具,可以在Ubuntu系统上通过指令apt-get install device-tree-compiler安装dtc工具,不过在内核源码scripts/dtc路径下已经包含了dtc工具;

dtb
dtb(Device Tree Blob),dts经过dtc编译之后会得到dtb文件,dtb通过Bootloader引导程序加载到内核。所以Bootloader需要支持设备树才行;Kernel也需要加入设备树的支持;

 

å¨è¿éæå¥å¾çæè¿°

--------------------- 
作者:UncleMac 
来源:CSDN 
原文:https://blog.csdn.net/u010632165/article/details/89847843 
版权声明:本文为博主原创文章,转载请附上博文链接!

 

 

2017-07-13 14:05:52 zoosenpin 阅读数 280
  • 深入探究Linux/VxWorks设备树视频教程

    很多人看了很Linux多设备树的资料后,还是不会用设备树。该Linux设备树视频课程假设一个全新的电路板,上面有4个ARM核,一片中断控制器、一个UART、一个GPIO控制器、一个I2C控制器、一个SPI控制器、I2C接一个触摸屏、一个以太网控制器,并依据这个假设的电路板,从头到尾构建一个新的dts文件。并讲解整个板级、设备/驱动匹配的全细节,我们把设备树的使用彻底地变得可实践。

    5203 人正在学习 去看看 宋宝华

@ gv.py

out_file = ''
temp_file = ''
dt_dir_path = ''
nr_plats = 1
is_oem = False
is_ext = False
dts_name = ''

arg0_proc_name = ''
arg1_plat_name = ''


@ dts_list.py

################################################
# Show dts tree for msm platform
# Author: George Tso <zoosenpin@163.com>
# 2015-2016, all rights reserved.
################################################

import sys,os
import shutil
import gv

def my_printf(string):
    print string

def print_usage(toast):
    if toast != '':
        print '\n' + toast
    print "\nUsage: python " + gv.arg0_proc_name + " [OPTION...]\n"
    print "    If you want to print all the DT of one platform, you should"
    print "    assign the directory as the first argument, otherwise it "
    print "    will use the current work directory."
    print "    -o    list all the .dtsi files which belong to a .dts to"
    print "        a file"
    print "    -e    list all the .dtsi files which belong to a .dts to"
    print "        a file and copy the assciated .dtsi files to"
    print "        ." + os.path.sep + 'EXT\n'
    print "For example:"
    print "    Linux:"
    print "    python " + gv.arg0_proc_name + " msm8909"
    print "    python " + gv.arg0_proc_name + " ./ msm8909"
    print "    python " + gv.arg0_proc_name + " -o msm8909-1gb-qrd-skuc.dts"
    print "    python " + gv.arg0_proc_name + " -e msm8909-1gb-qrd-skuc.dts\n"
    print "    vi KERNEL-msm8909.list"
    print "    vi OEM-msm8909-1gb-qrd-skuc.dts.list"
    print "    vi ./EXT/OEM-msm8909-1gb-qrd-skuc.dts.list\n"

    print "    <------------------------------------------------>\n"
    print "    Windows:"
    print "    python " + gv.arg0_proc_name + " msm8909"
    print "    python " + gv.arg0_proc_name + " E:\F\case\dts_test msm8909"
    print "    python " + gv.arg0_proc_name + " -o E:\F\case\dts_test\msm8909-1gb-qrd-skuc.dts"
    print "    python " + gv.arg0_proc_name + " -e E:\F\case\dts_test\msm8909-1gb-qrd-skuc.dts\n"
    print "    Open E:\F\case\dts_test\KERNEL-msm8909.list with text editor"
    print "    Open E:\F\case\dts_test\OEM-msm8909-1gb-qrd-skuc.dts.list "
    print "        with text editor"
    print "    Open E:\F\case\dts_test\EXT\OEM-msm8909-1gb-qrd-skuc.dts.list "
    print "        with text editor\n"

def write_file(f_name, line):
    h = open(f_name, 'a+')
    h.writelines(line)
    h.close()

def contains_substring(src, sub):
    if sub in src:
        return True
    elif src.startswith(sub):
        return True
    else:
        return False

def get_dt_list(dir_path, temp_file):
    for dts_file in os.listdir(dir_path):
        if contains_substring(dts_file, gv.arg1_plat_name) > 0:
            write_file(temp_file, dir_path + os.path.sep + dts_file + '\n')

def list_one_tree(dt_file_path, h, out_file):
    fp = open(dt_file_path, 'r')
    for line in fp:
        p = line.lstrip(' ')
        if p.startswith('/*') or p.startswith('//'):
            continue

        if line.find('include') > 0 and line.find(".dtsi") > 0:
            if line.find("/include/") > 0:
                idx = line.find('/include/')
        idx += 9
                p = line[idx:len(line)]
            else:
                idx = line.find('include')
        idx += 7
                p = line[idx:len(line)]
            p = p.lstrip('/').lstrip(' ').lstrip('\"').rstrip('\"')
            p = p.rstrip('\r').rstrip('\n').rstrip('\"')
            write_file(out_file, h + p + '\n')

            # Get the next
        p = p.rstrip('\r').rstrip('\n').lstrip('\"').rstrip('\"')
            p = gv.dt_dir_path + os.path.sep + p
            if os.path.exists(p):
                list_one_tree(p, h + '-', out_file)
    fp.close()

def walk_dt(dt_file_path, out_file, is_oem):
    p = dt_file_path

    idx = dt_file_path.find(os.path.sep)
    if idx > 0:
        idx += 1
        p = dt_file_path[idx:len(dt_file_path)]

    if p != '':
        write_file(out_file,
                "/**************(" + str(gv.nr_plats) +
        ") platform*****************/\n")
        gv.nr_plats += 1

        p = p.rstrip('\r').rstrip('\n')
        idx = p.rfind(os.path.sep)
        if idx > 0:
            idx += 1
            _dts = p[idx:]
        else:
            _dts = p
        write_file(out_file, _dts + '\n')

    dt_file_path = dt_file_path.rstrip('\r').rstrip('\n')
        list_one_tree(dt_file_path, "-", out_file)
        write_file(out_file, "\n")

def _show_dt(dir_path):
    h = open(gv.temp_file, 'r')
    for line in h:
        line = line.rstrip('\r').rstrip('\n')
        if line.endswith('.dts') == True:
            walk_dt(line, gv.out_file, False)
    h.close();

def create_file(file):
    if os.path.exists(file):
        os.remove(file)

    h = open(file, 'w')
    h.write('Author: George Cho <zoosenpin@163.com>\n')
    h.write('If you have any good advice, you can contact me directly\n\n')
    h.close()

def remove_file(file):
    if os.path.exists(file):
        os.remove(file)

def show_dt():
    create_file(gv.temp_file)

    if len(gv.dt_dir_path) > 1:
        get_dt_list(gv.dt_dir_path, gv.temp_file)
        _show_dt(gv.dt_dir_path)

    remove_file(gv.temp_file)

def remove_dir(dir_path):
    if os.path.isdir(dir_path):
        for file in os.listdir(dir_path):
            os.remove(dir_path + os.path.sep + file)
        os.removedirs(dir_path)

def extract_one_DT_to_EXT(file_path):
    if not os.path.exists(file_path):
        return

    is_found = False
    src_dir = gv.dt_dir_path
    dst_dir = gv.dt_dir_path

    h = open(file_path, 'r')
    for line in h:
        if line.find('*') > 0:
            is_found = True
            continue
        if (is_found == False):
            continue
        line = line.lstrip('-').lstrip('/').lstrip('\\')
        line = line.rstrip('\r').rstrip('\n').rstrip('\"')
        src_path = src_dir + os.path.sep + line
        dst_path = dst_dir + os.path.sep + 'EXT' + os.path.sep + line
        if os.path.exists(src_path) and not os.path.isdir(src_path):
            shutil.copy(src_path, dst_path)

def parse_args():
    if len(sys.argv) == 2:
        gv.dt_dir_path = os.getcwd()
        gv.arg1_plat_name = sys.argv[1]
    elif len(sys.argv) == 3:
        if not os.path.isdir(sys.argv[1]) and cmp(sys.argv[1], '-o') and cmp(sys.argv[1], '-e'):
            print_usage()
            sys.exit(0)
        elif not cmp(sys.argv[1], '-o'):
            gv.is_oem = True
            idx = sys.argv[2].rfind(os.path.sep)
            if idx > 0:
                idx += 1
                gv.dt_dir_path = sys.argv[2][0:idx]
                gv.dts_name = sys.argv[2][idx:]
            else:
                gv.dt_dir_path = os.getcwd()
                gv.dts_name = sys.argv[2]
        elif not cmp(sys.argv[1], '-e'):
            gv.is_ext = True
            idx = sys.argv[2].rfind(os.path.sep)
            if idx > 0:
                idx += 1
                gv.dt_dir_path = sys.argv[2][0:idx]
                gv.dts_name = sys.argv[2][idx:]
            else:
                gv.dt_dir_path = os.getcwd()
                gv.dts_name = sys.argv[2]
        else:
            gv.dt_dir_path = sys.argv[1]
            gv.arg1_plat_name = sys.argv[2]

    gv.dt_dir_path = gv.dt_dir_path.rstrip('\r').rstrip('\n')
    gv.temp_file = gv.dt_dir_path + os.path.sep + '.tmp.log'
    if gv.is_oem == True:
        gv.out_file = gv.dt_dir_path + os.path.sep + 'OEM-' + gv.dts_name + '.list'
    elif gv.is_ext == True:
        remove_dir(gv.dt_dir_path + os.path.sep + 'EXT')
        os.makedirs(gv.dt_dir_path + os.path.sep + 'EXT')
        gv.out_file = gv.dt_dir_path + os.path.sep + 'EXT' + os.path.sep + 'OEM-' + gv.dts_name + '.list'
    else:
        gv.out_file = gv.dt_dir_path + os.path.sep + 'KERNEL-' + gv.arg1_plat_name + '.list'

    print '\nDT directory: ' + gv.dt_dir_path
    if gv.is_ext:
        print '\nEXT directory: ' + gv.dt_dir_path + os.path.sep + 'EXT' + os.path.sep
    print '\nout file: ' + gv.out_file + '\n'
    create_file(gv.out_file)

def main():
    gv.arg0_proc_name = sys.argv[0]
    if sys.argv[0].rfind(os.path.sep) > 0 :
        index = sys.argv[0].rfind(os.path.sep)
        gv.arg0_proc_name = sys.argv[0][index+1:]

    if len(sys.argv) < 2:
        print_usage('')
        sys.exit(0)

    parse_args()

    if gv.is_ext == True:
        walk_dt(gv.dt_dir_path + os.path.sep + gv.dts_name,
        gv.out_file, True)
        extract_one_DT_to_EXT(gv.out_file)
    elif gv.is_oem == True:
            walk_dt(gv.dt_dir_path + os.path.sep + gv.dts_name,
        gv.out_file, True)
    else:
        if gv.arg1_plat_name.find('.dts') > 0 or gv.arg1_plat_name.find('dtsi') > 0:
            print_usage('Invalid arguments')
            sys.exit(0)
        show_dt()

if __name__ == '__main__':
    main()


2018-07-25 22:51:46 shenhuxi_yu 阅读数 116
  • 深入探究Linux/VxWorks设备树视频教程

    很多人看了很Linux多设备树的资料后,还是不会用设备树。该Linux设备树视频课程假设一个全新的电路板,上面有4个ARM核,一片中断控制器、一个UART、一个GPIO控制器、一个I2C控制器、一个SPI控制器、I2C接一个触摸屏、一个以太网控制器,并依据这个假设的电路板,从头到尾构建一个新的dts文件。并讲解整个板级、设备/驱动匹配的全细节,我们把设备树的使用彻底地变得可实践。

    5203 人正在学习 去看看 宋宝华
linux3.0 spi-s3c64xx.c
最近写一个spi dma的程序,不得已要先改在linux3.0上面
有dts支持的情况下一般是dts 的devnode 跟platform driver的of_match_table 的compatible 
属性match然后probe
3.0的时候还不支持dts,那用来match的属性各自在何处定义的呢
static int platform_match(struct device *dev, struct device_driver *drv)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct platform_driver *pdrv = to_platform_driver(drv);

	/* Attempt an OF style match first */
	if (of_driver_match_device(dev, drv))
		return 1;
//对比device dts node和driver of_match_table de compatibel属性
	/* Then try to match against the id table */
	if (pdrv->id_table)
		return platform_match_id(pdrv->id_table, pdev) != NULL;
//对比driver的id_table与device的name是否匹配
	/* fall-back to driver name match */
	return (strcmp(pdev->name, drv->name) == 0);
//直接对比device的name和driver的name
}


platform_driver结构体定义了driver的name
static struct platform_driver s3c64xx_spi_driver = {
	.driver = {
		.name	= "s3c64xx-spi",
		.owner = THIS_MODULE,
	},

没有match table 也没有id_table 也没有明显的看到有device name,这时候driver和device是如何match的呢

linux3.18  4.9 版本支持dts,platform device加入的方法是通过of_platform_populate根据dts的dev node 添加进platform device list,如果没有dts的话是在哪个阶段把platform device 添加进来的呢,mach-init!

在mach-s3c64xx.c中找到了spi的platform device的定义


struct platform_device s3c64xx_device_spi0 = {
	.name		  = "s3c64xx-spi",
	.id		  = 0,
	.num_resources	  = ARRAY_SIZE(s3c64xx_spi0_resource),
	.resource	  = s3c64xx_spi0_resource,
	.dev = {
		.dma_mask		= &spi_dmamask,
		.coherent_dma_mask	= DMA_BIT_MASK(32),
		.platform_data = &s3c64xx_spi0_pdata,
	},
};
EXPORT_SYMBOL(s3c64xx_device_spi0);


static struct platform_device *smdk6410_devices[] __initdata = {
    &s3c64xx_device_spi0,
}

static void __init smdk6410_machine_init(void)
{

	s3c_ide_set_platdata(&smdk6410_ide_pdata);

	platform_add_devices(smdk6410_devices, ARRAY_SIZE(smdk6410_devices));
}

在machine_init里建立platform device,spi init的时候注册了driver后probe就会执行 

Linux: 解析DTS

阅读数 10

linux dts interrupt

阅读数 2403

linux clock dts

阅读数 41

linux msm dts加载分析

阅读数 2925

没有更多推荐了,返回首页