Linux平台设备驱动 - 按键设备驱动

发布者:HappyExplorer最新更新时间:2024-09-20 来源: cnblogs关键字:Linux平台  设备驱动 手机看文章 扫描二维码
随时随地手机看文章

之前的一篇博客简单介绍了平台设备驱动模型(http://www.cnblogs.com/ape-ming/p/5107641.html),现在就根据那篇博客所列出来的模板把上一篇博客(http://www.cnblogs.com/ape-ming/p/5110996.html)的例程改成平台设备驱动模型。


一、平台设备

根据模板首先要写一个平台设备加载函数:


 1 /*

 2  *    函数名     : button_device_init

 3  *    函数功能: 设备加载

 4  */

 5 

 6 static int __init button_device_init(void)

 7 {

 8     int ret = 0;

 9 

10     /* 注册平台设备 */

11     platform_device_register(&button_platform_device);

12     return ret;

13 }


在这个函数里面调用platform_device_register()对设备进行注册。这个时候就需要给定一个平台设备结构体button_platform_device:


1 static struct platform_device button_platform_device = 

2 {

3     .name = 'button_dev',

4     .id = 0,

5     .num_resources = ARRAY_SIZE(button_resource),

6     .resource = button_resource,

7 };


根据模型在这个结构体里面需指定了设备资源button_resource:


 1 static struct resource button_resource[] = 

 2 {

 3     [0] = 

 4     {

 5         .start = IRQ_EINT(0),

 6         .end = IRQ_EINT(3),

 7         .flags = IORESOURCE_IRQ,

 8     },

 9     [1] = 

10     {

11         .start = (resource_size_t)S3C64XX_GPNDAT,

12         .end = (resource_size_t)S3C64XX_GPNDAT,

13         .flags = IORESOURCE_MEM,

14     },

15 };


数组第一个元素指定了设备的中断号为IRQ_EINT(0)到IRQ_EINT(3),第二个元素指定了设备的IO资源。


二、平台驱动

平台驱动也要先写一个平台驱动加载函数:


 1 /*

 2  *    函数名     : button_driver_init

 3  *    函数功能: 驱动加载

 4  */

 5 

 6 static int __init button_driver_init(void)

 7 {

 8     int ret = 0;

 9     ret = platform_driver_register(&button_platform_driver);

10     return ret;

11 }


在这里面完成了平台驱动的注册,接下来就要有一个平台驱动的结构体button_platform_driver:


 1 static struct platform_driver button_platform_driver = 

 2 {

 3     .probe = button_platform_probe,

 4     .remove = button_platform_remove,

 5     .driver = 

 6     {

 7         .owner = THIS_MODULE,

 8         .name = 'button_dev',

 9     },

10 };


probe成员所指定的函数就是平台设备与驱动配置之后要执行的第一个函数,匹配的条件就是driver里面的name成员是不是和上面平台设备结构体里面的name成员一致。


 1 /*

 2  *    函数名     : button_platform_probe

 3  *    函数功能: 匹配驱动与设备

 4  */

 5 

 6 static int button_platform_probe(struct platform_device *button_device)

 7 {

 8     int ret = 0;

 9     int i = 0;

10     int num = 0;

11     struct resource* irq_resource;

12     

13     /* 注册混杂设备驱动 */

14     ret = misc_register(&misc);

15     if(ret)

16     {

17         printk('can't register miscdevn');

18         return ret;

19     }

20 

21     /* 填充数组 */

22     irq_resource = platform_get_resource(button_device,IORESOURCE_IRQ,0);

23     for(num = 0,i = irq_resource->start;i <= irq_resource->end;i++,num++)

24     {

25         button_irq[num].irq = i;

26     }

27     mem_resource = platform_get_resource(button_device,IORESOURCE_MEM,0);

28     

29     /* 申请外部中断 */

30     for(i = 0;i < sizeof(button_irq)/sizeof(button_irq[0]);i++)

31     {

32         ret = request_irq(button_irq[i].irq,button_interrupt,IRQF_TRIGGER_FALLING,button_irq[i].name,(void*)&button_irq[i]);

33         if(ret != 0)

34         {

35             printk('request_irq failuren');

36         }

37     }

38 

39     /* 初始化工作队列 */

40     INIT_WORK(&button_work,do_buttons);

41 

42     /* 初始化内核定时器 */

43     init_timer(&button_time);

44     button_time.expires = jiffies + HZ/10;    //100ms

45     button_time.function = button_do_time;

46     add_timer(&button_time);

47 

48     return ret;

49 }


在button_platform_probe()函数中完成混杂设备驱动的注册、用platform_get_resource()获取设备的资源、申请外部中断、初始化工作队列、初始化内核定时器。其实就是把混杂设备驱动模型里面的设备注册函数和open函数所做的工作全部放到button_platform_probe()函数里面完成。之后的操作就跟混杂设备模型编写的按键驱动例程基本一样了。


这里总结一下:平台设备驱动只是一个框架,其归根到底还是采用混杂设备驱动模型(或字符设备等)的方式进行驱动程序的编写。但是采用平台设备驱动的方式使得板级代码和驱动代码分离开来,在同一类型的驱动中只需要通过相应的函数获取设备资源和数据而不必要去修改驱动代码。


完整代码:


 1 /*

 2  *    文件名     : button_device.c

 3  *    功能描述: 通过外部中断实现按键驱动程序,平台设备驱动方式

 4  *    驱动模型: platform

 5  *    设备节点: /dev/buttons6410

 6  *    MCU                : S3C6410

 7  *    端口连接: KEY0-GPN0  KEY1-GPN1  KEY2-GPN2  KEY3-GPN3

 8  */

 9 

10 #include

11 #include

12 #include

13 #include

14 #include

15 #include

16 #include

17 

18 #include

19 #include

20 #include

21 #include

22 #include

23 

24 

25 

26 static struct resource button_resource[] = 

27 {

28     [0] = 

29     {

30         .start = IRQ_EINT(0),

31         .end = IRQ_EINT(3),

32         .flags = IORESOURCE_IRQ,

33     },

34     [1] = 

35     {

36         .start = (resource_size_t)S3C64XX_GPNDAT,

37         .end = (resource_size_t)S3C64XX_GPNDAT,

38         .flags = IORESOURCE_MEM,

39     },

40 };

41 

42 static struct platform_device button_platform_device = 

43 {

44     .name = 'button_dev',

45     .id = 0,

46     .num_resources = ARRAY_SIZE(button_resource),

47     .resource = button_resource,

48 };

49 

50 /*

51  *    函数名     : button_device_init

52  *    函数功能: 设备加载

53  */

54 

55 static int __init button_device_init(void)

56 {

57     int ret = 0;

58 

59     /* 注册平台设备 */

60     platform_device_register(&button_platform_device);

61     return ret;

62 }

63 

64 /*

65  *    函数名     : button_device_exit

66  *    函数功能: 设备卸载

67  */

68 

69 static void __exit button_device_exit(void)

70 {

71     /* 注销平台设备*/

72     platform_device_unregister(&button_platform_device);

73 }

74 

75 module_init(button_device_init);

76 module_exit(button_device_exit);

77 MODULE_LICENSE('GPL');


  1 /*

  2  *    文件名     : button_driver.c

  3  *    功能描述: 通过外部中断实现按键驱动程序,平台设备驱动方式

  4  *    驱动模型: platform

  5  *    设备节点: /dev/buttons6410

  6  *    MCU                : S3C6410

  7  *    端口连接: KEY0-GPN0  KEY1-GPN1  KEY2-GPN2  KEY3-GPN3

  8  */

  9 

 10 #include

 11 #include

 12 #include

 13 #include

 14 #include

 15 #include

 16 #include

 17 #include

 18 #include

 19 #include

 20 #include

 21 #include

 22 #include

 23 #include

 24 #include

 25 

 26 #include

 27 #include

 28 #include

 29 

 30 #include

 31 #include

 32 #include

 33 

 34 

 35 volatile int isKey_Pressed = 0;    // 按键按下标志 

 36 struct work_struct button_work;    //定义工作队列

 37 struct timer_list button_time;

 38 struct resource* mem_resource;

 39 struct button_irqs

 40 {

 41     unsigned int irq;

 42     int id;

 43     char* name;

 44 };

 45 

 46 static struct button_irqs button_irq[] = 

 47 {

 48     {0,0,'KEY0'},

 49     {0,1,'KEY1'},

 50     {0,2,'KEY2'},

 51     {0,3,'KEY3'},

 52 };

 53 

 54 /* 初始化等待队列 */

 55 DECLARE_WAIT_QUEUE_HEAD(q_buttons);

 56 

 57 static volatile int button_press[4] = {0};

 58 

 59 /*

 60  *    函数名     : do_buttons

 61  *    函数功能: 工作队列处理函数,处理按键工作

 62  */

 63 static void do_buttons(struct work_struct *work)

 64 {

 65     mod_timer(&button_time,jiffies + HZ/10);

[1] [2]
关键字:Linux平台  设备驱动 引用地址:Linux平台设备驱动 - 按键设备驱动

上一篇:Linux设备驱动开发 - LCD设备驱动分析
下一篇:Linux混杂设备驱动 - 按键设备驱动

推荐阅读最新更新时间:2024-11-05 06:42

基于Linux和ARM9的物流信息化终端平台上对终端定位功能实现
  前 言   物流的定位方案与技术的选择对提高现代物流配送管理效率,减少运营成本具有重要的影响。物流终端定位要求较高的定位精度,能提供全天候连续不间断的定位信息支持,能满足复杂地形条件的定位需求。   本文针对当前物流行业终端定位功能的需求进行分析,针对当前定位技术现状,提出相适应的物流终端定位功能实现方案,并在基于嵌入式Linux和ARM9硬件核心的物流信息化终端平台上对终端定位功能进行了初步的实现。   系统实现方案   移动定位技术的现状分析目前,移动定位技术已经非常成熟,较广的应用主要可以分为两大类,一类是GPS等利用卫星进行后方交汇的定位技术;另一类是利用移动通信网技术提供位置服务的定位技术。常用的有:基于Cell
[单片机]
导出在Linux内核ARM平台驱动可用的函数
进入arch/arm/目录,然后用grep EXPORT_SYMBOL * -r 命令将那些被EXPROT_SYMBOL宏导出的ARM平台驱动可用的函数打印出来,用户程序不能使用EXPORT_SYMBOL导出的函数,通过观察和了解这些导出的函数可以有助于驱动的编写。其中对于s3c2440可以的有: common/scoop.c:32:EXPORT_SYMBOL(platform_scoop_config); common/scoop.c:139:EXPORT_SYMBOL(reset_scoop); common/scoop.c:140:EXPORT_SYMBOL(read_scoop_reg); common/scoop.c:1
[单片机]
基于嵌入式Linux平台的多协议路由器的设计
引言 随着社会信息化进程和互联网的飞迅发展,对无线环境下提供数据服务的需求变得更加迫切。传统的无线移动网络通常以固定的基础设施为支撑,无法满足人们对日益增长的通信业务的要求,一种新型的无线网络——AdHoc网络应运而生。Ad Hoc网络又称移动自组网、多跳网络,具备细网灵活、快捷,不受有线网络的影响等特点,可广泛应用于军事和救援等无法或不便预先铺设网络设施的场合。此外,Ad Hoc网络朝着网络互连的方向发展,Internet的接入是其中一项主要内容。 Ad Hoc无线网络具有自身的特殊性,在组建实际使用的无线工作网络时,必须充分考虑网络的应用规模和扩展性,以及应用的可靠程度及实时性要求,选择合适的网络拓扑结构。目前Ad Hoc
[单片机]
基于嵌入式<font color='red'>Linux</font><font color='red'>平台</font>的多协议路由器的设计
ARM设计的无线网卡设备驱动方案
随着嵌入式系统中无线局域网的接入,既可以实现对嵌人式系统的无线控制和数据传输,又可以满足一些特殊应用的场合。这里通过对USB无线网卡的Linux设备驱动的深入理解和分析,成功地移植在Atmel 9261 ARM处理器上。实现了嵌入式系统的无线局域网接入。利用该平台,可以进一步设计完善医用伽马相机和小型SPECT设备的手持数据采集系统,使得控制人员能够远离数据采集现场,而通过远程终端来控制现场数据和各种控制信号,较好地解决了安全性问题。 1 硬件系统构成 1.1 USB无线网卡介绍 无线网卡是无线局域网(WLAN)的重要组成部分,WLAN的物理层及MAC层是用无线网卡的硬件及其软件完成的,而LLC层以上各层均由计算机软件来实现
[单片机]
ARM设计的无线网卡<font color='red'>设备驱动</font>方案
USB设备驱动开发-USB协议相关(2)
一、USB设备通用操作       1. 热插拔 在热插拔中,USB HUB扮演着很重要的角色,HUB向主机报告端口的状态改变,主机才能对相应的动作采取相应的操作;       2. 地址分派 当USB设备插入后,主机会对USB设备分配一个独一无二的地址,同时resetUSB设备并对HUB的相应端口使能;       3. 配置(Configuration): 在USB设备的功能可用之前必须被配置,主机首先获取设备的配置信息了解设备的功能进而进行配置。主机将设置设备的配置(configuration),并且可能对接口(Interface)选择可变的设置(setting). 在一个配
[嵌入式]
基于arm920T嵌入式Linux的实验平台环境的构建
面向A R M微处理器构架的嵌入式操作系统的使用量这些年持续增长,在各种嵌入式操作系统中, L inux是获得支持最多的第三大力量。 目前,ARM L inux支持包括ARM610、A RM710、ARM720T cores、ARM920T cores、StrongARM 110、StrongARM1100、XScale等系列的arm处理器。 Gameboy是目前比较流行的8位掌上游戏机,通常被简称为GB,它的最终态Game Boy Color (GBC)是完全向后兼容的。Gnuboy是GB /GBC的软件模拟器,是一种自由软件,它是基于Qt系统的,能够运行几乎所有的黑白和彩色的GB /GBC游戏ROM,但运行复杂
[单片机]
基于arm920T嵌入式<font color='red'>Linux</font>的实验<font color='red'>平台</font>环境的构建
arm平台linux异常处理流程
异常处理 异常向量的位置 arch/arm/kernel/traps.c中的early_trap_init函数将异常向量复制到某特定位置,这样当异常发生时,arm就能找到异常向量。 /* * Copy the vectors, stubs and kuser helpers (in entry-armv.S) * into the vector page, mapped at 0xffff0000, and ensure these * are visible to the instruction stream. */ memcpy((void *)vectors, __vectors_start, __vectors
[单片机]
s3c6410的UART设备驱动(1)
1、 这段话摘于《设备驱动开发详解》 在使用串口核心层这个通用串口tty驱动层的接口后,一个串口驱动要完成的主要工作: (1)、定义uart_driver、uart_ops、uart_port等结构体的实例并在适当的地方根据具体硬件和驱动的情况初始化它们,当然具体设备的驱动可以将这些结构体在新定义的xxx_uart_driver、xxx_uart_ops、xxx_uart_port之内。 (2)、在模块初始化是调用uart_register_driver和uart_add_port注册UART驱动并添加端口,在模块卸载时调用uart_unregister_driver和uart_remove_one_port以注销
[单片机]
s3c6410的UART<font color='red'>设备驱动</font>(1)
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

更多往期活动

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved