当前位置: 首页 > 嵌入式Linux > 正文

我的内核学习笔记2:platform设备模型

说实话,我做这个例子之前,我对linux的platform设备、platform驱动了解不多,只知道有这些东西,但没概念。上网搜索了一些资料,并下了点功夫跟踪了内核源代码,虽然不能说吃透了原理,但也不至于像以前那样一无所知。这篇文章主要是说一下一个简单的驱动例子。
为了明确层次,不把所有代码都放到一个文件中,这个例子中,分别有设备文件simplechar_dev.c,驱动文件simplechar_drv.c以及共用的头文件simplechar.h。为了避免例子十分的简单,额外添加了些结构体,也在代码 中对这些结构体做了测试。总之,可以认为这是一个platform的模板吧。
simplechar.h文件是自定义的结构体:

#ifndef SIMPLECHAR_H #define SIMPLECHAR_H struct simplechar_platdata { char *name; }; #endif

simplechar_dev.c文件的代码仅仅与“设备”有关,即定义这个设备有哪些特性(名称、私有数据,等):

/** * @file simplechar_dev.c * @author Late Lee <latelee@163.com> * @date Tue Nov 12 21:07:03 2013 * * @brief * * */ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> #include "simplechar.h" // device static struct simplechar_platdata foo_pdata = { .name = "gotohell", }; // 避免删掉模块时出现警告 static void simplechar_dev_release(struct device* dev) { printk(KERN_NOTICE "do %s case of: Device xxx does not have a release() function, it is broken and must be fixed.\n", __func__); return; } // 另一文件要使用到,此处不能为static // 在/sys/devices/platform/生成目录:simplechar struct platform_device simplechar_device = { .name = "simplechar", .id = -1, // 注:如何为1,则生成目录:simplechar.1 .dev = { .platform_data = &foo_pdata, .release = &simplechar_dev_release, }, }; simplechar_drv.c文件主要实现了“驱动”,驱动的主要代码集中于此: /** * @file simplechar_drv.c * @author Late Lee <latelee@163.com> * @date Tue Nov 12 21:07:15 2013 * * @brief platform模型示例 * * @note 仅用于insmod和rmmod的测试,不具备字符设备特征 */ /** */ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> #include "simplechar.h" // device extern struct platform_device simplechar_device; // our own data struct simplechar { int id; struct simplechar_platdata *pdata; char buffer[16]; }; static inline struct simplechar *pdev_to_owndata(struct platform_device *dev) { return platform_get_drvdata(dev); } static int simplechar_remove(struct platform_device *dev) { struct simplechar *foo = pdev_to_owndata(dev); // 释放自定义数据空间 kfree(foo); return 0; } static int simplechar_test(struct platform_device *dev) { struct simplechar *foo = NULL; foo = pdev_to_owndata(dev); printk(KERN_NOTICE "%s: get id: %d data: %s\n", __func__, foo->id, foo->buffer); return 0; } static int simplechar_probe(struct platform_device *dev) { struct simplechar_platdata *pdata = dev->dev.platform_data; struct simplechar *foo = NULL; int ret = 0; printk(KERN_NOTICE "in %s our data name: %s\n", __func__, pdata->name); // 申请自定义数据空间 foo = kzalloc(sizeof(struct simplechar), GFP_KERNEL); if (foo == NULL) { dev_err(&dev->dev, "No memory for device\n"); return -ENOMEM; } // 设置自定义结构体数据 platform_set_drvdata(dev, foo); foo->id = 250; strcpy(foo->buffer, "hello world"); // 简单测试 simplechar_test(dev); return ret; } // driver static struct platform_driver simplechar_driver = { .probe = simplechar_probe, .remove = simplechar_remove, .driver = { .name = "simplechar", .owner = THIS_MODULE, }, }; static int __init simplechar_drv_init(void) { int ret = 0; printk(KERN_NOTICE "in %s\n", __func__); // 先注册设备(适用于静态定义设备结构体) ret = platform_device_register(&simplechar_device); if (ret) { printk(KERN_NOTICE "platform_device_register failed!\n"); return ret; } // 再注册驱动 ret = platform_driver_register(&simplechar_driver); if (ret) { printk(KERN_NOTICE "platform_driver_register failed!\n"); return ret; } printk("%s() ok\n", __func__); return ret; } static void __exit simplechar_drv_exit(void) { printk(KERN_NOTICE "in %s\n", __func__); // 先卸载驱动 platform_driver_unregister(&simplechar_driver); // 再卸载设备 platform_device_unregister(&simplechar_device); } module_init(simplechar_drv_init); module_exit(simplechar_drv_exit); MODULE_AUTHOR("Late Lee"); MODULE_DESCRIPTION("Simple platform driver"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:simplechar");

本文固定链接: http://www.latelee.org/embedded-linux/kernel-note-2-platform-dev.html

如无特别说明,迟思堂工作室文章均为原创,转载请注明: 我的内核学习笔记2:platform设备模型 | 迟思堂工作室

目前暂无评论

发表评论

*

快捷键:Ctrl+Enter