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

全部博文(100)

文章存档

2017年(1)

2016年(16)

2015年(83)

我的朋友

分类: 嵌入式

2015-06-25 15:55:41

led_cdev.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/cdev.h>

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

  18. #define LED_MAJOR 0

  19. static struct gpio leds_gpios[] = {
  20.     { S5PV210_GPC0(3), GPIOF_OUT_INIT_LOW, "LED1" }, /* 默认为输出 */
  21.     { S5PV210_GPC0(4),GPIOF_OUT_INIT_LOW, "LED2" } /* 默认为输出 */
  22. };

  23. static struct class *firstdrv_class;
  24. static struct device *firstdrv_class_dev;

  25. static int first_led_open(struct inode *inode, struct file *file)
  26. {
  27.     printk("first_drv_open\n");
  28.     return 0;
  29. }

  30. static ssize_t first_led_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)
  31. {
  32.     int val;
  33.     int ret;
  34.     printk("first_drv_write\n");
  35.     ret = copy_from_user(&val, buf, count); //    copy_to_user();
  36.     if(ret)
  37.     {
  38.      printk("copy_from_user error\n");
  39.      return -EFAULT;
  40.     }
  41.     if (val == 1)
  42.     {
  43.         gpio_set_value( S5PV210_GPC0(3), 1);
  44.         gpio_set_value( S5PV210_GPC0(4), 1);
  45.     }
  46.     else
  47.     {
  48.         gpio_set_value( S5PV210_GPC0(3), 0);
  49.         gpio_set_value( S5PV210_GPC0(4), 0);
  50.     }
  51.     return 0;
  52. }

  53. static struct file_operations first_led_fops = {
  54.     .owner = THIS_MODULE,
  55.     .open = first_led_open,
  56.     .write    =    first_led_write,    
  57. };

  58. int major = 0;
  59. dev_t devid;
  60. struct cdev led_dev;
  61. static int __init first_led_init(void)
  62. {
  63.     int err;
  64. #if    0
  65.     major = register_chrdev(0, "led_cdev", &first_led_fops);
  66. #else
  67.     /* 1. 分配设备号 */
  68.     if(major){
  69.         devid = MKDEV(major,0);
  70.         major = MAJOR(devid);
  71.         err = register_chrdev_region(devid,0,"led_cdev");//向系统注册一个已知的设备编号
  72.     }
  73.     else{
  74.         printk("-> alloc_chrdev_region\n");
  75.         err = alloc_chrdev_region(&devid,0,1,"led_cdev");//申请编号,主设备动态分配,次设备号为0,范围1,申请到的主设备号存放在devid中
  76.     }
  77.     
  78.     if(err){
  79.         printk(KERN_WARNING "led:can't get major %d\n",LED_MAJOR);
  80.         return err;
  81.     }
  82.     /* 2. 根据设备号注册设备 */
  83.     led_dev.owner = THIS_MODULE;
  84.     cdev_init(&led_dev, &first_led_fops);//构造字符设备结构体cdev led_dev
  85.     err = cdev_add(&led_dev,devid,1); //cdev_add(&led_dev,dev_t,count),注册字符设备
  86.     if(err){
  87.         printk("cdev_add error !");
  88.         return err;
  89.     }
  90. #endif
  91.     /* 3. 建立设备节点,用deice_create自动创建 */
  92.     //MKDEV将主设备号和次设备号转为dev_t类型
  93.     //device_create创建设备信息,udev会自动根据设备信息创建设备节点/dev/xyz,应用程序根据设备节点(路径)访问设备
  94.     //linux 3.10中,class_device_create替换为device_create
  95.     //major = MAJOR(devid);//提取申请到的主设备号
  96.     firstdrv_class = class_create(THIS_MODULE,"class_led_cdev");
  97.     firstdrv_class_dev = device_create(firstdrv_class, NULL,devid, NULL, "xyz");
  98.     
  99.     err = gpio_request_array(leds_gpios, ARRAY_SIZE(leds_gpios));//申请GPIO
  100.     if (err){
  101.      printk("gpio_request_array error\n");
  102.      return -EFAULT;
  103.     }
  104.     printk("led initialize\n");
  105.     return 0;
  106. }

  107. static void __exit first_led_exit(void)
  108. {
  109.     printk("first_led_exit\n");
  110.     gpio_free_array(leds_gpios, ARRAY_SIZE(leds_gpios));//释放GPIO
  111. #if 0
  112.     unregister_chrdev(major, "led_cdev");
  113. #else
  114.     unregister_chrdev_region(devid, 1);//释放设备编号unregister_chrdev_region(dev_t from, unsigned count)
  115.     cdev_del(&led_dev); //删除字符设备
  116. #endif
  117.     device_unregister(firstdrv_class_dev);//linux 3.10中,class_device_unregister替换为device_unregister
  118.     class_destroy(firstdrv_class);
  119. }

  120. module_init(first_led_init);
  121. module_exit(first_led_exit);

  122. MODULE_LICENSE("GPL");


ledtest.c:


点击(此处)折叠或打开

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

  5. /* firstdrvtest on
  6.   * firstdrvtest off
  7.   */
  8. int main(int argc, char **argv)
  9. {
  10.     int fd;
  11.     int val = 1;
  12.     fd = open("/dev/xyz", 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 <on|off>\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_cdev.o
  3. all:
  4. make -C $(KERN_DIR) M=`pwd` modules
  5. clean:
  6. rm -rf *.ko *.mod.c *.mod.o *.o *.order *.symvers *.cmd .*.o.* .*.ko.*

具体代码分析可参考LDD3或者宋宝华老师书籍或者韦东山的视频
阅读(1885) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~