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

发布时间:2024-09-20  

之前的一篇博客简单介绍了平台设备驱动模型(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);

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>