23.2.13 Drive development 设备树信息解析相关代码

这篇博客介绍了Linux驱动开发中的设备树信息解析,包括设备树的概念、dts文件、dtb文件及其作用。文章还深入讲解了epoll在IO多路复用中的应用,描述了epoll_create、epoll_ctl和epoll_wait等关键函数的工作原理。同时,提到了stdio.h等头文件的功能和标准输入输出函数的使用。
摘要由CSDN通过智能技术生成

1.练习课上代码

2.把设备树信息解析相关函数按照自己的理解发布CSDN

3.复习中断相关内核

IO多路复用---epoll

核心内容:一棵树一个链表三个方法

epoll会将要监听的事件文件描述符添加到内核里一颗红黑树上,当有事件发生,epoll会调用回调函数将发生事件的文件描述符添加到存放的链表中,程序中只需要判断这个表是否为空即可知道是否有事件发生,然后针对表中的文件描述符进行IO操作即可。

 一棵电路板上CPU、总线、设备组成的树

dtb文件会在内存中一直存在着,不会被内核或者应用程序占用,我们需要使用的时候可以直接使用dtb文件。dtb文件的内容会被解析生成多个device_node,然后这些device_node构成一棵树, 根节点为: of_root



🌟1.双亲表示法

💓2.孩子表示法

🌵3.孩子兄弟表示法

 

自动换行

#include <sys/epoll.h>

1. int epoll_create(int size)

                                                    功能:创建一个epoll(建立红黑树)

2. int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)

                                                     功能:epoll的操作函数

3.int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout);

                                                      功能:阻塞等待事件就绪

stdio.h      sys/types.h      sys/stat.h       sys/wait.h       fcntl.h          sys/select.h        sys/time.h         sys/epoll.h     unistd.h    stdlib.h      string.h

#include<stdio.h>                    

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/wait.h>

#include <fcntl.h>

#include <sys/select.h>

#include <sys/time.h>

#include <sys/epoll.h>

#include <unistd.h>

#include <stdlib.h>

#include<string.h>

 

 

 

stdio.h是stand input & output的缩写,意思是标准输入输出头文件。凡是用到标准输入输出函数,就要调用该头文件。

查看stdio.h目录下包含哪些函数:主要有文件访问、二进制输入/输出、格式化和非格式化输入/输出、文件定位、错误处理、文件操作等。

具体打开自己的VS安装目录,找到include文件夹,打开include夹下面的stdio.h文件即可查看

常用标准输入输出函数:

scanf()    从屏幕格式输入

printf()    格式输出到屏幕

getchar()    从屏幕得到一个字符

putchar()    字符输出到屏幕

gets()    从屏幕得到一个字符串

puts()    字符串输出到屏幕

fscanf()    从磁盘格式输入

fprintf()    格式输出到磁盘

fgetc()    从磁盘得到一个字符

fputc()    字符输出到磁盘

fgets()    从磁盘得到一个字符串

fputs()    字符串输出到磁盘

#号是预处理语句,表明在编译之前预先进行处理。

.h是header file的缩写,表面这是一个头文件。

include是文件包含命令,后面跟着引号""或者尖括号<>,意思是将引号或尖括号内指定的文件包含到本程序中,成为本程序的一部分,而包含的文件通常是由系统提供的。

区分引号""或者尖括号<>:尖括号<>编译程序会先到标准函数库中找文件,引号""编译程序会先从当前目录中找文件。
 

 

#include <sys/types.h>

基本系统数据类型

是Unix/Linux系统的基本系统数据类型的头文件,含有size_ttime_tpid_t等类型

NAME
       sys/types.h - data types

SYNOPSIS          (简要说明)
       #include <sys/types.h>

