/***********************************************************************************
*
* 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. html 画出矩形,鼠标弹起,矩形消失

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  2. Windows10中注册 regsvr32 xxx.ocx报错but the call to DIIRegisterServer failed with error code 0x80040200

    网站中有读取居民身份证的机器,需要安装一些注册activeX控件然后进入指定目录下执行以下命令regsvr32 xxx.ocx报了个错: but the call to DIIRegisterServ ...

  3. Python day20正则表达式和re方法

    元字符6个函数以及几个元字符1.'.'通配符2.'^'以什么开头3.'$'以什么结尾4.'*'紧挨着的字符0~∞次5.'+'紧挨着的字符1~∞次6.'?'紧挨的字符0次或1次7.'{}' {0,}== ...

  4. python将xml转换成json数据

    # -*- coding: utf-8 -*- import requests import xmltodict import json def get_response(request_url): ...

  5. Qt5_各种路径

    1.Qt5.3.2 -- vs2010 -- OpenGL 1.1.发布时需要的 DLL文件的路径 F:\ZC_software_installDir\Qt5.3.2_vs2010\5.3\msvc2 ...

  6. 使用排序数组/链表/preorder构建二叉搜索树

    2018-08-13 11:29:05 一.Convert Sorted Array to Binary Search Tree 问题描述: 问题求解: public TreeNode sortedA ...

  7. 1月10日 ruby基础教程,查漏补缺; 2月22日 Exception补充

    https://ruby-doc.org/core-2.5.0/Exception.html 1月20日练习完1,2章. 第一章 初探 ‘’单引号不执行转义符. \t 制表符.\n 换行符. p me ...

  8. 百度安卓SDK秘钥Key错误

    下载官方安卓地图demo,输入报名和sha1申请AK,发现key错误 构建的时候要指定生成的key 安卓定位BaiduLocDemo出现aapt.exe finished with non-zero ...

  9. Serega and Fun CodeForces - 455D (分块 或 splay)

    大意:给定n元素序列, 2种操作 将区间$[l,r]$循环右移1位 询问$[l,r]$中有多少个等于k的元素 现在给定q个操作, 输出操作2的询问结果, 强制在线 思路1: 分块 每个块内维护一个链表 ...

  10. 规格化设计-----JSF(第三次博客作业)

    从20世纪60年代开始,就存在着许多不同的形式规格说明语言和软件开发方法.在形式规格说明领域一些最主要的发展过程列举如下: 1969-1972 C.A.R Hoare撰写了"计算机编程的公理 ...