TQ210搭载Android4.0.3系统构建之LED从驱动到HAL到JNI到应用程序(HAL篇)

原帖地址:http://blog.csdn.net/undergrowth/article/details/9163491

 

开发板:TQ210

OS:Android 4.0.3

以下所有内容都是在TQ210开发板上实现,并且很多内容也是天嵌公司提供,我将一些内容进行了删减、替换,然后加入了一些自己的理解,同时也是记录自己学习的旅程。

HAL层头文件  放在hardware/libhardware/include/hardware/目录下

led_unders_led_hal.h

  1. #ifndef ANDROID_LED_UNDERS_H    //保证头文件只被加载一次  
  2. #define ANDROID_LED_UNDERS_H  
  3.   
  4. #include <hardware/hardware.h>  //包含hw_module_t hw_device_t hw_module_methods_t...  
  5. #include <stdint.h>  // 包含int long...  
  6. #include <sys/cdefs.h> //包含__begin_decls  
  7.   
  8. __BEGIN_DECLS  //按照C语言的方式编译和连接  
  9. #define LED_UNDERS_HARDWARE_MODULE_ID "led_unders"  //led_unders模块ID  
  10.   
  11. struct led_module_t   //led模块类型 ,继承hw_module_t  
  12. {  
  13.     struct hw_module_t common;  
  14. };  
  15.   
  16. struct led_control_device_t  //led设备类型,继承hw_device_t  
  17. {  
  18.     struct hw_device_t common;  
  19.     int (*led_on)(struct led_control_device_t *dev,int32_t number);  //打开led  
  20.     int (*led_off)(struct led_control_device_t *dev,int32_t number);//关闭led  
  21. };  
  22.   
  23. __END_DECLS  
  24.   
  25. #endif  

 

led_unders_led_hal.c

  1. #include <fcntl.h>  
  2. #include <stdio.h>  
  3. #include <stdlib.h> //包含malloc memset...  
  4. #include <android/log.h> //包含__android_log_print  
  5.   
  6. #include <hardware/hardware.h>  
  7. #include <hardware/led_unders_led_hal.h>  
  8.   
  9. #define DEV_FILE_NAME  "/dev/led_unders"   //设备文件名  
  10. #define IOCTL_GPIO_ON 1   //打开LED  
  11. #define IOCTL_GPIO_OFF 0 //关闭LED  
  12.   
  13. static int fd=-1;  //文件操作符  
  14.   
  15. static int open_led()  //打开LED  
  16. {  
  17.     fd=open(DEV_FILE_NAME,O_RDWR);  
  18.     if(fd<0)  
  19.         {  
  20.             __android_log_print(ANDROID_LOG_DEBUG,"msg","open_led failed.\n");  
  21.             return -1;  
  22.         }  
  23.     __android_log_print(ANDROID_LOG_DEBUG,"msg","open_led success.\n");  
  24.     return 0;  
  25. }  
  26.   
  27. static int close_led(struct hw_device_t *device) //关闭LED  
  28. {  
  29.     if(fd!=-1)  
  30.         {  
  31.             close(fd);  
  32.             fd=-1;  
  33.             if(device) free(device);  
  34.         }  
  35.     return 0;  
  36.   
  37. }  
  38.   
  39.   
  40. static int led_on(struct led_control_device_t *dev,int32_t number)  //点亮LED  
  41. {  
  42.     if(fd==-1) return -1;  
  43.     return ioctl(fd,IOCTL_GPIO_ON,number);  
  44. }  
  45.   
  46. static int led_off(struct led_control_device_t *dev,int32_t number) //关闭LED  
  47. {  
  48.     if(fd==-1) return -1;  
  49.     return ioctl(fd,IOCTL_GPIO_OFF,number);  
  50. }  
  51.   
  52. //led初始化函数  
  53. static int led_init(const struct hw_module_t *module,const char *name,struct hw_device_t **device)  
  54. {  
  55.     struct led_control_device_t *dev;  //定义led设备指针  
  56.     dev=(struct led_control_device_t *)malloc(sizeof(struct led_control_device_t)); //分配内存地址空间  
  57.     if(dev==NULL)   
  58.         {  
  59.         __android_log_print(ANDROID_LOG_DEBUG,"msg","malloc failed.\n");  
  60.         return 0;  
  61.         }  
  62.     memset(dev,0,sizeof(*dev)); //将内存块初始化为0  
  63.     dev->common.tag=HARDWARE_DEVICE_TAG;  //设备标志,由HWDT组成  
  64.     dev->common.version=0;  //设备版本  
  65.     dev->common.module=module; //指向设备所属于的模块  
  66.     dev->common.close=(int (*)(struct hw_device_t *))close_led; //关闭函数  
  67.   
  68.     *device=(struct hw_device_t *)&dev->common;   //指向设备  
  69.     dev->led_on=led_on;   //操作函数赋值  
  70.     dev->led_off=led_off;  
  71.   
  72.     if(open_led()==-1) //打开led设备  
  73.         {  
  74.             free(dev);  
  75.             dev=NULL;  
  76.             return -1;  
  77.         }  
  78.     return 0;  
  79. }  
  80.   
  81.   
  82. static struct hw_module_methods_t  led_module_methods= //模块拥有的打开方法  
  83. {  
  84.     open:led_init  
  85. };  
  86.   
  87.   
  88. const struct led_module_t HAL_MODULE_INFO_SYM=  //HAL_MODULE_INFO_SYM名称不能修改,用于导出的HMI找到模块,相当于模块的入口  
  89. {  
  90.     common:  
  91.         {  
  92.             tag:HARDWARE_MODULE_TAG, //在hardware.h中定义的,由HWMT组成  
  93.             version_major:1,   //模块主版本号  
  94.             version_minor:0,  //模块次版本号  
  95.             id:LED_UNDERS_HARDWARE_MODULE_ID,  //模块id,用于构成模块全名  
  96.             name:"led_unders stub",   //模块名称  
  97.             author:"undergrowth",   //模块作者  
  98.             methods:&led_module_methods,   //模块所拥有的方法  
  99.            }  
  100. };  

 

