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. HUST软工1506班第2周作业成绩公布

    说明 本次公布的成绩对应的作业为: 第2周个人作业:WordCount编码和测试 如果同学对作业成绩存在异议,在成绩公布的72小时内(截止日期4月26日0点)可以进行申诉,方式如下: 毕博平台的第二周 ...

  2. Mac上修改MySQL默认字符集为utf8

    1.检查默认安装的mysql的字符集 mysql> show variables like '%char%'; +--------------------------+------------- ...

  3. mysql数据库使用sql查询数据库大小及表大小

    网上查了很多资料,最后发现一个可行的,分享如下: 数据库大小查询: select concat(round(sum(DATA_LENGTH/1024/1024),2),'M') from inform ...

  4. 系统数据库--修改tempdb的位置

    use mastergoAlter database tempdb modify file (name = tempdev, filename = 'G:\db\tempdb.mdf')goAlter ...

  5. Apache 中httpd.conf文件配置详解(转载)

    httpd.conf文件配置详解   Apache的基本设置主要交由httpd.conf来设定管理,我们要修改Apache的相关设定,主要还是通过修改httpd.cong来实现.下面让我们来看看htt ...

  6. elk日志分析平台安装

    ELK安装 前言 什么是ELK? 通俗来讲,ELK是由Elasticsearch.Logstash.Kibana 三个开源软件的组成的一个组合体,这三个软件当中,每个软件用于完成不同的功能,ELK 又 ...

  7. SDOI2010粟粟的书架

    题目传送:https://www.luogu.org/problemnew/show/P2468 这是一个二合一的题目,前50% \(n!=1\)的分数中,我们考虑用动态规划来做. 设\(sum[i] ...

  8. “全栈2019”Java第四十章:this关键字

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  9. SFML从入门到放弃(1) 窗口和交互

    SFML从入门到放弃(1) 窗口和交互 创建一个新窗口: sf::RenderWindow window(sf::VideoMode(,),"new window"); 但是光创建 ...

  10. 如何提高scrapy的爬取效率

    提高scrapy的爬取效率 增加并发: 默认scrapy开启的并发线程为32个,可以适当进行增加.在settings配置文件中修改CONCURRENT_REQUESTS = 100值为100,并发设置 ...