ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

平台总线(一)

2021-09-20 21:02:36  阅读:142  来源: 互联网

标签:__ mybus struct bus 平台 总线 device


一、前面说到驱动编程的几种模型。我们已经可以自己手动的写一个简单的驱动设备了。
但是,从一开始我就觉得这种写法写的又很乱,然后每写一个设备就要写这么多东西,我们又这么多的设备那不是得占很多的空间。
然后我引入了平台总线的概念。
平台总线和IIC等其它总线的区别:
本质上是一样的,只是根据设备操作的总线类型不一样区分了不同的总线,台总线一般用于无法区分总线类型的那类设备,IIC,SPI总线,因为对应的操作的设备是IIC或SPI的,属于标准总线,所以直接标准化了,方便使用。
——————————————————————————————————————————————
(那么,平台总线是虚拟总线吗?虚拟总线和物理总线,数据总线,CAN总线。。。妈的这么多的总线关系是什么?)
——————————————————————————————————————————————————
那么我们就引入了平台总线的概念。

看一平台总线的概念和作用是什么?
在这里插入图片描述
这是一张设备驱动的步骤图,我们可以就看出来,如果写很多的驱动步骤都是差不多的。而且只有硬件设备的信息不一样。所以我们写代码的时候做了驱动分离。利用平台总线在驱动的时候做驱动合并。
在这里插入图片描述
1、device:设备属性模块,就是设备的信息,包括设备的硬件,物理地址,名称,大小等等,就跟类里面的数据一样。
2、Driver:驱动方法模块,就是存放数据的食用方法,拿到数据之后很多设备的使用方法都差不多所以,这一部分可以复用,这个模块就跟类里面的成员函数一样,使用类里面的数据。
3、BUS:总线模块。把对应的设备模块和驱动模块进行匹配。
这样我们就相当于把一个设备驱动模块分成了三个模块。但是驱动模块可以复用。
——————————————————————————————————————
二、那么,平台总线式怎么把设备模块和驱动模块进行匹配的呢?
在这里插入图片描述
我们的总线结构体里面创建了两个结构体链表,分别为:设备链表、驱动链表。我们通过设备模块和驱动模块的注册函数,将设备和驱动分别注册到里面的链表里面去。然后平台总线就会根据设备和驱动的名字将他们进行匹配(所以设备名字和驱动名字得一样)。
————————————————————实现——————————————————————————
一、BUS总线模块
1)基本的驱动框架搭建。
2)注册总线
注册和注销
int bus_register(struct bus_type *bus)
void bus_unregister(struct bus_type *bus)
3)定义总线结构体(这个结构体本来就存在,我们定义使用就可以了);
truct bus_type {
const char *name;
int (*match)(struct device *dev, struct device_driver *drv); //让设备,和驱动进行匹配。
}
代码:——————BUS.C——————————————

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
int mybus_match(struct device *dev, struct device_driver *drv)
{
	//如果匹配成功,match方法一定要返回一个1, 失败返回0
	if(!strncmp(drv->name, dev->kobj.name, strlen(drv->name)))
	{
		printk("match ok\n");
		return 1;
	}else{
		printk("match failed\n");
		return 0;

	}

	return 0;
}

//实例化一个bus对象
struct bus_type mybus = {
	.name = "mybus",
	.match = mybus_match,
};

EXPORT_SYMBOL(mybus);


static int __init mybus_init(void)
{
	printk("----------%s-------------\n", __FUNCTION__);
	int ret;

	//构建一个总线
	// /sys/bus/mybus
	ret = bus_register(&mybus);
	if(ret != 0)
	{
		printk("bus_register error\n");
		return ret;
	}

	
	return 0;
}

static void __exit mybus_exit(void)
{
	printk("----------%s-------------\n", __FUNCTION__);
	bus_unregister(&mybus);
	
}

module_init(mybus_init);
module_exit(mybus_exit);
MODULE_LICENSE("GPL");

