首页天道酬勤二总线,平台

二总线,平台

张世龙 05-12 21:47 39次浏览

一.前述驱动编程的几种模型。 我们已经可以自己写简单的驱动装置了。

但是,从一开始我就觉得这个写法又一团糟。 而且,每次写设备都写这么多。 我们又有这么多设备。 那必须占用很多空间。

然后我引入了平台总线的概念。

平台总线与其他总线(如IIC )的区别:平台总线用于平台升级

本质上是相同的,但根据设备操作的总线类型来区分不同的总线。 台总线一般用于无法区分总线类型的设备、IIC、SPI总线。 相应的操作设备是IIC或SPI,是标准总线,因此保持标准化,易于使用。

——————————————————————————————————————————————

(那么平台巴士是虚拟巴士吗? 虚拟总线和物理总线、数据总线、CAN总线。 这么多巴士关系是什么? )

——————————————————————————————————————————————————

那么,我们引入了平台总线的概念。

请看平台总线的概念和作用。

这是设备驱动的步骤图,可以看到写很多驱动步骤是一样的。 而且只有硬件设备的信息不同。 所以我们在写代码的时候进行了驱动分离。 利用平台总线在驱动时进行驱动整合。

1、device:设备属性模块是设备的信息,包括设备的硬件、物理地址、名称、大小等,与类中的数据相同。

2、Driver:驱动模块是一个存储数据的吃法,拿到数据后很多设备的使用方法都很相似,所以这一部分可以复用。 此模块使用类中的数据,就像使用类中的成员函数一样。

3、公交:公交模块。 匹配相应的设备模块和驱动器模块。

这意味着将一个设备驱动程序分为三个模块。 但是,驱动器模块可以复用。

——————————————————————————————————————

二、那么平台总线式如何匹配设备模块和驱动模块呢?

在我们的总线结构中,建立了两个结构链表:设备链表、驱动链表。 使用设备模块和驱动程序模块的注册函数,在各自的链表中注册设备和驱动程序。 然后,平台总线根据设备和驱动程序的名称进行匹配。 因此,设备名称和驱动程序名称相同。

——33543——3——3————33——333——33——3——33343——333——333——33333——33——33——3——33——33——333——33——343333——333————333333333

一.总线模块

1 )基本驱动框架构建。

2 )公交注册

注册和注销

int bus _ register (struct bus _ type * bus ) )

void bus _ unregister (struct bus _ type * bus ) )

3 )定义总线结构)这个结构本来就存在,我们可以定义和使用);

truct bus_type {

常数字符名称;

int (*匹配) ) struct device *dev,struct device_driver *drv ); //设备与驱动匹配。

}

代码: —————— bus.c ——3354——3354————————3——33——3333——333——333——333——333——

# include Linux/init.h # include Linux/module.h # include Linux/device.hintmybus _ match (结构设备* dev,strurude ) 返回1; } else { printk (匹配故障(n ); 返回0; }返回0; //bus对象struct bus _ typemybus={.name=' mybus ', match=mybus_match,}; export_symbol(mybus; 静态int _ initmybus _ init (void ) (printk ) (------ % s------------,) _ funct ting ing //构建总线//sys/bus/mybusret=bus _ register (mybus ); if(ret!=0) printk(bus_registererror(n ); 返回ret; }返回0; } static void _ _ exitmybus _ exit (void ) printk (------------ % s------------ fung ), }module_init(mybus_init ); module_exit(mybus_exit; 模块_许可证(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,};voidmydev_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_typestruct platform_devicestruct platform_driverplatform_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升级的时候, 对于相似的设备驱动,需要编写很多次(如果不用平台总线)
但是会有大部分重复代码
解决:引入平台总线
————————————————————————
好的,那么我们的驱动代码放哪里?申请设备号?申请设备节点?地址映射?文件操作接口,这些驱动代码呢?
没有写出来?做驱动肯定要这些啊?那这是按照以前一样写这里的驱动模块的装载函数里面?????

can总线帧结构,CAN帧一直重发 jk触发器二位二进制,二位二进制计数器