Android.mk

  1. LOCAL_PATH  :=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_PRELINK_MODULE    :=false  
  4. LOCAL_SRC_FILES :=led_unders_led_hal.c  
  5. LOCAL_SHARED_LIBRARIES  :=libutils  
  6. LOCAL_MODULE    :=led_unders.$(TARGET_BOARD_PLATFORM)  
  7. LOCAL_MODULE_TAGS   :=optional  
  8. LOCAL_MODULE_PATH   :=$(LOCAL_PATH)  
  9. include $(BUILD_SHARED_LIBRARY)  

 

说说个人对HAL的一些理解:

HAL是GOOGLE2008年I/O大会上提出来的,目的为了硬件厂商保护他们的proprietary,当然也正是这个原因,linux的维护者才将andorid的驱动从内核中删掉,因为linux遵循GPL协议,需要完全开放源代码,而Google遵循Apache 2.0,只需提供驱动的二进制代码即可,很明显,Google没有遵守linux的协议,就被linux干掉了。

       因为之前一直在做linux下的驱动开发,个人感觉HAL和驱动的测试代码很像,不同之处在于,你需要遵循一定的规则编写你的测试代码就形成了HAL层代码,建议最好看看hardware/libhardware/hardware.c和hardware/libhardware/include/hardware/hardware.h两个文件,这个是HAL的基础,对于编写HAL层代码有很大的帮助。

      对于HAL的更多介绍 就不多说了 这位老兄写的还不错 推荐  http://blog.csdn.net/k229650014/article/details/5801397

     可能碰到的错误:

  1.

  1.     fd=open(DEV_FILE_NAME,O_RDWR);  
  2.     if(fd<0)  
  3.         {  
  4.             __android_log_print(ANDROID_LOG_DEBUG,"msg","open_led failed.\n");  
  5.             return -1;  
  6.         }  

  调试的时候 发现open_led failed.  即打开文件失败 但是用驱动测试代码测试 设备文件是没有问题的  而是用HAL打开 就出现问题 无法打开 

 原因:权限不够

  解决方法:

(1) 添加设备文件的权限   eg: chmod 777 /dev/led_unders   即可解决

(2)android上的/dev下的设备文件权限 可以在init程序中控制,一般在
android/system/core/init/devices.c中有个变量:
static struct perms_ devperms[]={
...
{ "/dev/led_unders",          0666,   AID_ROOT,       AID_ROOT,       0 },
}
就ok了。

(3)关于权限的那一块,你可以再init.rc文件的on boot字眼下添加 #chmod 777 /dev/led_unders

 

2.调试的时候 发现load:countn't find symbol hmi

 查看hardware.c源码发现 是因为hmi为空值  于是查看led_unders_led_hal.c  发现 

  1. HAL_MODULE_INFO_SYM写成了HAL_MODULE_INFO_SYS  改过来即可  


附:生成的led_unders.tq210.so文件放在/system/lib/hw/目录下

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值