Chinaunix首页 | 论坛 | 博客
  • 博客访问: 752048
  • 博文数量: 98
  • 博客积分: 4934
  • 博客等级: 上校
  • 技术积分: 1151
  • 用 户 组: 普通用户
  • 注册时间: 2009-06-12 19:55
文章分类

全部博文(98)

文章存档

2014年(1)

2013年(2)

2012年(4)

2011年(25)

2010年(33)

2009年(33)

分类: 嵌入式

2012-09-27 14:25:56

手上有一个android开发平台,于是想在底层加个自己的硬件模块然后通过Android的HAL方式向上封装出底层驱动供JAVA APP调用。既然是刚上手,那就用led灯来做为先导开发走走流程吧,至少得把从内核到应用层的流程走通才行。
 
 
从底层到上层一共分成四个阶段。
1: 内核硬件驱动层
2: HAL(硬件抽象层)
3: 框架层(framework,包含JNI和实现硬件服务的JAVA接口)
4: JAVA应用层
 
 
 
一,首先是第一层,内核硬件驱动层
    在kernel\driver\下新建一个目录swt,在swt下再新建led文件夹,并新建swtled.c swtled.h,通过注册模块方式,实现ioctl,write,read接口。之后通过设备名给上层访问。
    swtled.c部分
   