DESCRIPTION   (描述)
       The <sys/types.h> header shall include definitions for at least the following types (以下类型)

       blkcnt_t
              Used for file block counts.

       blksize_t
              Used for block sizes.

       clock_t
              Used for system times in clock ticks or CLOCKS_PER_SEC; see <time.h> .

       clockid_t
              Used for clock ID type in the clock and timer functions.

       dev_t  Used for device IDs.

       fsblkcnt_t
              Used for file system block counts.

       fsfilcnt_t
              Used for file system file counts.

       gid_t  Used for group IDs.

       id_t   Used as a general identifier; can be used to contain at least a pid_t, uid_t, or gid_t.

       ino_t  Used for file serial numbers.

       key_t  Used for XSI interprocess communication.

       mode_t Used for some file attributes.

       nlink_t
              Used for link counts.

       off_t  Used for file sizes.

       pid_t  Used for process IDs and process group IDs.

       size_t Used for sizes of objects.

       ssize_t
              Used for a count of bytes or an error indication.

       suseconds_t
              Used for time in microseconds.

       time_t Used for time in seconds.

       timer_t
              Used for timer ID returned by timer_create().

       trace_attr_t
              Used to identify a trace stream attributes object.

       trace_event_id_t
              Used to identify a trace event type.

       trace_event_set_t
              Used to identify a trace event type set.

       trace_id_t
              Used to identify a trace stream.

       uid_t  Used for user IDs.

       useconds_t
              Used for time in microseconds.

       All of the types shall be defined as arithmetic types of an appropriate length, with the following exceptions:

       key_t
       Additionally:

        * mode_t shall be an integer type.

        * nlink_t, uid_t, gid_t, and id_t shall be integer types.

        * blkcnt_t and off_t shall be signed integer types.

        * fsblkcnt_t, fsfilcnt_t,   and ino_t shall be defined as unsigned integer types.

        * size_t shall be an unsigned integer type.

        * blksize_t, pid_t, and ssize_t shall be signed integer types.

        * time_t and clock_t shall be integer or real-floating types.

 

       dts   设备树源文件                  dtc  设备树编译              dtb   二进制设备树镜像              dtsi   功能类似设备树文件的头文件  

 流程为      dts                             dtb                                device_node                      platform_device

什么是设备树

(1)设备树(dt:device tree)是linux内核采用的参数表示和传递技术,在系统引导启动阶段进行设备初始化的时候,将设备树中描述的硬件信息传递给操作系统;
(2)dts(device tree source):设备树源文件,描述设备信息的;
(3)dtc(device tree compiler):设备树编译/反编译/调试工具
(4)dtb(device tree binary):二进制设备树镜像
(5)dtsi(device tree source include):功能类似设备树文件的头文件,可以被dts文件通过include引用,dtsi文件一般是描述共性部分;
设备树的加载流程

dts文件经过dtc工具编译为dtb,内核加载并解析dtb文件,最终获得设备树的信息

dts文件中,在根节点中有一个compatible属性,该属性的值是一系列的字符串,比如compatible = “samsung,smdk2440”“samsung,smdk2410,samsung,smdk24xx”;,该属性就是告诉内核要选择什么样的machine_desc,因为machine_desc结构体中有一个dt_compat成员,该成员表示machine_desc支持哪些单板,所以内核会把compatible中的字符串与dt_compat进行依次比较。
 

一、dts产生原因
DTS即Device Tree Source 设备树源码, DeviceTree是一种描述硬件的数据结构,它起源于OpenFirmware (OF)。

它替代arch/arm/plat-xxx和arch/arm/mach-xxx中的板级spec代码,便于code管理。

本质上,Device Tree改变了原来用hardcode方式将HW配置信息嵌入到内核代码的方法,改用bootloader传递一些参数。

如果我们认为kernel是一个black box,那么其输入参数应该包括:

a.识别platform的信息           b. runtime的配置参数             c.设备的拓扑结构以及特性

对于嵌入式系统,在系统启动阶段bootloader会加载内核并将控制权转交给内核,此外,还需要把上述的三个参数信息传递给kernel,以便kernel可以有较大的灵活性。在linux kernel中,Device Tree的设计目标就是如此。

 2.1 dts加载过程
