IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux 平台总线platform与设备树 -> 正文阅读

[系统运维]Linux 平台总线platform与设备树

系列文章目录

第一章 Linux 中内核与驱动程序
第二章 Linux 设备驱动编写 (misc)
第三章 Linux 设备驱动编写及设备节点自动生成 (cdev)
第四章 Linux 平台总线platform与设备树
第五章 Linux 设备树中pinctrl与gpio(lichee nano pi)



前言

如果你在学习Linux 设备驱动编程过程中,如果你一上来直接就去看设备树,或者去看别人写的一些驱动代码,你可能会迷惑:什么是prob函数?device.c和driver.c的区别和联系?为什么要用设备树?


一、平台总线

1.1 平台总线简介

1.平台总线定义
平台总线模型也叫platform总线模型。是 Linux内核虚拟出来的一条总线,不是真实的导线。
平台总线模型就是把原来的驱动C文件给分成了俩个C文件,一个是device.c,一个是driver.c
把稳定不变的放在driver.c里面,需要变得就放在了device.c里面。
2.为什么会有平台总线模型?
(1)可以提高代码的重用性(2)减少重复性代码。
设备 总线 I驱动
device.c driver.c
3.怎么编写以平台总线模型设计的驱动?
一个是device.c,一个是driver.c,然后分别注册device.c和driver.c。平台总线是以名字来匹配的,实际上就是字符串比较。

1.2 以平台总线模型设计的驱动

1.2.1 注册device

device.c里面写的是硬件资源,这里的硬件资源是指寄存器的地址,中断号,时钟等硬件资源。
在Linux 内核里面,我们是用一个结构体来描述硬件资源的。

struct platform_device {
	const char *name;	  //平台总线进行匹配的时候用到的name,/sys/bus..
	int id;				  //设备id,一般写-1
	struct device dev;	  //内嵌的device结构体
	{
	u32 num_resources;    //资源的个数
	struct resource *resource;	//device里面的硬件资源。
	};
};

现在给出一个例子,当中的描述的是蜂鸣器的资源,根据每个开发板的具体情况进行更改。

#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>
struct resource beep_res = {
    [0]={
        .start  = 0x2OACO00,
        .end    = 0x2OAC083,
        .flags  = IORESOURCE_MEM,
        .name   = "GPIO5_DR",
    };

};
struct platform_device beep_device = {;
    .name   = "beep_test",
    .id     = -1,
    .resource       =beep_res,
    .num_resources  =ARRAY_SIZE(beep_res),
}
static int device_init(void)
{
     printk(KERN_ALERT "device_init");
     return platform_device_register (&beep_device);
}

static void device_exit(void)
{
    printk(KERN_ALERT "device_exit");
    return platform_device_unregister (&beep_device);
}
module_init( device_init );
module_exit( device_exit );
MODULE_LICENSE("Dual BSD/GPL");

1.2.2 注册driver

现在来编写driver.c

struct platform_driver {
	int (*probe)(struct platform_device *);//当driver和device 匹配成功的时候,就会执行probe函数
	int (*remove)(struct platform_device *);//当driver和device任意一个remove的时候,就会执行这个函数
	
	void (*shutdown)(struct platform_device *);//当设备收到shutdown命令的时候,就会执行这个函数
	int (*suspend)(struct platform_device *. pm_message_t state);//当设备收到suspend命令的时候,就会执行这个函数
	int (*resume)(struct platform_device *);//当设备收到resume命令的时候,就会执行这个函数
	struct device_driver driver;	
	conststruct  patrorm_device_id *id_table;
	bool prevent_deferred_probe;
};
struct device_driver {
	const char *name;//这个是我们匹配设备时候用到的名字
	struct module *owner;
};



代码如下

#include <linux/module.h>
#include <linux/init.h>
#include <linux/platform_device.h>

int beep_probe(struct platform_device *pdev)
{
     printk( "beep_probe\n");
     return 0;
}
int beep_remove(struct platform_device *pdev)
{
     printk( "beep_remove\n");
     return 0;
}
struct platform_driver beep_driver{

    .probe = beep_probe,
    .remove = beep_remove,
    .driver = {
        .owner = THIS_MODULE,
        .name = "beep_test"
        }
    //const struct platform_device_id *id_table;

};
static int driver_init(void)
{

    int ret = 0;
    ret = platform_driver_register(&beep_driver);
    if(ret < 0){
            printk( "platform_driver_register error \n");
            return ret;
    }

    printk(KERN_ALERT "driver_init");
    return 0;
}
}
static void device_exit(void)
{
    platform_driver_unregister(&beep_driver);

    printk(KERN_ALERT "driver_exit");

}
module_init( driver_init );
module_exit( driver_exit );
MODULE_LICENSE("Dual BSD/GPL");

