zoukankan      html  css  js  c++  java
  • 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/目录下

  • 相关阅读:
    Android——继续深造——从安装Android Studio 2.0开始(详)
    PHP——安装wampserver丢失MSVCR110.dll
    Marza Gift for GDC 2016
    Retrieve OpenGL Context from Qt 5.5 on OSX
    Space Time Varying Color Palette
    Screen Space Depth Varying Glow based on Heat Diffusion
    Visualization of Detail Point Set by Local Algebraic Sphere Fitting
    Glass Dragon
    Jump Flood Algorithms for Centroidal Voronoi Tessellation
    京都之行
  • 原文地址:https://www.cnblogs.com/liangxinzhi/p/4275632.html
Copyright © 2011-2022 走看看