Chinaunix首页 | 论坛 | 博客
  • 博客访问: 98173
  • 博文数量: 38
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 384
  • 用 户 组: 普通用户
  • 注册时间: 2014-04-06 16:52
文章分类

全部博文(38)

文章存档

2014年(38)

我的朋友

分类: 嵌入式

2014-05-07 17:02:30

1.分层和分离的概念的示意图
                  App

--------------------------------------------------
                 input.c
--------------------------------------------------分层
           /                  \
          /                    \
         /        分离          \
    button.c    < ===== >     evdev.c
    硬件相关                  纯软件(稳定)

2.bus_drv_dev模型
                     bus
--------------------------------------------------
            /                  \
  device_add/                    \ driver_register
          /        分离          \
     devices      < ===== >      driver
     硬件相关                    比较稳定的代码

device_add:  1.把device放入bus的dev链表   
              2.从bus的drv链表取出每一个drv        
                用bus的match函数判断drv能否支持dev  
              3.若可以支持,调用drv的probe函数

driver_register: 1.把driver放入bus的drv链表   
                 2.从bus的dev链表取出每一个dev        
                   用bus的match函数判断dev能否支持drv  
                 3.若可以支持,调用probe函数

注意:这只不过是一种左右建立联系的机制,devices和drivers都只不过是结构体而已

3.led驱动的分层分离实例
    led_dev.c代码如下

点击(此处)折叠或打开

  1. //moudle.h 包含了大量加载模块需要的函数和符号的定义
  2. #include <linux/module.h>
  3. //kernel.h以便使用printk()等函数
  4. #include <linux/kernel.h>
  5. //fs.h包含常用的数据结构,如struct file等
  6. #include <linux/fs.h>
  7. //uaccess.h 包含copy_to_user(),copy_from_user()等函数
  8. #include <linux/uaccess.h>
  9. //io.h 包含inl(),outl(),readl(),writel()等IO口操作函数
  10. #include <linux/io.h>
  11. #include <linux/miscdevice.h>
  12. #include <linux/pci.h>
  13. //init.h来指定你的初始化和清理函数,例如:module_init(init_function)、module_exit(cleanup_function)
  14. #include <linux/init.h>
  15. #include <linux/delay.h>
  16. #include <linux/device.h>
  17. #include <linux/cdev.h>
  18. #include <linux/gpio.h>
  19. #include <linux/irq.h>
  20. #include <linux/sched.h>
  21. #include <linux/interrupt.h>
  22. #include <linux/poll.h>
  23. #include <linux/input.h>
  24. #include <linux/pm.h>
  25. #include <linux/sysctl.h>
  26. #include <linux/proc_fs.h>
  27. #include <linux/platform_device.h>
  28. #include <linux/version.h>
  29. #include <linux/types.h>
  30. #include <linux/list.h>
  31. #include <linux/timer.h>
  32. #include <linux/serial_core.h>

  33. //irq.h中断与并发请求事件
  34. #include <asm/irq.h>
  35. //下面这些头文件是IO口在内核的虚拟映射地址,涉及IO口的操作所必须包含
  36. //#include <mach/gpio.h>
  37. #include <mach/regs-gpio.h>
  38. #include <plat/gpio-cfg.h>
  39. #include <mach/hardware.h>
  40. #include <mach/map.h>


  41. /* 分配/设置/注册一个platform_device */

  42. static struct resource led_resource[] = {
  43.     /*寄存器地址*/
  44.     [0] = {
  45.         .start = 0x7F008820,
  46.         .end = 0x7F008820 + 8 - 1,
  47.         .flags = IORESOURCE_MEM,
  48.     },
  49.     /*哪一位*/
  50.     [1] = {
  51.         .start = 0,
  52.         .end = 0,
  53.         .flags = IORESOURCE_IRQ,
  54.     }    
  55. };

  56. static void led_release(struct device * dev)
  57. {
  58. }

  59. static struct platform_device led_dev = {
  60.     .name = "myled",
  61.     .id      = -1,
  62.     .num_resources = ARRAY_SIZE(led_resource),
  63.     .resource = led_resource,
  64.     .dev = {
  65.         .release = led_release,
  66.     },
  67. };

  68. static int led_dev_init(void)
  69. {
  70.     platform_device_register(&led_dev);
  71.     return 0;
  72. }

  73. static void led_dev_exit(void)
  74. {
  75.     platform_device_unregister(&led_dev);
  76. }

  77. module_init(led_dev_init);
  78. module_exit(led_dev_exit);

  79. MODULE_LICENSE("GPL");

    led_drv.c代码如下

