Linux平台总线设备驱动
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平台总线设备驱动的更多相关文章
- 芯灵思SinlinxA33开发板 Linux平台总线设备驱动
1.什么是platform(平台)总线? 相对于USB.PCI.I2C.SPI等物理总线来说,platform总线是一种虚拟.抽象出来的总线,实际中并不存在这样的总线. 那为什么需要platform总 ...
- Linux中总线设备驱动模型及平台设备驱动实例
本文将简要地介绍Linux总线设备驱动模型及其实现方式,并不会过多地涉及其在内核中的具体实现,最后,本文将会以平台总线为例介绍设备和驱动程序的实现过程. 目录: 一.总线设备驱动模型总体介绍及其实现方 ...
- Linux的总线设备驱动模型
裸机编写驱动比较自由,按照手册实现其功能即可,每个人写出来都有很大不同: 而Linux中还需要按照Linux的驱动模型来编写,也就是需要按照"模板"来写,写出来的驱动就比较统一. ...
- Linux I2C总线设备驱动模型分析(ov7740)
1. 框架1.1 硬件协议简介1.2 驱动框架1.3 bus-drv-dev模型及写程序a. 设备的4种构建方法a.1 定义一个i2c_board_info, 里面有:名字, 设备地址 然后i2c_r ...
- Linux学习 : 总线-设备-驱动模型
platform总线是一种虚拟的总线,相应的设备则为platform_device,而驱动则为platform_driver.Linux 2.6的设备驱动模型中,把I2C.RTC.LCD等都归纳为pl ...
- Linux下 USB设备驱动分析(原创)
之前做过STM32的usb HID复合设备,闲来看看linux下USB设备驱动是怎么一回事, 参考资料基于韦东山JZ2440开发板,以下,有错误欢迎指出. 1.准备知识 1.1USB相关概念: USB ...
- Linux和Windows设备驱动架构比较
毕业后一直在学操作系统, 有时候觉得什么都懂了,有时候又觉得好像什么都不懂,但总体来说自认为对操作系统实现机制的了解比周围的人还是要多一些.去年曾花了几个星期的晚上时间断断续续翻译了这篇对Linux和 ...
- usb驱动开发4之总线设备驱动模型
在上文说usb_init函数,却给我们留下了很多岔路口.这次就来好好聊聊关于总线设备驱动模型.这节只讲理论,不讲其中的函数方法,关于函数方法使用参考其他资料. 总线.设备.驱动对应内核结构体分别为bu ...
- 总线设备驱动模型---platform篇
总线设备驱动模型----驱动篇 http://blog.chinaunix.net/uid-27664726-id-3334923.html http://blog.chinaunix.net/uid ...
随机推荐
- HaXe以及OpenFL部署
HaXe以及OpenFL部署 Haxe是一种跨平台的编程语言,本文并未HAXE的教程,只是针对OPENFL以及HAXE的部署教程.HAXE的语法非常类似AS3,由于国内部署HAXE艰难,经常下载到一半 ...
- CentOS7 安装Maven3
下载安装文件 cd /root wget http://mirrors.tuna.tsinghua.edu.cn/apache/maven/maven-3/3.3.9/binaries/apache- ...
- JavaBugCharSequence
目录 文章背景 目录 问题分析 问题解决 说明 参考文章 版本记录 文章背景 新建一个项目时候,不知道为什么,代码出现java.lang.CharSequence cannot be resolved ...
- RPM管理,计划任务与性能监控
=========== RPM 软件包管理: 相关命令: rpm -ivh 软件包名称 rpm -e 软件包名称 rpm -U 软件名称 软件包信息查询: 相关命令: rpm -q 查询指定软 ...
- Backup--压缩备份和数据库压缩
1> 即使数据库启用了页压缩或行压缩,压缩备份也可以有效减小备份的大小,压缩备份的压缩效率取决于表中的数据类型 2> 数据库压缩有利于降低备份时间(因为数据库变小) 3> 对已启用压 ...
- 项目前端打包工具从 NEJ 切换成 webpack
此文已由作者张磊授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 这里不讨论 NEJ 和 webpack 的优劣,仅从技术角度来探寻一下能否实现,以及实现的代价. 前言 上一篇 ...
- HAOI2014 遥感监测
题目链接:戳我 比较水的一个题,直接处理点,找在直线上的可以覆盖到它的区间,然后做最小线段覆盖即可: 代码如下: #include<iostream> #include<cstdio ...
- 爬虫开发9.scrapy框架之递归解析和post请求
今日概要 递归爬取解析多页页面数据 scrapy核心组件工作流程 scrapy的post请求发送 今日详情 1.递归爬取解析多页页面数据 - 需求:将糗事百科所有页码的作者和段子内容数据进行爬取切持久 ...
- const 与define 创建符号常量的 用法与区别
一.define 的用法: 在c语言中我经常会看到 :#define PI 12 ,这是创建了一个符号常量,这里面要注意没有那个等于号“=”: 二.const 的用法: 1.const 也可以来创 ...
- 最后一个 last-of-type
last-of-type这个比较好点,有时候:last-child 不起作用