device.c和driver.c是通过name来匹配的,当两者都insmod之后,如果两者匹配的话,会进入driver.c当中的prob函数。重点变成都在prob函数中。我们可以通过of系列函数获得device中的硬件资源,具体的prob函数编写现在不在详细讲解
以上就将硬件信息和相同的驱动代码分割开了。
平台总线platfrom解决了问题,当我们在另一个开发板上要运行相同的驱动,只需要改改引脚就可以了。
但是又有个问题出现了,一个开发板上肯定不止有一个硬件、一个驱动。一个驱动写一个device.c去描写其硬件资源,那么好多就显得很冗余,因为device.c和driver.c不同,它的结构很固定。那么有没有一种方法将开发板的你需要的硬件资源都汇总到一个文件?
设备树就出现了。

二、设备树

1.基本语法

1节点
什么是节点呢?节点就好比一颗大树,从树的主干开始,然后有一节一节的树枝,这个就叫节点。在代码中的节点是什么样子的呢。我们把上面模板中的根节点摘出来,如下图所示,这个就是根节点。相当于大树的树干。

/{
};//分号

而树枝就相当于设备树的子节点,同样我们把子节点摘出来就是根节点里面的node1和node2,如下图所示:

/{ //根节点
	node1//子节点node1
	{
	}
	node2//子节点node2
	{
	};
};//分号

一个树枝是不是也可以继续分成好几个树枝呢,也就是说子节点里面可以包含子子节点。所以child-node1和child-node2是node1和node1的子节点,如下图所示:

{//根节点
	node1//子节点node1
	{
		child-node1//子子节点
		{
		};
	};
};
	node2//子节点node2
	{
	};

看设备树文件要从上往下看,从左往右看

2节点名称
节点的命名有一个固定的格式。

格式:<名称>[@<设备地址>]

<名称>节点的名称也不是任意起的,一般要体现设备的类型而不是特点的型号,比如网口,应该命名为ethernet,而不是随意起一个,比如111。
<设备地址>就是用来访问该设备的基地址。但并不是说在操作过程中来描述一个地址,他主要用来区分用。
注意事项:
<1>同一级的节点只要地址不一样,名字是可以不唯一的。
<2>设备地址是一个可选选项,可以不写。但为了容易区分和理解,一般是都写的。
3节点别名
当我们找一个节点的时候,我们必须书写完整的节点路径,如果我们的节点名很长,那么我们在引用的时候就十分不方便,所以,设备树允许我们用下面的形式为节点标注引用(起别名)。

pio: pinctrl@1c20800

4节点引用
要对子节点进行更改时我们一般不在根节点里面进行更改,而是在外面。通过引用的方式对其进行更改。

/ {
	pio:pinctrl@1c20800{
	};
};

&pio{
	//通过&引用,在这里进行更改
};

5
一些属性的讲解在此不做赘述。链接: link

2.实例讲解

例1
Q:有的父节点有compatible属性,字节点也有自己的compatible,那么该匹配那个呢?A:用你那个节点就在驱动中与之匹配。
Q:这样看来父子节点之间好像没什么关系,A:我的理解是:父节点中定义#address-cells 与#size-cells这样就可以完成一类的字节点的编写,有共性。
在这里插入图片描述

例2设备树中不仅要看该设备树中的根节点,还要从头文件中找到根节点,这两个文件中的根节点运行的时候会合并起来。就像下面的例子中,
在这里插入图片描述

例3

//根节点
/ {
	#address-cells = <1>; //带有#一般都是描述子节点的属性,
	#size-cells = <1>;	  //这个与上一行的经常一块使用,描述字节点的地址大小相关
	interrupt-parent = <&intc>;

	//子节点
	clocks {
		#address-cells = <1>;
		#size-cells = <1>;
		ranges;
		
		//子节点下的chirld节点
		osc24M: clk-24M {
			#clock-cells = <0>;
			compatible = "fixed-clock";		//compatible ,与driver中的name匹配,会进入driver.c的prob函数
			clock-frequency = <24000000>;
			clock-output-names = "osc24M";
		};
	...
}
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-07-17 17:01:55  更:2022-07-17 17:05:01 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/18 18:55:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码