改进的平台设备驱动——dev和drv完全分离
这是平台设备:
1 #include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/bitmap.h>
#include <asm/gpio.h>
#include <linux/platform_device.h> static struct resource led_data[] = {
[] = {
.start = 0x56000050,
.end = 0x56000050 + -,
.flags = IORESOURCE_MEM,
},
[] = {
.start = ,
.end = ,
.flags = IORESOURCE_IO,
},
[] = {
.start = IRQ_EINT0,
.end = IRQ_EINT0,
.name = "IRQ_EINT0",
.flags = IORESOURCE_IRQ,
},
[] = {
.start = IRQ_EINT2,
.end = IRQ_EINT2,
.name = "IRQ_EINT2",
.flags = IORESOURCE_IRQ,
},
[] = {
.start = IRQ_EINT11,
.end = IRQ_EINT11,
.name = "IRQ_EINT11",
.flags = IORESOURCE_IRQ,
}
}; static struct platform_device led_device = {
.name = "jz2440_led",
.num_resources = ARRAY_SIZE(led_data),
.resource = led_data,
}; int led_dev_init(void)
{
platform_device_register(&led_device);
return ;
} void led_dev_exit(void)
{
platform_device_unregister(&led_device);
} module_init(led_dev_init);
module_exit(led_dev_exit); MODULE_LICENSE("GPL");
这是平台驱动:
1 #include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/input.h>
#include <linux/bitmap.h>
#include <asm/gpio.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/sched.h> static volatile unsigned long *ledcon;
static volatile unsigned long *leddat; static int pin_nums;
static int pin_start,pin_end; static struct resource *pRes;
static unsigned long *pname;
static struct resource *irq; static struct class *led_class;
static struct timer_list led_timer; static int led_open(struct inode *inode, struct file *file)
{
int i;
for(i = ; i < pin_nums; i++){
*ledcon &= ~( << (pin_start + i) * );
*leddat &= ~( << (pin_start + i));
*ledcon |= ( << (pin_start + i) * );
} return ;
} static struct file_operations led_fops = {
.owner = THIS_MODULE,
.open = led_open, }; static irqreturn_t led_irq(int dat, void *pvoid)
{
pRes = (struct resource *)pvoid;
mod_timer(&led_timer, jiffies + HZ/); return IRQ_HANDLED;
} static int STRCMP(const char *str1,const char *str2)
{
while((*str1++) == (*str2++)){
if(*str1 == '\0' && *str2 == '\0')
return ;
else if(*str1 == '\0' || *str2 == '\0')
break;
}
return -;
} static int GetPinNum(struct resource *pres)
{
int i;
for(i = ; i < pin_nums; i++){
if( == STRCMP(pres->name,(char *)*(pname + i))){
return i;
}
}
return -;
} static void led_time_function(unsigned long dat)
{ int ls = GetPinNum(pRes);
if(ls >= )
*leddat ^= ( << (pin_start + ls));
} static int major;
static int led_probe(struct platform_device *led_dev)
{
int i;
struct resource *reg;
struct resource *led_pins; major = register_chrdev(,"led",&led_fops);
led_class = class_create(THIS_MODULE, "led");
device_create(led_class,NULL,MKDEV(major,),NULL,"led0");
reg = platform_get_resource(led_dev,IORESOURCE_MEM,);
led_pins = platform_get_resource(led_dev,IORESOURCE_IO,);
ledcon = ioremap(reg->start,reg->end - reg->start + );
leddat = ledcon + ;
pin_start = led_pins->start;
pin_end = led_pins->end;
pin_nums = led_pins->end - led_pins->start + ;
pname = (unsigned long *)kmalloc(pin_nums * sizeof(unsigned long), GFP_KERNEL); //pin_nums个指针
for(i = ; i < pin_nums; i++){
irq = platform_get_resource(led_dev,IORESOURCE_IRQ,i);
request_irq(irq->start, led_irq, IRQ_TYPE_EDGE_BOTH, irq->name, irq);
*(pname + i)= (unsigned long)irq->name;
} init_timer(&led_timer);
led_timer.function = led_time_function;
add_timer(&led_timer); return ;
} static int led_remove(struct platform_device *led_dev)
{
int i;
del_timer(&led_timer);
for(i = ; i < pin_nums; i++){
irq = platform_get_resource(led_dev,IORESOURCE_IRQ,i);
free_irq(irq->start,irq);
}
kfree(pname);
iounmap(ledcon);
device_destroy(led_class, MKDEV(major,));
class_destroy(led_class);
unregister_chrdev(major, "led"); return ;
} static struct platform_driver led_drv = {
.driver = {
.name = "jz2440_led",
.owner = THIS_MODULE,
},
.probe = led_probe,
.remove = __devexit_p(led_remove),
}; static int led_init(void)
{
platform_driver_register(&led_drv);
return ;
} static void led_exit(void)
{
platform_driver_unregister(&led_drv);
} module_init(led_init);
module_exit(led_exit); MODULE_LICENSE("GPL");
这是应用程序:
1 #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> int main(int argc,char **argv)
{
int fd = open("/dev/led0",O_RDWR);
if(fd < ){
return -;
} while();
return ;
}
改进的平台设备驱动——dev和drv完全分离的更多相关文章
- 嵌入式Linux驱动学习之路(十七)驱动程序分层分离概念-平台设备驱动
平台设备驱动: 包含BUS(总线).DEVICE.DRIVER. DEVICE:硬件相关的代码 DRIVER:比较稳定的代码 BUS有一个driver链表和device链表. ①把device放入bu ...
- 字符设备驱动、平台设备驱动、设备驱动模型、sysfs的比较和关联
转载自:http://www.kancloud.cn/yueqian_scut/emlinux/106829 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动.设备驱动模型和sy ...
- Linux驱动之平台设备驱动模型简析(驱动分离分层概念的建立)
Linux设备模型的目的:为内核建立一个统一的设备模型,从而有一个对系统结构的一般性抽象描述.换句话说,Linux设备模型提取了设备操作的共同属性,进行抽象,并将这部分共同的属性在内核中实现,而为需要 ...
- 【Linux高级驱动】linux设备驱动模型之平台设备驱动机制
[1:引言: linux字符设备驱动的基本编程流程] 1.实现模块加载函数 a.申请主设备号 register_chrdev(major,name,file_operations); b.创 ...
- [kernel]字符设备驱动、平台设备驱动、设备驱动模型、sysfs几者之间的比较和关联
转自:http://www.2cto.com/kf/201510/444943.html Linux驱动开发经验总结,绝对干货! 学习Linux设备驱动开发的过程中自然会遇到字符设备驱动.平台设备驱动 ...
- Linux Platform devices 平台设备驱动
设备总线驱动模型:http://blog.csdn.net/lizuobin2/article/details/51570196 本文主要参考:http://www.wowotech.net/devi ...
- 【Linux高级驱动】平台设备驱动机制的编程流程与编译进内核
[平台设备驱动机制的编程流程] [如何将驱动静态的编译进内核镜像] 1.添加资源(dev-led.c) 1.1:一般来说,系统习惯上将资源放在arch/arm/plat-samsung/目录中 cp ...
- Linux中总线设备驱动模型及平台设备驱动实例
本文将简要地介绍Linux总线设备驱动模型及其实现方式,并不会过多地涉及其在内核中的具体实现,最后,本文将会以平台总线为例介绍设备和驱动程序的实现过程. 目录: 一.总线设备驱动模型总体介绍及其实现方 ...
- platform平台设备驱动简化示例代码
driver.c: #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h& ...
随机推荐
- div的浮动(float)
什么是浮动 浮动,故名思议,就是移动位置. 之所以不叫移动,而叫浮动,那是因为给元素设置浮动后,元素会浮到文档上面来,术语叫脱离文档流. 例子 下面我们看例子 <html> <hea ...
- 从零开始的全栈工程师——js篇(js的异步)
js中的异步 Javascript语言的执行环境是"单线程"(single thread,就是指一次只能完成一件任务.如果有多个任务,就必须排队,前面一个任务完成,再执行后面一个任 ...
- <Android 基础(七)> DrawerLayout and NavigationView
介绍 DrawerLayout是Support Library包中实现了侧滑菜单效果的控件 android.support.v4.widget.DrawerLayout NavigationView是 ...
- [原创]Centos7 安装配置ASP.NET Core+Nginx+Supervisor
序言 此教程安装的都是最新版本的. 一键安装 有了这个神器,下面的教程就不用做了!只需运行几行代码,直接打开浏览器就可以访问! cd /home/ wget https://files.cnblogs ...
- [javascript]什么是闭包?
http://www.zcfy.cc/article/master-the-javascript-interview-what-is-a-closure-2127.html
- POJO详解
转自:http://blog.csdn.net/lushuaiyin/article/details/7436318 一:什么是POJO POJO的名称有多种,pure old java objec ...
- Servlet是线程安全的吗?
Servlet不是线程安全的. 要解释为什么Servlet为什么不是线程安全的,需要了解Servlet容器(即Tomcat)使如何响应HTTP请求的. 当Tomcat接收到Client的HTTP请求时 ...
- 吴超hadoop7天视频教程全集
吴超hadoop7天视频教程全集 一.初级班全套视频 1.linux使用(3节) 2.伪分布模式安装hadoop(2节) 3.HDFS的体系结构和操作(2节) 4.HDFS的java操作方式(4节) ...
- 计算后缀表达式的过程(C#)
计算后缀表达式的过程是一个很好玩的过程,而且很简单哦!这里呢,有个计算的技巧,就是:遇到数字直接入栈,遇到运算符就计算! 后缀表达式也叫逆波兰表达式,求值过程可以用到栈来辅助存储: 假定待求值的后缀表 ...
- S7-1500 读取V90/S120/S210/G120的常用驱动参数
S7-1500 读取V90/S120的常用驱动参数 此程序已更新,可以下载例子程序 https://files.cnblogs.com/files/lion-zheng/PLC_async_drive ...