/***********************************************************************************
*
* mdev,bus,device,driver,platform
*
* 声明:
* 1. 本系列文档是在vim下编辑,请尽量是用vim来阅读,在其它编辑器下可能会
* 不对齐,从而影响阅读.
* 2. 由于本人水平有限,很难阐述清楚bus device driver platform的关系
* 所以强烈要求您详细参考本次提供的预热文章.
*
*
* 2015-3-21 晴 深圳 尚观 Opt 曾剑锋
**********************************************************************************/ \\\\\\\\\\\--*目录*--//////////
| 一. 预热文章:
| 二. mdev 原理及配置:
| 三. bus device driver接口:
| 四. platform bus接口
\\\\\\\\\\\\\\\//////////////// 一. 预热文章:
. linux设备驱动模型(上):
http://m.blog.csdn.net/blog/zhuzongwei1988/5785461
. [嵌入式Linux学习七步曲之第四篇 Linux内核移植]详解Linux2.6内核中
基于platform机制的驱动模型:
http://blog.csdn.net/sailor_8318/article/details/5267698
. [嵌入式Linux学习七步曲之第五篇 Linux内核移植]PowerPC+Linux2..25平台
下的I2C驱动架构分析:
http://blog.csdn.net/sailor_8318/article/details/5905988
. [嵌入式Linux学习七步曲之第五篇 Linux内核移植]PowerPC+Linux2..25平台
下的SPI驱动架构分析:
http://blog.csdn.net/sailor_8318/article/details/5977733 二. mdev 原理及配置:
. 在/etc/init.d/rcS中最后执行命令:
#采用设备模型进行创建设备节点的必须加上,热插拔处理
echo "/sbin/mdev" > /proc/sys/kernel/hotplug
mdev -s
. mdev扫描/sys/lock(块设备保存在/sys/block目录下,2.6.25版本以后,块设备也保存在
/sys/class/block目录下.mdev扫描/sys/block是为了实现向后兼容和/sys/class两个
目录下的dev属性文件,从该dev属性文件中获取设备编号(dev属性文件以"major:minor\n"
形式保存设备编号),并以包含该dev属性文件的目录名称作为设备名device_name(即包含
dev属性文件的目录为device_name,而/sys/class和/device_name之间的那部分目录称为
subsystem,也就是每个dev属性文件所在的路径都可表示/sys/class/subsystem/device_name/dev),
. 并在/dev目录下创建相应的设备文件.例如:
cat /sys/class/tty/tty0/dev会得到4:,subsystem为tty,device_name为tty0.
. 系统运行起来以后,每次创建新的节点的时候都会调用mdev,并根据/etc/mdev.conf文件
做相应的事,如果配置中没有对应的配置,那就按常规处理:
cat > /etc/mdev.conf << EOF
misc_dev : =test/my_device
event.* : =input/
mice : =input/
mouse0 : =input/
dsp : =sound/
sdb[-] : * /sbin/auto_mount
EOF
配置解析:
. 格式: <device regex> <uid>:<gid> <octal permissins> [<@|$|*> <command>]
. @在创建设备节点后运行命令;
. $在删除设备节点前运行命令;
. *创建设备节点后和创建设干杯节点前都会运行命令;
. =input: 表示将mice放在/dev/input目录下;
. =test/my_device: 表示将misc_dev改名字为my_device,并放在/dev/test目录下;
. 按照上面的操作,可以实现U盘的自动挂载. 三. bus device driver接口:
. 总线注册:
struct bus_type bus;
bus_register(&bus);
. 总线注销:
bus_unregister(&bus);
. 设备注册:
struct device dev;
device_register(&dev);
. 设备注销:
device_unregister(&dev);
. 驱动注册:
struct device_driver drv;
driver_register(&drv);
. 驱动注销:
driver_unregister(&drv);
. bus device接口实例Demo:
...
//总线通过match函数决定总线匹配规则,返回0代表匹配失败
int up_match(struct device *dev, struct device_driver *drv)
{
printk("try to match!\n"); /**
* 通过名字匹配设备和驱动,init_name中的值会赋给kobj.name
* 并且init_name中的值会变成NULL,所以如果要通过名字匹配
* 设备驱动,需要比较的是dev->kobj.name和drv->name的值.
* 如下方式是错误的:
* return !strcmp(dev->init_name, drv->name);
*/
return !strcmp(dev->kobj.name, drv->name);
} struct bus_type up_bus = {
.name = "niubi_bus",
.match = up_match,
};
EXPORT_SYMBOL(up_bus); void test_release(struct device *dev)
{
} struct device up_dev = {
.init_name = "bus_device",
.release = test_release,
};
EXPORT_SYMBOL(up_dev); int __init test_init(void)
{
int ret; ret = bus_register(&up_bus);
if(ret)
{
printk("bus_register FAILED!\n");
goto err0;
} ret = device_register(&up_dev);
if(ret)
{
printk("device_register FAILED!\n");
goto err1;
} return ret; err1:
bus_unregister(&up_bus);
err0:
return ret;
} void __exit test_exit(void)
{
bus_unregister(&up_bus);
}
... . device_driver接口实例Demo:
...
extern struct bus_type up_bus; //dev指向匹配的设备结构
static int up_probe(struct device *dev)
{
printk("Probe.\n"); return ;
} static int up_remove(struct device *dev)
{
printk("Remove.\n"); return ;
} struct device_driver drv = {
.owner = THIS_MODULE,
.name = "niubi_dev", //match的时候要用到
.bus = &up_bus,
.probe = up_probe,
.remove = up_remove,
}; int __init test_init(void)
{
int ret;
ret = driver_register(&drv);
if(ret)
printk("driver_register FAILED!\n"); return ret;
} void __exit test_exit(void)
{
driver_unregister(&drv);
}
... 四. platform bus接口
. 注册平台设备:
struct platform_device pdev;
platform_device_register(&dev);
. 注销平台设备:
platform_device_unregister(&dev);
. 注册平台驱动:
struct platform_driver pdrv;
platform_driver_register(&pdrv);
. 注销平台驱动:
platform_driver_unregister(&pdrv); . platform_device接口Demo: #include <linux/module.h>
#include <linux/platform_device.h> //定义自己的平台数据结构
struct my_platform_data {
int w;
int h;
char name[];
}; struct my_platform_data pdata = {
.w = ,
.h = ,
.name = "lcd_screen",
}; struct resource res[] = {
[] = {
.start = 0x10000000,
.end = 0x10000000 + SZ_128 - ,
.flags = IORESOURCE_MEM,
},
[] = {
.start = 0x20000000,
.end = 0x20000000 + SZ_128 - ,
.flags = IORESOURCE_MEM,
},
[] = {
.start = 0x30,
.end = 0x30,
.flags = IORESOURCE_IRQ,
},
}; void test_release(struct device *dev)
{
} //设备的resource保存在设备结构里
struct platform_device pdev = {
.name = "device_v3",
.id = -,
.dev = {
.release = test_release,
.platform_data = &pdata,
},
.num_resources = ARRAY_SIZE(res),
.resource = res,
}; int __init test_init(void)
{
int ret;
ret = platform_device_register(&pdev);
if(ret)
printk("platform_device_register FAILED!\n"); return ret;
} void __exit test_exit(void)
{
platform_device_unregister(&pdev);
} module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL"); . platform_device接口Demo: #include <linux/module.h>
#include <linux/platform_device.h> //定义自己的平台数据结构
struct my_platform_data {
int w;
int h;
char name[];
}; static int up_probe(struct platform_device *pdev)
{
int i;
struct my_platform_data *pdata = pdev->dev.platform_data; for(i = ; i < pdev->num_resources; i++)
{
printk("start = %x, end = %x\n",
pdev->resource[i].start,
pdev->resource[i].end);
}
printk("==========================\n");
printk("platform data.\n");
printk("width = %d, height = %d\n%s\n",
pdata->w, pdata->h, pdata->name); return ;
} static int up_remove(struct platform_device *pdev)
{
printk("In %s func.\n", __func__); return ;
} //最后一个元素清0
struct platform_device_id up_ids[] = {
{"device_v1", },
{"device_v2", },
{"device_v3", },
{"device_v4", },
{"device_v5", },
{},
}; //使用id_table和设备匹配
struct platform_driver pdrv = {
.probe = up_probe,
.remove = up_remove,
.driver = {
.name = "xxxxxxx",
.owner = THIS_MODULE,
},
.id_table = up_ids,
}; int __init test_init(void)
{
int ret;
ret = platform_driver_register(&pdrv);
if(ret)
printk("platform_driver_register FAILED!\n"); return ret;
} void __exit test_exit(void)
{
platform_driver_unregister(&pdrv);
} module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE("GPL");

Samsung_tiny4412(驱动笔记10)----mdev,bus,device,driver,platform的更多相关文章

  1. linux下bus,device,driver三者关系

    linux下bus,device,driver三者关系 1.bus: 总线作为主机和外设的连接通道,有些总线是比较规范的,形成了很多协议.如 PCI,USB,1394,IIC等.任何设备都可以选择合适 ...

  2. Samsung_tiny4412(驱动笔记01)----linux 3.5,U-Boot,Busybox,SD卡启动环境搭建

    /*********************************************************************************** * * linux 3.5,U ...

  3. Samsung_tiny4412(驱动笔记04)----volatile,container_of,file_operations,file,inode

    /*********************************************************************************** * * volatile,co ...

  4. Samsung_tiny4412(驱动笔记03)----字符设备驱动基本操作及调用流程

    /*********************************************************************************** * * 字符设备驱动基本操作及 ...

  5. Samsung_tiny4412(驱动笔记09)----alloc_pages,kmalloc,vmalloc,kmem_cache,class

    /*********************************************************************************** * * alloc_pages ...

  6. Samsung_tiny4412(驱动笔记07)----spinlock,semaphore,atomic,mutex,completion,interrupt

    /*********************************************************************************** * * spinlock,se ...

  7. Samsung_tiny4412(驱动笔记06)----list_head,proc file system,GPIO,ioremap

    /**************************************************************************** * * list_head,proc fil ...

  8. Samsung_tiny4412(驱动笔记05)----Makefile,open,read,write,lseek,poll,ioctl,fasync

    /*********************************************************************************** * * Makefile,op ...

  9. 【驱动笔记10】再谈IRP

    文章作者:grayfox作者主页:http://nokyo.blogbus.com原始出处:http://www.blogbus.com/nokyo-logs/34010655.html 这一节会对I ...

随机推荐

  1. pyCharm最新2017激活码

    pyCharm最近激活码过期,找到一个最新的activation code,可用期为2017一年.如下: BIG3CLIK6F-eyJsaWNlbnNlSWQiOiJCSUczQ0xJSzZGIiwi ...

  2. VC动态调用DLL

    1. //函数指针声明 typedef int (_stdcall MYDLLFUN)(char* _pcOut, /*INOUT*/int *_piOutBufLen, char* _pcIn, i ...

  3. Angular2,Springboot,Zuul,Shiro跨域CORS请求踩坑实录

    前言:前后端分离,业务分离,网关路由等已经成为当下web application开发的流行趋势.前端以单页面路由为核心的框架为主体,可以单独部署在nodejs或nginx上.后端以springboot ...

  4. Codeforces 260B - Ancient Prophesy

    260B - Ancient Prophesy 思路:字符串处理,把符合条件的答案放进map里,用string类中的substr()函数会简单一些,map中的值可以边加边记录答案,可以省略迭代器访问部 ...

  5. Bootstrap 栅格系统(布局)

    基本用法  网格系统用来布局,其实就是列的组合.Bootstrap框架的网格系统中有四种基本的用法.由于Bootstrap框架在不同屏幕尺寸使用了不同的网格样式,在这一节中所涉及到的示例,我们都以中屏 ...

  6. [Android教程] Cordova开发App入门(一)创建android项目

    前言 Apache Cordova是一个开源的移动开发框架.允许使用标准的web技术-HTML5,CSS3和JavaScript做跨平台开发. 应用在每个平台的具体执行被封装了起来,并依靠符合标准的A ...

  7. LeetCode--125--验证回文串

    问题描述: 好 times out: class Solution(object): def isPalindrome(self, s): """ :type s: st ...

  8. LeetCode--067--二进制求和

    问题描述: 给定两个二进制字符串,返回他们的和(用二进制表示). 输入为非空字符串且只包含数字 1 和 0. 示例 1: 输入: a = "11", b = "1&quo ...

  9. javascript实现select菜单/级联菜单(用Rails.ajax实现发送请求,接收响应)

    在购物网站,填写收货地址的时候,会出现XX省XX市XX区的下拉菜单,如何实现此功能?思路是什么? 功能设置: 当选择省select菜单后,市的select菜单为这个省的城市列. 当选择市菜单后,区菜单 ...

  10. Prefix Product Sequence CodeForces - 487C (数论,构造)

    大意: 构造一个[1,2,...n]的排列, 使得前缀积模n为[0,1,...,n-1]的排列 这种构造都好巧妙啊, 大概翻一下官方题解好了 对于所有>=6的合数$n$, 有$(n-1)! \e ...