• 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.
    ");
    			return -1;
    		}
    	__android_log_print(ANDROID_LOG_DEBUG,"msg","open_led success.
    ");
    	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.
    ");
    		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的一些理解:

    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.
    ");
    			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/目录下

  • 相关阅读:
    java实现遍历树形菜单方法——设计思路【含源代码】
    java实现动态验证码源代码——接受ajax的jsp
    java实现动态验证码源代码——接受ajax的jsp
    java实现动态验证码源代码——绘制验证码的jsp
    java实现动态验证码源代码——绘制验证码的jsp
    java实现动态验证码源代码——jsp页面
    java实现动态验证码源代码——jsp页面
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——struts.xml配置详情
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——struts.xml配置详情
    struts+hibernate+oracle+easyui实现lazyout组件的简单案例——Action的实现类
  • 原文地址:https://www.cnblogs.com/liangxinzhi/p/4275632.html
Copyright © 2020-2023  润新知