zoukankan      html  css  js  c++  java
  • platform设备驱动框架

    驱动框架

    通过使用platform设备驱动框架,实现led驱动与设备操作的分离。

       

    我们关注led_drv里面的 struct platform_driver led_drv里面的.probe函数,当有同名的device注册到内核,将运行这个driver的probe函数(同名的:led_dev里面的struct platform_device led_dev里面的.name与 struct platform_driver led_drv里面的.name一一对应)。

       

    led_dev.c

    1 /* 分配/设置/注册一个platform_device */
    2 #include <linux/module.h>
    3 #include <linux/version.h>
    4
    5 #include <linux/init.h>
    6 #include <linux/fs.h>
    7 #include <linux/interrupt.h>
    8 #include <linux/irq.h>
    9 #include <linux/sched.h>
    10 #include <linux/pm.h>
    11 #include <linux/sysctl.h>
    12 #include <linux/proc_fs.h>
    13 #include <linux/delay.h>
    14 #include <linux/platform_device.h>
    15 #include <linux/input.h>
    16 #include <linux/irq.h>
    17 #include <asm/uaccess.h>
    18 #include <asm/io.h>
    19
    20
    21 static struct resource led_resource[] = {
    22         [0] = {
    23                 .start         = 0x56000050,                
    24                 .end         = 0x56000050 + 8 - 1,        
    25                 .flags        = IORESOURCE_MEM,        //标记资源类型
    26         },
    27
    28         [1] = {                                                
    29                 .start         = 4,                                        
    30                 .end         = 4,                                        
    31                 .flags        = IORESOURCE_IRQ,                
    32         }
    33 };
    34
    35 static void led_release(struct device *dev)
    36 {
    37
    38 }
    39
    40 static struct platform_device led_dev = {
    41         .name                         = "myled",        //与drv保持一致
    42         .id                         = -1,
    43         .num_resources         = ARRAY_SIZE(led_resource),
    44         .resource                = led_resource,
    45         .dev = {
    46                 .release = led_release,
    47         }
    48 };
    49
    50
    51 static int led_dev_init(void)
    52 {
    53         platform_device_register(&led_dev);
    54         return 0;
    55 }
    56
    57
    58 static void led_dev_exit(void)
    59 {
    60         platform_device_unregister(&led_dev);
    61         return;
    62 }
    63
    64 module_init(led_dev_init);
    65 module_exit(led_dev_exit);
    66 MODULE_LICENSE("GPL");

       

       

    led_drv.c

    1 /* 分配/设置/注册一个platform_driver */
    2 #include <linux/module.h>
    3 #include <linux/version.h>
    4
    5 #include <linux/init.h>
    6 #include <linux/fs.h>
    7 #include <linux/interrupt.h>
    8 #include <linux/irq.h>
    9 #include <linux/sched.h>
    10 #include <linux/pm.h>
    11 #include <linux/sysctl.h>
    12 #include <linux/proc_fs.h>
    13 #include <linux/delay.h>
    14 #include <linux/platform_device.h>
    15 #include <linux/input.h>
    16 #include <linux/irq.h>
    17 #include <asm/uaccess.h>
    18 #include <asm/io.h>
    19
    20
    21
    22 static int major;
    23
    24 static struct class *led_class;
    25 static struct class_device *led_class_dev;
    26
    27 static unsigned long *gpioctl;
    28 static unsigned long *gpiodat;
    29
    30 static int led_pin;
    31
    32
    33 static int led_open(struct inode *inode, struct file *file)
    34 {
    35         /* 初始化LED硬件 ―― GPF4、GPF5、GPF6设置为输出 */
    36         *gpioctl &= ~(0x3<<(led_pin*2));
    37         *gpioctl |= (0x1<<(led_pin*2));
    38         return 0;
    39 }
    40
    41 static ssize_t led_write(struct file *file, const char __user *buf,
    42 size_t count, loff_t *ppos)
    43 {
    44         int val;
    45
    46         copy_from_user(&val, buf, count);
    47         if (1 == val)
    48         {
    49                 *gpiodat &= ~(1<<led_pin);
    50         }
    51         else {
    52                 *gpiodat |= 1<<led_pin;
    53         }
    54         return 0;
    55 }
    56
    57 static struct file_operations led_fops = {
    58         .owner         = THIS_MODULE,
    59         .open         = led_open,
    60         .write        = led_write,
    61 };
    62
    63 static int led_probe(struct platform_device *pdev)
    64 {
    65         struct resource *res;
    66
    67         printk("led_probe, found led ");
    68         
    69         /* 根据platform_device(led_dev)里面的资源,进行ioremap */
    70         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
    71         gpioctl = ioremap(res->start, res->end - res->start + 1);
    72         gpiodat = gpioctl + 1;
    73
    74         res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
    75         led_pin = res->start;
    76
    77         /* 注册字符设备驱动 */
    78         major = register_chrdev(0, "myled", &led_fops);
    79
    80         led_class = class_create(THIS_MODULE, "myled");
    81
    82         /* 创建有主设备号和次设备号的设备节点系统信息 */
    83         led_class_dev = class_device_create(led_class, NULL, MKDEV(major, 0), NULL, "led");
    84
    85         return 0;
    86 }
    87
    88 static int led_remove(struct platform_device *pdev)
    89 {
    90         printk("led_remove ");
    91         /* 根据platform_device(led_dev)里面的资源,进行iounmap */
    92
    93         /* 卸载字符设备驱动 */
    94         unregister_chrdev(major, "myled");
    95         class_device_unregister(led_class_dev);
    96         class_destroy(led_class);
    97
    98         /* 释放虚拟地址映射 */
    99         iounmap(gpioctl);
    100
    101         return 0;
    102 }
    103
    104 struct platform_driver led_drv = {
    105         .probe         = led_probe,
    106         .remove = led_remove,
    107         .driver = {
    108                 .name         = "myled",//与dev保持一致
    109         }
    110 };
    111
    112 static int led_drv_init(void)
    113 {
    114         platform_driver_register(&led_drv);
    115         return 0;
    116 }
    117
    118 static void led_drv_exit(void)
    119 {
    120         platform_driver_unregister(&led_drv);
    121         return;
    122 }
    123
    124 module_init(led_drv_init);
    125 module_exit(led_drv_exit);
    126 MODULE_LICENSE("GPL");

       

    app.c

    1 #include <sys/types.h>
    2 #include <sys/stat.h>
    3 #include <fcntl.h>
    4 #include <stdio.h>
    5
    6 int main (int argc, char **argv)
    7 {
    8         int fd;
    9         int val = 1;
    10         char *filename;
    11         
    12         printf("test app! ");
    13         if (argc != 3)
    14         {
    15                 printf("Usage: led<on|off> ");
    16                 return -1;
    17         }
    18         
    19         filename = argv[1];
    20         
    21         printf("filename: %s ", filename);
    22         
    23         fd = open(filename, O_RDWR);
    24         if(fd < 0)
    25         {
    26                 printf("open failed!---%d--- ", fd);
    27                 return -1;
    28         }
    29         
    30         //if (argv[2] == "on")
    31         if (!strcmp("on", argv[2]))
    32         {
    33                 val = 1;
    34                 write(fd, &val, 4);
    35         }
    36         //else if(argv[2] == "off")
    37         else if(!strcmp("off", argv[2]))
    38         {        
    39                 val = 0;
    40                 write(fd, &val, 4);
    41         }
    42         return 0;        
    43 }

       

    Makefile

    1 KERN_DIR = /work/system/linux-2.6.22.6
    2
    3 all:
    4         make -C $(KERN_DIR) M=`pwd` modules
    5

    6 clean:
    7         make -C $(KERN_DIR) M=`pwd` modules clean
    8
            rm -rf modules.order

    9
    10 obj-m += led_drv.o
    11 obj-m += led_dev.o

  • 相关阅读:
    H5应用加固防破解-js虚拟机保护方案浅谈
    Hijack chrome browser
    端口复用正向后门
    Django框架的一些漏洞
    07_简单的LISP加减乘除(基本计算器)
    git error:invalid path问题解决(win下)
    配置win10支持文件夹内区分大小写
    win10启用自带ubuntu虚拟机并升级至wsl2
    【进程调度】关于CPU的sockets、dies、cores、threads含义理解
    06_最长回文子串长度
  • 原文地址:https://www.cnblogs.com/lilto/p/11878034.html
Copyright © 2011-2022 走看看