1. 平台总线(Platform bus)是linux2.6内核加入的一种虚拟总线,其优势在于采用了总线的模型对设备(没有挂到真实总线的设备)与驱动进行了管理,这样提高了程序的可移植性。

2. 平台总线开发设备驱动流程

(1)定义平台设备

(2)注册平台设备

(3)定义平台驱动

(4)注册平台驱动

3. 平台设备使用struct platform_device来描述

struct platform_device {
const char * name;
int id;
struct device dev;
u32 num_resources;
struct resource * resource;
};

① name:设备名

② id:设备ID:配合设备名使用,以区分不同设备

③ dev:

④ num_resources:硬件资源个数

⑤ resource:硬件资源

struct resource {
resource_size_t start;
resource_size_t end;
const char *name;
unsigned long flags;
struct resource *parent, *sibling, *child;
};

(1) 注册平台设备:int platform_device_register(struct platform_device *pdev);

(2) 注销平台设备:void platform_device_unregister(struct platform_device *pdev);

4. 平台驱动使用struct platform_driver描述

struct platform_driver {
int (*probe)(struct platform_device *);
int (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*suspend_late)(struct platform_device *, pm_message_t state);
int (*resume_early)(struct platform_device *);
int (*resume)(struct platform_device *);
struct device_driver driver;
};

(1)平台驱动注册: int platform_driver_register(struct platform_driver *)

(2)平台驱动注销:void platform_driver_unregister(struct platform_driver *)

5. 简单示例

① PlatformKeyDevice.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h> MODULE_LICENSE("GPL"); #define GPGCON 0x56000060 void key_release(struct device *dev)
{
printk("dev->init_name = %s release!\n", dev->init_name);
} static struct resource key_resource[] = {
[] = {
.start = GPGCON,
.end = GPGCON + ,
.flags = IORESOURCE_MEM,
},
[] = {
.start = IRQ_EINT8,
.end = IRQ_EINT11,
.flags = IORESOURCE_IRQ,
},
[] = {
.start = IRQ_EINT13,
.end = IRQ_EINT14,
.flags = IORESOURCE_IRQ,
},
[] = {
.start = IRQ_EINT15,
.end = IRQ_EINT19,
.flags = IORESOURCE_IRQ,
},
}; struct platform_device key_device = {
.name = "my-key",
.id = ,
.dev = {
.init_name = "init_key",
.release = key_release,
},
.num_resources = ARRAY_SIZE(key_resource),
.resource = key_resource,
}; static int button_init(void)
{
platform_device_register(&key_device); return ;
} static void button_exit(void)
{
platform_device_unregister(&key_device);
} module_init(button_init);
module_exit(button_exit);

② PlatformKeyDriver.c

