Chinaunix首页 | 论坛 | 博客
  • 博客访问: 479589
  • 博文数量: 100
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 955
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-21 09:30
文章分类

全部博文(100)

文章存档

2017年(1)

2016年(16)

2015年(83)

我的朋友

分类: 嵌入式

2015-07-02 14:17:47

首先编写设备层:
led_device.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 <asm/uaccess.h>
  7. #include <asm/irq.h>
  8. #include <asm/io.h>
  9. #include <linux/device.h>//classcreate的定义
  10. #include <linux/gpio.h>//gpio结构体的定义
  11. #include <mach/regs-gpio.h>
  12. //linux 3.10内核的regs-gpio.h位置不再是<asm/arch/regs-gpio.h>
  13. #include <mach/hardware.h>
  14. #include <linux/platform_device.h>

  15. static struct resource led_resource[] = {
  16.      [0] = DEFINE_RES_MEM(0xE0200060, SZ_16), 
  17. };

  18. static void led_release(struct device * dev)
  19. {
  20. }

  21. static struct platform_device led_dev = {
  22.     .name = "s5pv210_led",
  23.     .id = -1,
  24.     .num_resources = ARRAY_SIZE(led_resource),
  25.     .resource = led_resource,
  26.     .dev = {
  27.         .release = led_release,
  28.     },
  29. };



  30. static int led_dev_init(void)
  31. {
  32.     platform_device_register(&led_dev);
  33.     return 0;
  34. }

  35. static void led_dev_exit(void)
  36. {
  37.     platform_device_unregister(&led_dev);
  38. }

  39. module_init(led_dev_init);
  40. module_exit(led_dev_exit);

  41. MODULE_LICENSE("GPL");
接下来写驱动层:
led_driver.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 <asm/uaccess.h>
  7. #include <asm/irq.h>
  8. #include <asm/io.h>
  9. #include <linux/device.h>//classcreate的定义
  10. #include <linux/gpio.h>//gpio结构体的定义
  11. #include <mach/regs-gpio.h>
  12. //linux 3.10内核的regs-gpio.h位置不再是<asm/arch/regs-gpio.h>
  13. #include <mach/hardware.h>
  14. #include <linux/platform_device.h>

  15. volatile unsigned long *gpc0con = NULL;
  16. volatile unsigned long *gpc0pud = NULL;
  17. volatile unsigned long *gpc0dat = NULL;

  18. static struct class *led_drv_class;
  19. static struct device *led_drv_class_dev;

  20. ///static volatile unsigned long *gpio_con;
  21. //static volatile unsigned long *gpio_dat;

  22. static int led_open(struct inode *inode, struct file *file)
  23. {
  24.     printk("led_drv_open\n");
  25.     
  26.     *gpc0con &= ~(0xf<<3*4);
  27.     *gpc0con |= (0x1<<3*4);//1为输出模式
  28.     *gpc0dat &= ~(0x1<<3);//gpc0_3
  29.     *gpc0dat |= (0x0<<3);//高电平亮
  30.     
  31.     return 0;
  32. }

  33. static ssize_t led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
  34. {

  35.     int val;
  36.     int ret;
  37.     printk("led_drv_write\n");
  38.     
  39.     ret = copy_from_user(&val, buf, count); //    copy_to_user();
  40.     if(ret)
  41.     {
  42.      printk("copy_from_user error\n");
  43.      return -EFAULT;
  44.     }
  45.     if (val == 1)
  46.     {
  47.         *gpc0dat &= ~(0x1<<3);//高电平亮
  48.         *gpc0dat |= (0x1<<3);
  49.     }
  50.     else
  51.     {
  52.         // gpc0dat = (*gpc0dat & ~(0x1<<3)) | (0x1<<3);
  53.         *gpc0dat &= ~(0x1<<3);//
  54.         *gpc0dat |= (0x0<<3);
  55.     }
  56.     
  57.     return 0;
  58. }

  59. static struct file_operations led_fops = {
  60.     .owner = THIS_MODULE,
  61.     .open = led_open,
  62.     .write    =    led_write,    
  63. };

  64. int major;
  65. static int led_probe(struct platform_device *pdev)
  66. {
  67.     struct resource        *res;
  68.     /* 根据platform_device的资源进行ioremap */
  69.     res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  70.     if(!res){
  71.         printk("get resource error\n");
  72.         return -1;
  73.     }
  74.     gpc0con = ioremap(res->start, res->end - res->start + 1);
  75.     gpc0dat = gpc0con + 1;

  76.     major = register_chrdev(0, "led_cdev", &led_fops);
  77.     led_drv_class = class_create(THIS_MODULE,"class_led_cdev");
  78.     led_drv_class_dev = device_create(led_drv_class, NULL,MKDEV(major, 0), NULL, "led");
  79.     //MKDEV将主设备号和次设备号转为dev_t类型
  80.     //device_create创建设备信息,udev会自动根据设备信息创建设备节点/dev/led,应用程序根据设备节点(路径)访问设备
  81.     //linux 3.10中,class_device_create替换为device_create
  82.     printk("led initialize\n");
  83.     return 0;
  84. }

  85. static int led_remove(struct platform_device *pdev)
  86. {
  87.     printk("led_drv_exit\n");
  88.     unregister_chrdev(major, "led_cdev");
  89.     device_unregister(led_drv_class_dev);//linux 3.10中,class_device_unregister替换为device_unregister
  90.     class_destroy(led_drv_class);
  91.     return 0;
  92. }

  93. struct platform_driver led_drv = {
  94.     .probe        = led_probe,
  95.     .remove        = led_remove,
  96.     .driver        = {
  97.         .owner    = THIS_MODULE,    /* 一定要加上这句,否则运行测试程序会出现段错误 */
  98.         .name    = "s5pv210_led",
  99.     }
  100. };

  101. static int __init led_drv_init(void)
  102. {
  103.     platform_driver_register(&led_drv);
  104.     return 0;
  105. }

  106. static void __exit led_drv_exit(void)
  107. {
  108.     platform_driver_unregister(&led_drv);
  109. }

  110. module_init(led_drv_init);
  111. module_exit(led_drv_exit);

  112. MODULE_LICENSE("GPL");
测试程序ledtest.c:

点击(此处)折叠或打开

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

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

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

点击(此处)折叠或打开

  1. KERN_DIR = /home/richard/work/kernel/linux-3.10.80
  2. obj-m += led_device.o led_driver.o

  3. all:
  4.     make -C $(KERN_DIR) M=`pwd` modules
  5.     arm-linux-gnueabi-gcc -o ledtest ledtest.c
  6. clean:
  7.     rm -rf *.ko *.mod.c *.mod.o *.o *.order *.symvers *.cmd .*.o.* .*.ko.*

cdev_add方式参考
http://blog.chinaunix.net/uid-30031530-id-5096590.html
https://blog.csdn.net/wangdapao12138/article/details/82193246





阅读(1725) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~