如果要使用Device Tree,首先用户要了解自己的硬件配置系统运行参数,并把这些信息组织成Device Tree source file。通过DTC(Device Tree Compiler),可以将这些适合人类阅读的Device Tree source file变成适合机器处理的Device Tree binary file(有一个更好听的名字,DTBdevice tree blob)。在系统启动的时候,boot program(例如:firmware、bootloader)可以将保存在flash中的DTB copy到内存(当然也可以通过其他方式,例如可以通过bootloader的交互式命令加载DTB,或者firmware可以探测到device的信息,组织成DTB保存在内存中),并把DTB的起始地址传递给client program(例如OS kernel,bootloader或者其他特殊功能的程序)。对于计算机系统(computer system),一般是firmware->bootloader->OS对于嵌入式系统,一般是bootloader->OS

2.2 dts描述信息
Device Tree由一系列被
命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的name和value。在Device Tree中,可描述的信息包括(原先这些信息大多被hard code到kernel中):

CPU的数量和类别

内存基地址和大小

总线和桥

外设连接

中断控制器和中断使用情况

GPIO控制器和GPIO使用情况

Clock控制器和Clock使用情况

 

一棵电路板上CPU、总线、设备组成的树

.dts文件是一种ASCII 文本格式的Device Tree描述,此文本格式非常人性化,适合人类的阅读习惯。基本上,在ARM Linux在,一个.dts文件对应一个ARM的machine,一般放置在内核的arch/arm/boot/dts/目录。由于一个SoC可能对应多个machine(一个SoC可以对应多个产品和电路板),势必这些.dts文件需包含许多共同的部分,Linux内核为了简化,把SoC公用的部分或者多个machine共同的部分一般提炼为.dtsi,类似于C语言的头文件。其他的machine对应的.dts就include这个.dtsi。

 

dtb文件会在内存中一直存在着,不会被内核或者应用程序占用,我们需要使用的时候可以直接使用dtb文件。dtb文件的内容会被解析生成多个device_node,然后这些device_node构成一棵树, 根节点为: of_root

设备树中的每一个节点,都会被转换为device_node结构体

 那么多的device_node,哪些会被转化为platform_device呢?

    根节点下的子节点,且该子节点必须包含compatible属性;
    如果一个节点的compatile属性含有这些特殊的值(“simple-bus”,“simple-mfd”,“isa”,“arm,amba-bus”)之一,那么它的子结点(需含compatile属性)也可以转换为platform_device。

 

内核提供了一些API来直接获取设备树中对应的属性。如:

  • of_property_read_u32_index:获取设备树中某个属性的值
  • of_property_read_string:获取设备树中某个属性的字符串的值
  • of_get_address:获取设备树中的某个节点的地址信息

 头文件:

                                                                                      a. 处理DTB
of_fdt.h             // dtb文件的相关操作函数, 我们一般用不到, 因为dtb文件在内核中已经被转换为device_node树(它更易于使用)

                                                                                      b. 处理device_node
of.h                   // 提供设备树的一般处理函数, 比如 of_property_read_u32(读取某个属性的u32值), of_get_child_count   (获取某个                         device_node的子节点数)
of_address.h     // 地址相关的函数, 比如 of_get_address(获得reg属性中的addr, size值)of_match_device(从matches数组中取出与                          当前设备最匹配的一项)
of_dma.h          // 设备树中DMA相关属性的函数
of_gpio.h           // GPIO相关的函数
of_graph.h         // GPU相关驱动中用到的函数, 从设备树中获得GPU信息
of_iommu.h       // 很少用到
of_irq.h              // 中断相关的函数
of_mdio.h          // MDIO (Ethernet PHY) API
of_net.h             // OF helpers for network devices.
of_pci.h              // PCI相关函数
of_pdt.h              // 很少用到
of_reserved_mem.h         // reserved_mem的相关函数

                                                                              c. 处理 platform_device
of_platform.h       // 把device_node转换为platform_device时用到的函数,
                            // 比如of_device_alloc(根据device_node分配设置platform_device),
                            // of_find_device_by_node (根据device_node查找到platform_device),
                            // of_platform_bus_probe (处理device_node及它的子节点)
of_device.h         // 设备相关的函数, 比如 of_match_device

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值