#include <linux/module.h>
#include <linux/init.h>
#include <linux/miscdevice.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/platform_device.h> MODULE_LICENSE("GPL"); struct timer_list buttons_timer; unsigned int key_num = ; wait_queue_head_t key_wait_queue; unsigned int *key_base = NULL; void buttons_timer_function(unsigned long data)
{
printk("keys_timer_function\n"); key_num = ; printk("data = %lx\n", data); switch(data)
{
case IRQ_EINT8:
key_num = ;
break; case IRQ_EINT11:
key_num = ;
break; case IRQ_EINT13:
key_num = ;
break; case IRQ_EINT14:
key_num = ;
break; case IRQ_EINT15:
key_num = ;
break; case IRQ_EINT19:
key_num = ;
break; default:
break;
} printk("key_num = %d\n", key_num); wake_up(&key_wait_queue);
} irqreturn_t key_int(int irq, void *dev_id)
{
//1. 检测是否发生了按键中断 //2. 清除已经发生的按键中断 //3. 提交下半部
buttons_timer.data = irq;
mod_timer(&buttons_timer, jiffies + (HZ /)); //return 0;
return IRQ_HANDLED;
} void key_hw_init(void)
{
unsigned int config_data; if(key_base != NULL)
{
config_data = readl(key_base);
config_data &= 0b001111110000001100111100;
config_data |= 0b100000001010100010000010; writel(config_data, key_base);
}
} int key_open(struct inode *node,struct file *filp)
{
return ;
} ssize_t key_read(struct file *filp, char __user *buf, size_t size, loff_t *pos)
{
wait_event(key_wait_queue, key_num); copy_to_user(buf, &key_num, ); key_num = ; return ;
} struct file_operations key_fops =
{
.open = key_open,
.read = key_read,
}; struct miscdevice key_miscdev = {
.minor = ,
.name = "key",
.fops = &key_fops,
}; int key_probe(struct platform_device *pdev)
{
int ret, size; struct resource *resources;
struct resource *resources_irq; ret = misc_register(&key_miscdev); if (ret != )
printk("register fail!\n"); //注册中断处理程序
resources_irq = platform_get_resource(pdev, IORESOURCE_IRQ, ); request_irq(resources_irq->start, key_int, IRQF_TRIGGER_LOW, "key1", );
request_irq(resources_irq->end, key_int, IRQF_TRIGGER_LOW, "key2", ); resources_irq = platform_get_resource(pdev, IORESOURCE_IRQ, ); request_irq(resources_irq->start, key_int, IRQF_TRIGGER_LOW, "key3", );
request_irq(resources_irq->end, key_int, IRQF_TRIGGER_LOW, "key4", ); resources_irq = platform_get_resource(pdev, IORESOURCE_IRQ, ); request_irq(resources_irq->start, key_int,IRQF_TRIGGER_LOW, "key5", );
request_irq(resources_irq->end, key_int,IRQF_TRIGGER_LOW, "key6", ); //按键初始化
resources = platform_get_resource(pdev, IORESOURCE_MEM, );
size = (resources->end - resources->start) + ;
key_base = ioremap(resources->start, size); key_hw_init(); /* 初始化定时器 */
init_timer(&buttons_timer);
buttons_timer.function = buttons_timer_function; /* 向内核注册一个定时器 */
add_timer(&buttons_timer); /*初始化等待队列*/
init_waitqueue_head(&key_wait_queue); return ;
} int key_remove(struct platform_device *pdev)
{
struct resource *resources_irq;
int i = ; printk("PlatformKeyDriver: key_remove!\n"); for(i = ; i <= ; i++)
{
resources_irq = platform_get_resource(pdev, IORESOURCE_IRQ, i); free_irq(resources_irq->start, );
free_irq(resources_irq->end, );
} iounmap(key_base);
misc_deregister(&key_miscdev); return ;
} static struct platform_driver key_driver = {
.probe = key_probe,
.remove = key_remove,
.driver = {
.owner = THIS_MODULE,
.name = "my-key",
},
}; static int button_init(void)
{
return platform_driver_register(&key_driver);
} static void button_exit(void)
{
platform_driver_unregister(&key_driver);
} module_init(button_init);
module_exit(button_exit);