————————————————————————————————————————
二、设备模块
这个模块我们主要做的事就是定义我们的设备信息。
1)搭建基本驱动框架
2)注册和注销设备
int device_register(struct device *dev)
void device_unregister(struct device *dev)
3)定义设备信息对象
device对象:设备对象,描述设备信息,包括地址,中断号,甚至其他自定义的数据
struct device {
struct kobject kobj;  //所有对象的父类
const char *init_name;
// 在总线中会有一个名字,用于做匹配,在/sys/bus/mybus/devices/名字
struct bus_type *bus; //指向该device对象依附于总线的对象
void *platform_data; // 自定义的数据,指向任何类型数据

platform_data:用户可以自定义的一些数据,你要加什么数据就加到这里面。
代码:

#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include "dev_info.h"


extern struct bus_type mybus;           //注意引用bus模块的要声明

struct mydev_desc devinfo = {
	.name = "testdev",
	.irqno = 9999,
	.addr = 0x30008000,
};

void	mydev_release(struct device *dev)
{

	printk("----------%s-------------\n", __FUNCTION__);
}

//构建一个device对象
struct device  mydev= {
	.init_name = "fsdev_drv",
	.bus = &mybus,
	.release = mydev_release,
	.platform_data = &devinfo,     			//我们定义的其他数据 
};

static int __init mydev_init(void)
{
	printk("----------%s-------------\n", __FUNCTION__);
	//将device注册到总线中
	int ret;
	ret  = device_register(&mydev);
	if(ret < 0)
	{
		printk("device_register error\n");
		return ret;
	}
	

	return 0;
}

static void __exit mydev_exit(void)
{

	printk("----------%s-------------\n", __FUNCTION__);
	device_unregister(&mydev);

}

module_init(mydev_init);
module_exit(mydev_exit);
MODULE_LICENSE("GPL");

——————————————————————————————————————
驱动模块:
这个模块要做的事情就是拿到设备的信息,并完成,你想要做什么的实现函数.
1)搭建框架
2)注册和注销设备驱动
int driver_register(struct device_driver *drv)
void driver_unregister(struct device_driver *drv)
3)定义驱动结构体
struct device_driver mydrv = {
.name = “fsdev_drv”, //这个名字要和设备模块的保持一致
.bus = &mybus,
.probe = mydrv_probe, //probe函数,当我匹配完成会制动调用这个函数,就可以实现我们想实现的一些功能
.remove = mydrv_remove, //移除函数,当不匹配的时候就会执行这个函数里面的东西。
};
在,probe这个函数里面他的参数就是设备信息结构体,所以它可以使用设备信息里面的所有数据。
代码:


```c
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/io.h>
#include "dev_info.h"


struct mydev_desc  *pdesc;

int mydrv_probe(struct device *dev)
{
	printk("----------%s-------------\n", __FUNCTION__);

	pdesc = (struct mydev_desc  *)dev->platform_data;

	printk("name = %s\n", pdesc->name);
	printk("irqno = %d\n", pdesc->irqno);

	unsigned long *paddr = ioremap(pdesc->addr, 8);

	platform_bus_type

	struct platform_device
	struct platform_driver

	platform_device_unregister(struct platform_device * pdev);
	

	platform_driver_register(struct platform_driver *drv);
	platform_driver_unregister(struct platform_driver *drv);
	
	return 0;
}

int mydrv_remove(struct device *dev)
{

	printk("----------%s-------------\n", __FUNCTION__);
	return 0;
}

extern struct bus_type mybus;

struct device_driver mydrv = {
	.name = "fsdev_drv",
	.bus = &mybus,
	.probe = mydrv_probe,
	.remove = mydrv_remove,
};


static int __init mydrv_init(void)
{
	printk("----------%s-------------\n", __FUNCTION__);
	//将driver注册到总线中
	int ret;
	ret  = driver_register(&mydrv);
	if(ret < 0)
	{
		printk("device_register error\n");
		return ret;
	}
	

	return 0;
}

static void __exit mydrv_exit(void)
{

	printk("----------%s-------------\n", __FUNCTION__);
	driver_unregister(&mydrv);
}

module_init(mydrv_init);
module_exit(mydrv_exit);
MODULE_LICENSE("GPL");
————————————————————————
这样就实现了,平台总线的驱动模型。
这样做的好处有、
为什么会有平台总线:
		用于平台升级:三星: 2410, 2440, 6410, s5pc100  s5pv210  4412
			硬件平台升级的时候,部分的模块的控制方式,基本上是类似的
			但是模块的地址是不一样
			gpio控制逻辑: 1, 配置gpio的输入输出功能: gpxxconf
						   2, 给gpio的数据寄存器设置高低电平: gpxxdata
						逻辑操作基本上是一样的
						但是地址不一样
			uart控制:1,设置8n1,115200, no AFC
						UCON,ULCON, UMODOEN, UDIV				
					逻辑基本上是一样的
					但是地址不一样
	问题:
		当soc升级的时候, 对于相似的设备驱动,需要编写很多次(如果不用平台总线)
		但是会有大部分重复代码
	解决:引入平台总线	
————————————————————————
好的,那么我们的驱动代码放哪里?申请设备号?申请设备节点?地址映射?文件操作接口,这些驱动代码呢?
没有写出来?做驱动肯定要这些啊?那这是按照以前一样写这里的驱动模块的装载函数里面?????

标签:__,mybus,struct,bus,平台,总线,device
来源: https://blog.csdn.net/wzf_Cql/article/details/120394716

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有