点击(此处)折叠或打开

  1. #include <linux/kernel.h>
  2. #include <linux/sched.h>
  3. #include <linux/timer.h>
  4. #include <linux/init.h>
  5. #include <linux/module.h>
  6. #include <linux/uaccess.h>
  7. #include <linux/gpio.h>
  8. #include <linux/cdev.h>
  9. #include <linux/fs.h>
  10. #include <linux/device.h>
  11. #include <linux/miscdevice.h>
  12. #include <linux/watchdog.h>
  13. #include <linux/fs.h>

  14. #include <asm/io.h>
  15. #include <mach/gpio.h>
  16. #include <asm/uaccess.h>


  17. #define LED_ON _IO ('k',1)
  18. #define LED_OFF _IO ('k',2)


  19. struct light_dev
  20. {
  21.     struct cdev cdev;
  22.     
  23.     unsigned char value;
  24. };

  25. static struct light_dev *light_devp;
  26. static struct class * light_class = NULL;


  27. int light_major = 250;

  28. #if 0


  29. static ssize_t light_val_show(struct device* dev, struct device_attribute* attr, char* buf)
  30. {
  31.     return 0;
  32. }

  33. static ssize_t light_val_store(struct device* dev, struct device_attribute* attr, const char* buf, size_t count)
  34. {
  35.     return 0;
  36. }


  37. static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, light_val_show, light_val_store);

  38. #endif

  39. void led_off(int arg)
  40. {
  41.     switch(arg)
  42.     {
  43.         case 1: gpio_set_value(RK29_PIN6_PB3,GPIO_LOW); //GPIO8
  44.         break;

  45.         case 2: gpio_set_value(RK29_PIN6_PC2,GPIO_LOW); //GPIO10
  46.         break;

  47.         default:
  48.         break;
  49.     }
  50. }

  51. void led_on(int arg)
  52. {
  53.     switch(arg)
  54.     {
  55.         case 1: gpio_set_value(RK29_PIN6_PB3,GPIO_HIGH);
  56.         break;

  57.         case 2: gpio_set_value(RK29_PIN6_PC2,GPIO_HIGH);
  58.         break;

  59.         default:
  60.         break;
  61.     }
  62. }


  63. int light_open(struct inode *inode, struct file *filp)
  64. {
  65.     struct light_dev *dev;

  66.     int ret = 0;

  67.     printk(KERN_ALERT"light_open()");
  68.     

  69.     dev = container_of(inode->i_cdev, struct light_dev, cdev);

  70.     filp->private_data = dev;

  71.     ret = gpio_request(RK29_PIN6_PB3, NULL);

  72.         if(ret != 0)
  73.         {
  74.             gpio_free(RK29_PIN6_PB3);
  75.         }
  76.         gpio_direction_output(RK29_PIN6_PB3, 0);

  77.         ret = gpio_request(RK29_PIN6_PC2, NULL);

  78.         if(ret != 0)
  79.         {
  80.             gpio_free(RK29_PIN6_PC2);
  81.         }
  82.         gpio_direction_output(RK29_PIN6_PC2, 0);



  83.     return 0;
  84. }

  85. int light_release(struct inode *inode, struct file *filp)
  86. {
  87.     printk(KERN_ALERT"light_release()");
  88.     
  89.     return 0;
  90. }



  91. ssize_t light_read(struct file *filp, char __user *buf, size_t count, loff_t*f_pos)
  92. {
  93.     struct light_dev *dev = filp->private_data;

  94.     printk(KERN_ALERT"light_read()");

  95.     if (copy_to_user(buf, &(dev->value), 1))
  96.     {
  97.         return -EFAULT;
  98.     }
  99.     
  100.     return 1;
  101. }

  102. ssize_t light_write(struct file *filp, const char __user *buf, size_t count, loff_t *f_pos)
  103. {
  104.     struct light_dev *dev = filp->private_data;

  105.     printk(KERN_ALERT"light_write()");
  106.     
  107.     if (copy_from_user(&(dev->value), buf, 1))
  108.     {
  109.         return -EFAULT;
  110.     }
  111.     


  112.     if (dev->value == 1)
  113.         printk(KERN_ALERT"LED on");
  114.     else
  115.         printk(KERN_ALERT"LED off");
  116.     return 1;
  117. }


  118. int light_ioctl(struct inode    *inode, struct file *filp, unsigned int cmd, unsigned long arg)
  119. {
  120.     struct light_dev *dev = filp->private_data;

  121.     printk(KERN_ALERT"light_ioctl(cmd = %d)", cmd);
  122.     
  123.     switch (cmd)
  124.         {
  125.             case LED_ON:
  126.                 led_on(arg);
  127.                 break;
  128.             case LED_OFF:
  129.                 led_off(arg);
  130.                 break;
  131.             default: break;
  132.         }

  133.     
  134.     return 0;
  135. }

  136. struct file_operations light_fops =
  137. {
  138.     .owner = THIS_MODULE,
  139.     .read = light_read,
  140.     .write = light_write,
  141.     .ioctl = light_ioctl,
  142.     .open = light_open,
  143.     .release = light_release,
  144. };

  145. static int light_setup_cdev(struct light_dev *dev, int index)
  146. {
  147.     int err, devno = MKDEV(light_major, index);
  148.     cdev_init(&dev->cdev, &light_fops);
  149.     dev->cdev.owner = THIS_MODULE;
  150.     dev->cdev.ops = &light_fops;
  151.     dev->value = 0;
  152.     err = cdev_add(&dev->cdev, devno, 1);

  153.     return err;
  154. }



  155. int light_init(void)
  156. {
  157.     int result = 0;
  158.     
  159.     struct device * temp = NULL;    

  160.     dev_t dev = MKDEV(light_major, 0);
  161.         
  162.     printk(KERN_ALERT"light_init()");


  163.     
  164.     if (light_major) {
  165.         result = register_chrdev_region(dev, 1, "LED");
  166.     }
  167.     else {
  168.         result = alloc_chrdev_region(&dev, 0, 1, "LED");

  169.         light_major = MAJOR(dev);
  170.     }
  171.     
  172.     if (result < 0) {
  173.         goto failed;
  174.     }
  175.     

  176.     
  177.     light_devp = kmalloc(sizeof(struct light_dev), GFP_KERNEL);    
  178.     if (!light_devp){    
  179.         result = -ENOMEM;        
  180.         goto unregister;
  181.     }
  182.     
  183.     memset(light_devp, 0, sizeof(struct light_dev));
  184.     
  185.     result = light_setup_cdev(light_devp, 0);
  186.     if(result) {
  187.         goto cleanup;
  188.     }


  189.     
  190.     light_class = class_create(THIS_MODULE, "led");
  191.     if(IS_ERR(light_class)) {
  192.         printk(KERN_ALERT"Failed to create light class./n");
  193.         goto destroy_cdev;    
  194.     }        
  195.     

  196.     
  197.     temp = device_create(light_class, NULL, dev, "%s", "swtled");
  198.     if(IS_ERR(temp)) {    
  199.         printk(KERN_ALERT"Failed to create hello device.");
  200.         goto destroy_class;     
  201.     }

  202. #if 0

  203.     
  204.     result = device_create_file(temp, &dev_attr_val);
  205.     if(result < 0) {
  206.      printk(KERN_ALERT"Failed to create attribute val.");
  207.      goto destroy_device;
  208.     }

  209.     dev_set_drvdata(temp, light_devp);
  210. #endif    
  211.     

  212.     
  213.     return 0;

  214. destroy_device:
  215.     device_destroy(light_class, dev);
  216.   
  217. destroy_class:    
  218.     class_destroy(light_class);
  219.   
  220. destroy_cdev:
  221.     cdev_del(&(light_devp->cdev));

  222. cleanup:
  223.         kfree(light_devp);
  224.         
  225. unregister:

  226.     unregister_chrdev_region(dev, 1);
  227.     
  228. failed:

  229.     printk(KERN_ALERT"light_init failed.");
  230.     
  231.     
  232. return result;

  233. }


  234. void light_cleanup(void)
  235. {
  236.     printk(KERN_ALERT"light_cleanup()");


  237.     
  238.     if(light_class) {
  239.         device_destroy(light_class, MKDEV(light_major, 0));
  240.         class_destroy(light_class);
  241.     }
  242.   

  243.     if(light_devp) {
  244.         cdev_del(&light_devp->cdev);
  245.         kfree(light_devp);
  246.     }
  247.     
  248.     unregister_chrdev_region(MKDEV(light_major, 0), 1);
  249.     
  250. }

  251. module_init(light_init);
  252. module_exit(light_cleanup);


  253. MODULE_LICENSE("GPL");
  254. MODULE_DESCRIPTION("led driver");
  255. MODULE_ALIAS("led module");
led文件夹中Kconfig文件

点击(此处)折叠或打开

  1. config SWT_XXX_LED
  2.     bool "swt led"
  3.     default n
  4.     help
  5.      This compiles in support for the led of xxx.
led文件夹中MakeFile文件


点击(此处)折叠或打开

  1. obj-$(CONFIG_SWT_XXX_LED)+=swt_led.o
swtled文件中Kconfig文件

点击(此处)折叠或打开

  1. menu "swtled Drivers"

  2. source "drivers/swt/led/Kconfig"

  3. endmenu
swtled文件夹中MakeFile文件

点击(此处)折叠或打开

  1. obj-y += led/
接下来,就要修改kernel/driver下的MakeFile和Kconfig文件了,在分别其中添加一句
 
MakeFile文件

点击(此处)折叠或打开

  1. obj-y += swt/
Kconfig文件

点击(此处)折叠或打开

  1. source "drivers/swt/Kconfig"
保存所有之后,执行make
编译成功后,就可以在swt/led目录下看到swtled.o文件了,这时候编译出来的img已经包含了swtled驱动了





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