Linux平台总线设备驱动的更多相关文章

  1. 芯灵思SinlinxA33开发板 Linux平台总线设备驱动

    1.什么是platform(平台)总线? 相对于USB.PCI.I2C.SPI等物理总线来说,platform总线是一种虚拟.抽象出来的总线,实际中并不存在这样的总线. 那为什么需要platform总 ...

  2. Linux中总线设备驱动模型及平台设备驱动实例

    本文将简要地介绍Linux总线设备驱动模型及其实现方式,并不会过多地涉及其在内核中的具体实现,最后,本文将会以平台总线为例介绍设备和驱动程序的实现过程. 目录: 一.总线设备驱动模型总体介绍及其实现方 ...

  3. Linux的总线设备驱动模型

    裸机编写驱动比较自由,按照手册实现其功能即可,每个人写出来都有很大不同: 而Linux中还需要按照Linux的驱动模型来编写,也就是需要按照"模板"来写,写出来的驱动就比较统一. ...

  4. Linux I2C总线设备驱动模型分析(ov7740)

    1. 框架1.1 硬件协议简介1.2 驱动框架1.3 bus-drv-dev模型及写程序a. 设备的4种构建方法a.1 定义一个i2c_board_info, 里面有:名字, 设备地址 然后i2c_r ...

  5. Linux学习 : 总线-设备-驱动模型

    platform总线是一种虚拟的总线,相应的设备则为platform_device,而驱动则为platform_driver.Linux 2.6的设备驱动模型中,把I2C.RTC.LCD等都归纳为pl ...

  6. Linux下 USB设备驱动分析(原创)

    之前做过STM32的usb HID复合设备,闲来看看linux下USB设备驱动是怎么一回事, 参考资料基于韦东山JZ2440开发板,以下,有错误欢迎指出. 1.准备知识 1.1USB相关概念: USB ...

  7. Linux和Windows设备驱动架构比较

    毕业后一直在学操作系统, 有时候觉得什么都懂了,有时候又觉得好像什么都不懂,但总体来说自认为对操作系统实现机制的了解比周围的人还是要多一些.去年曾花了几个星期的晚上时间断断续续翻译了这篇对Linux和 ...

  8. usb驱动开发4之总线设备驱动模型

    在上文说usb_init函数,却给我们留下了很多岔路口.这次就来好好聊聊关于总线设备驱动模型.这节只讲理论,不讲其中的函数方法,关于函数方法使用参考其他资料. 总线.设备.驱动对应内核结构体分别为bu ...

  9. 总线设备驱动模型---platform篇

    总线设备驱动模型----驱动篇 http://blog.chinaunix.net/uid-27664726-id-3334923.html http://blog.chinaunix.net/uid ...

随机推荐

  1. MyBatis 3(中文版) 第四章 使用注解配置SQL映射器

    本章将涵盖以下话题: l 在映射器Mapper接口上使用注解 l 映射语句 @Insert,@Update,@Delete,@SeelctStatements l 结果映射 一对一映射 一对多映射 l ...

  2. [C#] IEnumerable vs IQueryable

    这篇博客将介绍IEnumerable和IQueryable之间的区别. 1. IQueryable是继承自IEnumerable接口的.所以IEnumerable能做的,IQueryable都能做. ...

  3. 并发编程CAS操作

    并发编程CAS操作 简介 CAS即compare and swap,中文就是比较并交换 CAS是Java并发包的基石 原理 其实CAS的原理相对来说比较简单.将要被改变的数据和期望的值作比较,当两个值 ...

  4. 手把手教你看KEGG通路图!

    手把手教你看KEGG通路图! 亲爱的小伙伴们,是不是正关注代谢通路研究?或者你正面对数据,绞尽脑汁?小编当然不能让亲们这么辛苦,今天就跟大家分享KEGG代谢通路图的正确解读方法,还在迷糊中的小伙伴赶紧 ...

  5. centos7.0查看有没有运行mysql

    centos7自带是mariadb,一个mysql的变种. 查看有没有安装过:yum list installed mysql*rpm -qa | grep mysql* 安装mysql软件(mari ...

  6. mysql复制表以及复制数据库

    (一)将旧表复制到新表 1.CREATE TABLE新表 SELECT* FROM旧表; 该语句只是复制表结构以及数据,它不会复制与表关联的其他数据库对象,如索引,主键约束,外键约束,触发器等. CR ...

  7. MFC 错误异常,用vs添加资源并为资源定义类后报错:error C2065 : 未声明的标识符

    添加了一个Dialog资源,修改了ID之后右击资源添加了一个类,在类里面有一个成员变量: // 对话框数据    enum { IDD = IDD_GETIN }; 而在编译过程中出现报错,错误代号是 ...

  8. MongoDB整理笔记のjava MongoDB分页优化

    最近项目在做网站用户数据新访客统计,数据存储在MongoDB中,统计的数据其实也并不是很大,1000W上下,但是公司只配给我4G内存的电脑,让我程序跑起来气喘吁吁...很是疲惫不堪. 最常见的问题莫过 ...

  9. union 和 all union

    sql union用法和sql union all用法,sql union效率 1.sql union用法 sql union在查询中可以将两个SQL 语句的结果合并起来.如果这样看的话, UNION ...

  10. mybatis 起别名

    mybatis.xml文件 typeAliases 节点进行配置别名(有两种配置方法:1.typeAlias   2.package 这个方式比较简单) 也可以省略不写