TQ210搭载Android4.0.3系统构建之LED从驱动到HAL到JNI到应用程序(HAL篇)
开发板:TQ210
OS:Android 4.0.3
以下所有内容都是在TQ210开发板上实现,并且很多内容也是天嵌公司提供,我将一些内容进行了删减、替换,然后加入了一些自己的理解,同时也是记录自己学习的旅程。
HAL层头文件 放在hardware/libhardware/include/hardware/目录下
led_unders_led_hal.h
#ifndef ANDROID_LED_UNDERS_H //保证头文件只被加载一次 #define ANDROID_LED_UNDERS_H #include <hardware/hardware.h> //包含hw_module_t hw_device_t hw_module_methods_t... #include <stdint.h> // 包含int long... #include <sys/cdefs.h> //包含__begin_decls __BEGIN_DECLS //按照C语言的方式编译和连接 #define LED_UNDERS_HARDWARE_MODULE_ID "led_unders" //led_unders模块ID struct led_module_t //led模块类型 ,继承hw_module_t { struct hw_module_t common; }; struct led_control_device_t //led设备类型,继承hw_device_t { struct hw_device_t common; int (*led_on)(struct led_control_device_t *dev,int32_t number); //打开led int (*led_off)(struct led_control_device_t *dev,int32_t number);//关闭led }; __END_DECLS #endif
led_unders_led_hal.c
#include <fcntl.h> #include <stdio.h> #include <stdlib.h> //包含malloc memset... #include <android/log.h> //包含__android_log_print #include <hardware/hardware.h> #include <hardware/led_unders_led_hal.h> #define DEV_FILE_NAME "/dev/led_unders" //设备文件名 #define IOCTL_GPIO_ON 1 //打开LED #define IOCTL_GPIO_OFF 0 //关闭LED static int fd=-1; //文件操作符 static int open_led() //打开LED { fd=open(DEV_FILE_NAME,O_RDWR); if(fd<0) { __android_log_print(ANDROID_LOG_DEBUG,"msg","open_led failed.\n"); return -1; } __android_log_print(ANDROID_LOG_DEBUG,"msg","open_led success.\n"); return 0; } static int close_led(struct hw_device_t *device) //关闭LED { if(fd!=-1) { close(fd); fd=-1; if(device) free(device); } return 0; } static int led_on(struct led_control_device_t *dev,int32_t number) //点亮LED { if(fd==-1) return -1; return ioctl(fd,IOCTL_GPIO_ON,number); } static int led_off(struct led_control_device_t *dev,int32_t number) //关闭LED { if(fd==-1) return -1; return ioctl(fd,IOCTL_GPIO_OFF,number); } //led初始化函数 static int led_init(const struct hw_module_t *module,const char *name,struct hw_device_t **device) { struct led_control_device_t *dev; //定义led设备指针 dev=(struct led_control_device_t *)malloc(sizeof(struct led_control_device_t)); //分配内存地址空间 if(dev==NULL) { __android_log_print(ANDROID_LOG_DEBUG,"msg","malloc failed.\n"); return 0; } memset(dev,0,sizeof(*dev)); //将内存块初始化为0 dev->common.tag=HARDWARE_DEVICE_TAG; //设备标志,由HWDT组成 dev->common.version=0; //设备版本 dev->common.module=module; //指向设备所属于的模块 dev->common.close=(int (*)(struct hw_device_t *))close_led; //关闭函数 *device=(struct hw_device_t *)&dev->common; //指向设备 dev->led_on=led_on; //操作函数赋值 dev->led_off=led_off; if(open_led()==-1) //打开led设备 { free(dev); dev=NULL; return -1; } return 0; } static struct hw_module_methods_t led_module_methods= //模块拥有的打开方法 { open:led_init }; const struct led_module_t HAL_MODULE_INFO_SYM= //HAL_MODULE_INFO_SYM名称不能修改,用于导出的HMI找到模块,相当于模块的入口 { common: { tag:HARDWARE_MODULE_TAG, //在hardware.h中定义的,由HWMT组成 version_major:1, //模块主版本号 version_minor:0, //模块次版本号 id:LED_UNDERS_HARDWARE_MODULE_ID, //模块id,用于构成模块全名 name:"led_unders stub", //模块名称 author:"undergrowth", //模块作者 methods:&led_module_methods, //模块所拥有的方法 } };
Android.mk
LOCAL_PATH :=$(call my-dir) include $(CLEAR_VARS) LOCAL_PRELINK_MODULE :=false LOCAL_SRC_FILES :=led_unders_led_hal.c LOCAL_SHARED_LIBRARIES :=libutils LOCAL_MODULE :=led_unders.$(TARGET_BOARD_PLATFORM) LOCAL_MODULE_TAGS :=optional LOCAL_MODULE_PATH :=$(LOCAL_PATH) include $(BUILD_SHARED_LIBRARY)
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.
fd=open(DEV_FILE_NAME,O_RDWR);
if(fd<0)
{
__android_log_print(ANDROID_LOG_DEBUG,"msg","open_led failed.\n");
return -1;
}
调试的时候 发现open_led failed. 即打开文件失败 但是用驱动测试代码测试 设备文件是没有问题的 而是用HAL打开 就出现问题 无法打开
原因:权限不够
解决方法: 添加设备文件的权限 eg: chmod 777 /dev/led_unders 即可解决
2.调试的时候 发现load:countn't find symbol hmi
查看hardware.c源码发现 是因为hmi为空值 于是查看led_unders_led_hal.c 发现
HAL_MODULE_INFO_SYM写成了HAL_MODULE_INFO_SYS 改过来即可
附:生成的led_unders.tq210.so文件放在/system/lib/hw/目录下
posted on 2013-06-24 17:00 liangxinzhi 阅读(145) 评论(0) 编辑 收藏 举报