点击(此处)折叠或打开

  1. //moudle.h 包含了大量加载模块需要的函数和符号的定义
  2. #include <linux/module.h>
  3. //kernel.h以便使用printk()等函数
  4. #include <linux/kernel.h>
  5. //fs.h包含常用的数据结构,如struct file等
  6. #include <linux/fs.h>
  7. //uaccess.h 包含copy_to_user(),copy_from_user()等函数
  8. #include <linux/uaccess.h>
  9. //io.h 包含inl(),outl(),readl(),writel()等IO口操作函数
  10. #include <linux/io.h>
  11. #include <linux/miscdevice.h>
  12. #include <linux/pci.h>
  13. //init.h来指定你的初始化和清理函数,例如:module_init(init_function)、module_exit(cleanup_function)
  14. #include <linux/init.h>
  15. #include <linux/delay.h>
  16. #include <linux/device.h>
  17. #include <linux/cdev.h>
  18. #include <linux/gpio.h>
  19. #include <linux/irq.h>
  20. #include <linux/sched.h>
  21. #include <linux/interrupt.h>
  22. #include <linux/poll.h>
  23. #include <linux/input.h>
  24. #include <linux/pm.h>
  25. #include <linux/sysctl.h>
  26. #include <linux/proc_fs.h>
  27. #include <linux/platform_device.h>

  28. //irq.h中断与并发请求事件
  29. #include <asm/irq.h>
  30. //下面这些头文件是IO口在内核的虚拟映射地址,涉及IO口的操作所必须包含
  31. //#include <mach/gpio.h>
  32. #include <mach/regs-gpio.h>
  33. #include <plat/gpio-cfg.h>
  34. #include <mach/hardware.h>
  35. #include <mach/map.h>


  36. static int major;
  37. static struct class *cls;
  38. static volatile unsigned long *gpio_con;
  39. static volatile unsigned long *gpio_dat;
  40. static int pin;

  41. static int led_open(struct inode *inode, struct file *file)
  42. {
  43.     /* 配置为输出 */
  44.     *gpio_con &= ~(0xE<<(pin*4));

  45.     return 0;    
  46. }

  47. static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
  48. {
  49.     int val;

  50.     if( copy_from_user(&val, buf, count) ) //    copy_to_user();
  51.         return -EFAULT;

  52.     if (val == 1)
  53.     {
  54.         // 点灯
  55.         *gpio_dat &= ~(1<<pin);
  56.     }
  57.     else
  58.     {
  59.         // 灭灯
  60.         *gpio_dat |= (1<<pin);
  61.     }
  62.     
  63.     return 0;
  64. }


  65. static struct file_operations led_fops = {
  66.     .owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
  67.     .open = led_open,
  68.     .write    = led_write,    
  69. };

  70. static int led_probe(struct platform_device *pdev)
  71. {
  72.     struct resource        *res;

  73.     /* 根据platform_device的资源进行ioremap */
  74.     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  75.     gpio_con = ioremap(res->start, res->end - res->start + 1);
  76.     gpio_dat = gpio_con + 1;

  77.     res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
  78.     pin = res->start;

  79.     /* 注册字符设备驱动程序 */

  80.     printk("led_probe, found led\n");

  81.     major = register_chrdev(0, "myled", &led_fops);

  82.     cls = class_create(THIS_MODULE, "myled");

  83.     device_create(cls, NULL, MKDEV(major, 0), NULL, "led"); /* /dev/led */
  84.     
  85.     return 0;
  86. }

  87. static int led_remove(struct platform_device *pdev)
  88. {
  89.     /* 卸载字符设备驱动程序 */
  90.     /* iounmap */
  91.     printk("led_remove, remove led\n");

  92.     device_destroy(cls, MKDEV(major, 0));
  93.     class_destroy(cls);
  94.     unregister_chrdev(major, "myled");
  95.     iounmap(gpio_con);
  96.     
  97.     printk("led_removed!\n");
  98.     
  99.     return 0;
  100. }


  101. struct platform_driver led_drv = {
  102.     .probe        = led_probe,
  103.     .remove        = led_remove,
  104.     .driver        = {
  105.         .name    = "myled",
  106.     }
  107. };


  108. static int led_drv_init(void)
  109. {
  110.     platform_driver_register(&led_drv);
  111.     return 0;
  112. }

  113. static void led_drv_exit(void)
  114. {
  115.     platform_driver_unregister(&led_drv);
  116. }

  117. module_init(led_drv_init);
  118. module_exit(led_drv_exit);

  119. MODULE_LICENSE("GPL");

    测试程序代码如下

点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <sys/stat.h>
  3. #include <fcntl.h>
  4. #include <stdio.h>

  5. int main(int argc, char **argv)
  6. {
  7.     int fd;
  8.     int val = 1;
  9.     fd = open("/dev/led", O_RDWR);
  10.     if (fd < 0)
  11.     {
  12.         printf("can't open!\n");
  13.     }
  14.     if (argc != 2)
  15.     {
  16.         printf("Usage :\n");
  17.         printf("%s \n", argv[0]);
  18.         return 0;
  19.     }

  20.     if (strcmp(argv[1], "on") == 0)
  21.     {
  22.         val = 1;
  23.     }
  24.     else
  25.     {
  26.         val = 0;
  27.     }
  28.     
  29.     write(fd, &val, 4);
  30.     return 0;
  31. }

  测试:insmod led_drv.ko
        insmod led_dev.ko
        ./led_test on
        ./led_test off
    要修改哪个led只需修改led_dev.c中的led_resource[]的位就行了
阅读(1133) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~