• 驱动的分离分层设计——按键点灯


    源码附带注释:

    key_dev.c

     1 #include <linux/module.h>
     2 #include <linux/kernel.h>
     3 #include <linux/fs.h>
     4 #include <linux/init.h>
     5 #include <linux/delay.h>
     6 #include <linux/irq.h>
     7 #include <asm/irq.h>
     8 #include <asm/io.h>
     9 #include <linux/cdev.h>
    10 #include <linux/device.h>
    11 #include <linux/interrupt.h>
    12 #include <linux/input.h>
    13 #include <linux/bitmap.h>
    14 #include <asm/gpio.h>
    15 #include <linux/platform_device.h>
    16 
    17 /*记录硬件相关资源*/
    18 static struct resource key_rsrc[] = {  
    19     [0] = {      /*内存空间*/
    20         .start = 0x56000050,
    21         .end   = 0x56000050 + 8 -1,
    22         .flags = IORESOURCE_MEM
    23     },
    24     [1] = {
    25          /*GPF4,5,6*/
    26         .start = 4,    
    27         .end   = 6,
    28         .flags = IORESOURCE_IO   //flag随便取个什么,按照自己的想法来就行了
    29     }
    30 };
    31 
    32 static struct platform_device key_dev = {
    33     .name           = "key_led",
    34     .num_resources  = ARRAY_SIZE(key_rsrc),
    35     .resource       = key_rsrc
    36 };
    37 
    38 /*之所以要平台设备要注册进内核,是因为待会平台设备要根据平台name找到相应的设备
    39 *然后获得硬件相关的资源
    40 */
    41 static int key_dev_init(void)
    42 {
    43    /*注册*/
    44    platform_device_register(&key_dev);
    45    return 0;
    46 }
    47 
    48 static void key_dev_exit(void)
    49 {
    50     platform_device_unregister(&key_dev);
    51 }
    52 
    53 module_init(key_dev_init);
    54 module_exit(key_dev_exit);
    55 
    56 MODULE_LICENSE("GPL");
    57 MODULE_AUTHOR("1653699780@qq.com");

    key_drv.c

      1 #include <linux/module.h>
      2 #include <linux/kernel.h>
      3 #include <linux/fs.h>
      4 #include <linux/init.h>
      5 #include <linux/delay.h>
      6 #include <linux/irq.h>
      7 #include <asm/irq.h>
      8 #include <asm/io.h>
      9 #include <linux/cdev.h>
     10 #include <linux/device.h>
     11 #include <linux/interrupt.h>
     12 #include <linux/input.h>
     13 #include <linux/bitmap.h>
     14 #include <asm/gpio.h>
     15 #include <linux/platform_device.h>
     16 
     17 static volatile unsigned long *gpfcon;
     18 static volatile unsigned long *gpfdat;
     19 
     20 static struct timer_list key_time;
     21 
     22 static struct class *key_class;
     23 
     24 struct input_inode {
     25             char *name;
     26             unsigned int irq_type;
     27             unsigned int pin;
     28             unsigned int key_num;
     29 };
     30 
     31 static struct input_inode *irq_pd;
     32 static struct resource *key_resource;
     33 static struct resource *pin_resource;
     34 
     35 static struct input_inode key[] = {
     36                  [0] = {
     37                          "EINT0",
     38                          IRQ_EINT0,
     39                          S3C2410_GPF(0),
     40                          0},
     41                  [1] = {
     42                         "EINT2",
     43                          IRQ_EINT2,
     44                          S3C2410_GPF(2),
     45                          1},
     46                  [2] = {
     47                         "EINT11",
     48                         IRQ_EINT11,
     49                         S3C2410_GPG(3),
     50                         2},
     51 };
     52 
     53 static irqreturn_t key_irq(int irq, void *dev_id)
     54 {
     55      irq_pd = (struct input_inode *)dev_id;
     56      mod_timer(&key_time,jiffies + HZ/100); //延迟10ms,延迟过程中断仍然可以被触发
     57       
     58       return IRQ_HANDLED;
     59 }
     60 
     61 static void key_time_function(unsigned long data)
     62 {
     63      unsigned int key_val;
     64      unsigned int pin_num;
     65      
     66      if(!irq_pd)
     67          return;
     68 
     69      key_val = s3c2410_gpio_getpin(irq_pd->pin);
     70      pin_num = pin_resource->start + irq_pd->key_num;
     71      
     72      if(key_val){
     73          
     74         (*gpfdat) |= (1<<pin_num);
     75         
     76      }else{
     77      
     78         (*gpfdat) &= ~(1<<pin_num);
     79         
     80      }
     81 }
     82 
     83 int key_open(struct inode *inode, struct file *file)
     84 {
     85     int i;
     86     int pin_num;
     87     pin_num = pin_resource->end - pin_resource->start + 1;
     88     /*配置输出引脚*/
     89     for(i = 0; i < pin_num; i++){
     90         *gpfcon &= ~(3<<((pin_resource->start + i)* 2));
     91         *gpfcon |= (1<<((pin_resource->start + i)* 2));
     92     }
     93     
     94     return 0;
     95 }
     96 
     97 int key_release(struct inode * inode, struct file * file)
     98 {
     99      return 0;
    100 }
    101 
    102 static int major;
    103 
    104 static struct file_operations key_fops = {
    105            .owner   = THIS_MODULE,
    106            .open    = key_open,
    107            .release = key_release,
    108 };
    109            
    110 //驱动分离适合用probe函数
    111 static int key_probe(struct platform_device *pdev) //需要枚举找到设备里面同名的pdev
    112 {
    113     int i;
    114     int error;
    115      /*获得设备里面的硬件资源*/
    116     major = register_chrdev(0,"led_key",&key_fops); //cat /proc/devices 出现led_key
    117     key_class = class_create(THIS_MODULE,"key");
    118     device_create(key_class,NULL,MKDEV(major,0),NULL,"key0_led"); //次设备号0,/dev/key0_led
    119     
    120     key_resource = platform_get_resource(pdev, IORESOURCE_MEM,0);
    121     gpfcon = ioremap(key_resource->start,key_resource->end-key_resource->start + 1);
    122     gpfdat = gpfcon +1;
    123 
    124     pin_resource = platform_get_resource(pdev, IORESOURCE_IO,0);
    125     
    126     for(i = 0; i < 3; i++){
    127         error = request_irq(key[i].irq_type,key_irq,IRQ_TYPE_EDGE_BOTH,key[i].name,&key[i]);
    128         if(error){
    129           printk("couldn't get irq!
    ");
    130           return -1;
    131         }
    132     }
    133 
    134     init_timer(&key_time);
    135     key_time.function = key_time_function;
    136     add_timer(&key_time);
    137 
    138     return 0;
    139 }
    140 
    141 static int __devexit key_remove(struct platform_device *pdev)
    142 {
    143     int i;
    144     del_timer(&key_time);
    145     for(i = 0; i < 3; i++){
    146       free_irq(key[i].irq_type,&key[i]);
    147     }
    148     unregister_chrdev(major,"led_key");
    149     class_destroy(key_class);
    150     device_destroy(key_class, MKDEV(major,0));
    151     return 0;
    152 }
    153 
    154 static struct platform_driver key_driver = {
    155     .driver = {
    156         .name    = "key_led",
    157         .owner    = THIS_MODULE,
    158     },
    159     .probe    = key_probe,
    160     .remove    = __devexit_p(key_remove),
    161 };
    162 
    163 static int key_drv_init(void)
    164 {
    165     /*注册*/
    166     platform_driver_register(&key_driver);
    167     return 0;
    168 }
    169 
    170 static void key_drv_exit(void)
    171 {
    172     platform_driver_unregister(&key_driver);
    173 }
    174 
    175 module_init(key_drv_init);
    176 module_exit(key_drv_exit);
    177 
    178 MODULE_LICENSE("GPL");
    179 MODULE_AUTHOR("1653699780@qq.com");
  • 相关阅读:
    C#里List.Sort的用法
    解决在IE中返回JSON格式的数据时提示下载的问题
    关于json语句的相关用法
    vector数组的相关知识
    编程珠矶第一章阅读笔记
    第三周学习进度博客
    echarts以地图形式显示中国疫情情况实现点击省份下钻
    课堂作业,疫情数据统计(柱形图的生成)
    过滤器filter学习进度一
    android开发对应高德地图定位服务进度一
  • 原文地址:https://www.cnblogs.com/zhu-g5may/p/9308808.html
Copyright © 2020-2023  润新知