platform模型驱动和字符设备模型驱动

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

platform模型驱动和字符设备模型驱动
字符设备驱动模型:
1、申请设备号:动态申请(alloc_chrdev_region()),动态申请(register_chrdev_region())
struct cdev btn_cdev;
//申请设备号
if(major)
{
//静态申请设备号
dev_id = MKDEV(major, 0);
register_chrdev_region(dev_id, 1, "button");
}
else
{
//动态申请设备号
alloc_chardev_region(&dev_id, 0, 1, "button");
major = MAJOR(dev_id);
}
在Linux中以主设备号用来标识与设备文件相连的驱动程序。

次编号被驱动程序用来辨别操作的是哪个设备。

cdev 结构体的 dev_t 成员定义了设备号,为 32 位,其中高 12 位为主设备号,低20 位为次设备号。

设备号的获得与生成:
获得:主设备号:MAJOR(dev_t dev);
次设备号:MINOR(dev_t dev);
生成:MKDEV(int major,int minor);
2、初始化设备:
void cdev_init(struct cdev *, struct file_operations *);
cdev_init()函数用于初始化cdev 的成员,并建立cdev 和file_operations 之间的连接。

3、注册设备
int cdev_add(struct cdev *, dev_t, unsigned);
cdev_add()函数向系统添加一个 cdev,完成字符设备的注册。

4、创建设备节点
手动创建设备节点:
mknod 的标准形式为:mknod DEVNAME {b | c} MAJOR MINOR
1,DEVNAME是要创建的设备文件名,如果想将设备文件放在一个特定的文件夹下,就需要先用mkdir在dev目录下新建一个目录;
2, b和c 分别表示块设备和字符设备:
b表示系统从块设备中读取数据的时候,直接从内存的buffer中读取数据,而不经过磁盘;
c表示字符设备文件与设备传送数据的时候是以字符的形式传送,一次传送一个字符,比如打印机、终端都是以字符的形式传送数据;
3,MAJOR和MINOR分别表示主设备号和次设备号:
为了管理设备,系统为每个设备分配一个编号,一个设备号由主设备号和次设备号组成。

主设备号标示某一种类的设备,次设备号用来区分同一类型的设备。

linux操作系统中为设备文件编号分配了32位无符号整数,其中前12位是主设备号,后20位为次设备号,所以在向系统申请设备文件时主设备号不好超过4095,次设备号不好超过2^20 -1。

mknod /dev/cobing/mydev1 c 128 512
自动创建设备节点:
//注册一个类,使mdev可以在/dev/下面建立设备节点
leds_class = class_create(THIS_MODULE, DEVICE_NAME);
//创建一个设备节点,节点名字为DEVICE_NAME
device_create(leds_class, NULL, MKDEV(led_major, 0), NULL, DEVICE_NAME);
平台模型驱动
实现的总线平台驱动模型的最简单源码 :
平台设备的实现: device.c
#include
#include
#include
#include
#include
#include
/* 平台模型驱动
的平台设备对象 */
static struct platform_device *my_device;
/* 初始化函数*/
static int __init my_device_init(void)
{
int ret = 0;
/* 采用 platform_device_alloc分配一个 platform_device 对象参数分别为 platform_device 的name, 和 id。

*/
my_device = platform_device_alloc("my_dev",-1);
/* 注册设备, 注意不是platform_device_register ,将平台设备注册到内核中 */
ret = platform_device_add(my_device);
/* 如果出错释放相关的内存单元 */
if(ret)
{
platform_device_put(my_device);
}
return ret;
}
/* 卸载处理函数 */
static void __exit my_device_exit(void)
{
platform_device_unregister(my_device);
}
module_init(my_device_init);
module_exit(my_device_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("GP-");
平台驱动的实现: driver.c
#include
#include
#include
#include
#include
/* 平台驱动中的 probe和 remove 函数是必须实现的函数 */
/* 设备驱动的探测函数,主要实现检测总线上是否有该驱动对应的设备 */
static my_probe(struct device *dev)
{
/*
如果添加实际的设备到该平台总线设备驱动模型中,则可以在该函数
中实现具体的设备驱动函数的初始化操作,包括设备号的申请,设备
的初始化,添加。

自动设备文件创建函数的添加等操作。

或者是混杂字符设备的相关初始化操作。

当然结构体的相关处理仍
然采取全局变量的形式。

*/
printk("Driver found devices which this driver can be handle\n");
return 0;
}
/* 设备驱动的移除函数,主要检测该驱动支持设备的移除活动检
测 */
static my_remove(struct device *dev)
{
/*
如果添加实际的设备到该平台总线设备驱动模型中,则可以在该函数
中实现具体的设备的释放,包括设备的删除,设备号的注销等操作。

*/
printk("Driver found device unpluded\n");
return 0;
}
static struct platform_driver my_driver =
{
/* 平台驱动的 probe 函数实现*/
.probe = my_probe,
/* 平台驱动的 remove 函数实现*/
.remove = my_remove,
/* 实现设备驱动的 name 和owner 变量 */
.driver =
{
/* 该参数主要实现总线中的匹配函数调用 */
.name = "my_dev",
/* 该函数表示模块的拥有者 */
.owner = THIS_MODULE,
},
};
/* 初始化函数*/
static int __init my_driver_init(void)
{
/* 注册平台驱动 */
return platform_driver_register(&my_driver);
}
/* 退出函数*/
static void __exit my_driver_exit(void)
{
/* 注销平台驱动 */
return platform_driver_unregister(&my_driver);
}
/* 加载和卸载*/
module_init(my_driver_init);
module_exit(my_driver_ex
it);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("GP-");
将一般设备驱动加入到总线设备模型中的相关操作是后期总结和学习的内容。

设备驱动实现的实现原理还是之前的那些操作,但是初始化和推出函数发生了改变。

总结: platform 总线的驱动模型只是在一般总线模型的基础上做了相关的延伸,实质上只要弄清除总线模型的一般原理,学习platform 总线也就简单不少。

相关文档
最新文档