欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > PPT文档下载  

    硬件抽象层(HAL).ppt

    • 资源ID:5293958       资源大小:1.44MB        全文页数:33页
    • 资源格式: PPT        下载积分:15金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要15金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    硬件抽象层(HAL).ppt

    第9讲 硬件抽象层(HAL),讲师:李宁,讲师 李宁,主要内容,什么是HAL 为什么要在Android在添加HAL 编写和测试基于HAL的LED驱动,讲师 李宁,什么是HAL,HAL(Hardware Abstraction Layer,硬件抽象层)是建立在Linux驱动之上的一套动态库。这套动态库并不属于Linux内核,而是属于Linux内核层之上的系统运行库层。Google为Android增加HAL的主要目的除尽量避免应用程序直接访问Linux驱动外,还有一个重要原因,那就是保护“私人财产”。对于那些既想发布基于Android的Linux驱动程序,又不想将核心业务逻辑公开的企业或个人,HAL简直就是福音。,讲师 李宁,为什么要在Android中加入HAL,讲师 李宁,加入HAL的主要目的,统一硬件的调用接口。由于HAL有标准的调用接口,所以可以利用HAL屏蔽Linux驱动复杂、不统一的接口。解决了GPL版权问题。由于Linux内核基于GPL协议,而Android基于Apache Licence 2.0协议。因此Google玩了个“穿越”,将原本位于Linux内核中的Linux驱动的敏感代码向上移了一个层次。这样这些敏感代码就摆脱了GPL协议的束缚。那写不想开源的Linux驱动作者也就没必要开源了。针对一些特殊的要求。对于有些硬件,可能需要访问一些用户空间的资源,或在内核空间不方便完成的工作以及特殊需求。在这种情况下,可以利用位于用户空间的HAL代码来辅助Linux驱动完成一些工作。,讲师 李宁,Android HAL的旧架构,讲师 李宁,Android HAL的新架构,讲师 李宁,Android HAL程序库的路径,Android HAL的源代码存储的位置并不固定。一般会存储在/hardware目录中。其中/hardware/libhardware_legacy用于保存旧的HAL架构的源代码。新HAL架构的源代码在/hardware/libhardware目录中,当然,这些源代码可以放在/hardware或其他的目录。最终编译生成的.so文件主要放在Android系统的/system/lib/hw目录,也可以放在其他的目录。,讲师 李宁,精简LED驱动,基于HAL的LED驱动去掉了所有与读写寄存器规则相关的代码,只保留了创建设备文件已经与寄存器交互的代码(不涉及到任何规则,只是将数据简单地写入指定的寄存器,或从指定的寄存器读取数据)。LED驱动利用了设备文件的read和write函数来读写指定的寄存器。基本原理是只从指定寄存器读取或写入5个字节。第1个字节用于指定读写的动作以及寄存器。后4个字节是读写的实际的数据(因为LED驱动只涉及到操作一个int类型数据的寄存器,因此使用4个字节个来表示一个int类型的数据)。在与LED驱动交互是,只要向设备文件(/dev/s3c6410_leds_hal)读取或发送5个字节的数据,就可以读写指定的寄存器。,讲师 李宁,测试读写寄存器操作,由于LED驱动程序的设备文件接收的不是字符串,而是字节类型的数据(字节数组),因此需要单独做一个程序向设备文件写入字节形式的数据,或从设备文件中读取字节类型的数据。命令行参数来传递设备文件名、字节数和要传递的字节等信息。命令行语法格式如下:rwdev byte1 byte2.byten编译rw_dev.c程序arm-gcc-static-o/root/drivers/read_write_dev/rwdev/root/drivers/read_write_dev/rw_dev.c,讲师 李宁,调用LED驱动的HAL程序库(1),任何被系统自动调用的程序都会有一个标准的接口。这个接口相当与一个约定的规则。不管任何程序,只要遵循这个规则,就可以成功被调用。例如,C语言可执行程序都会有一个main函数,系统中执行程序是都会寻找main函数来执行;Linux驱动也有多个接口,最常用的就是init和exit函数,除此之外,还有与设备文件相关的read、write、ioctl等函数。只要Linux驱动程序安装接口的要求定义和实现,就可以成功安装在Linux驱动中。,讲师 李宁,调用LED驱动的HAL程序库(2),既然HAL程序库也可以被Android系统自动调用,那么自然也拥有标准的接口。只不过这个接口不是函数,而是一个固定名称的结构体变量HAL_MODULE_INFO_SYM。也就是说,所有的HAL程序都必须要有一个HAL_MODULE_INFO_SYM变量,并且初始化该结构体变量的common成员变量。,讲师 李宁,调用LED驱动的HAL程序库(3),第1步:定义结构体和宏 编写HAL程序库需要使用到3个非常重要的结构体(hw_module_t、hw_device_t和hw_module_methods_t),在第1步需要定义两个新的结构体,这两个结构体的第1个变量的类型必须是hw_module_t和hw_device_t。一般还需要为HAL模块定义一个ID。实际上在这1步就是编写leds_hal.h头文件的代码。,讲师 李宁,调用LED驱动的HAL程序库(4),typedef struct hw_module_t/*模块的Tag,值必须是HARDWARE_MODULE_TAG*/uint32_t tag;/*模块主版本号*/uint16_t version_major;/*模块从版本号*/uint16_t version_minor;/*模块的ID,通过该ID可以找到当前模块*/const char*id;/*模块名称*/const char*name;/*模块作者*/const char*author;/*与模块相关的函数指针,都包含着hw_module_methods_t结构体中*/struct hw_module_methods_t*methods;/*模块的dso,dlopen函数返回的HAL动态库的handler*/void*dso;/*保留的空间*/uint32_t reserved32-7;hw_module_t;,讲师 李宁,调用LED驱动的HAL程序库(5),描述硬件设备(或称为HAL设备)的结构体hw_device_t。typedef struct hw_device_t/*设备的Tag,值必须是HARDWARE_DEVICE_TAG*/uint32_t tag;/*硬件设备的版本号*/uint32_t version;/*指向描述硬件模块的hw_module_t结构体指针*/struct hw_module_t*module;/*保留的内存空间*/uint32_t reserved12;/*关闭设备的函数指针*/int(*close)(struct hw_device_t*device);hw_device_t;,讲师 李宁,调用LED驱动的HAL程序库(6),描述模块入口函数的结构体hw_module_methods_t。typedef struct hw_module_methods_t/*打开设备是调用的open函数的指针*/int(*open)(const struct hw_module_t*module,const char*id,struct hw_device_t*device);hw_module_methods_t;在这3个结构体中,hw_module_t是最先使用到的,然后通过hw_module_t.methods找到hw_module_methods_t.open函数,并调用该函数。这个open函数相当与HAL程序库的入口函数。一般会在这个函数里打开设备文件,初始化hw_device_t结构体设置一些控制硬件设备的函数。,讲师 李宁,调用LED驱动的HAL程序库(7),在第1步先考虑hw_module_t和hw_device_t两个结构体。HAL规则建议不直接使用hw_module_t和hw_device_t(直接使用这,而要新定义两个结构体,将hw_module_t和hw_device_t分别作为新结构体的第1个变量的类型。就像leds_hal.h文件中的led_module_t和led_control_device_t。那么HAL为什么要这么建议呢?,讲师 李宁,调用LED驱动的HAL程序库(8),在说明原因之前,先看一下led_device_open函数和led_control_device_t结构体。static int led_device_open(const struct hw_module_t*module,const char*name,struct hw_device_t*device)struct led_control_device_t struct hw_device_t hw_device;int(*set_on)(struct led_control_device_t*dev,int32_t led);int(*set_off)(struct led_control_device_t*dev,int32_t led);,讲师 李宁,调用LED驱动的HAL程序库(9),led_device_open函数将在NDK程序中被调用。该函数的最后1个参数类型是hw_device_t*,不过在调用该函数时,传进来的却是led_control_device_t*。从这一点看。hw_device_t相当与led_control_device_t的父类(C语言中并没有类的概念,这样解释只是便于理解,也可以称为其父结构体)。在调用led_device_open函数时将led_control_device_t*强行转换成了hw_device_t*。对于C语言来说,这样的转换要满足一个条件,就是做为父结构体(hw_device_t)的结构体必须是子结构体(led_control_device_t)的第1个变量的数据类型。,讲师 李宁,调用LED驱动的HAL程序库(10),那么为什么要这样做强行转换呢?主要是因为扩展的需要。因为在led_control_device_t结构体中定义了两个函数指针变量(set_on和set_off)。这两个变量的名称和参数个数、参数类型是任意指定的。但为了使HAL程序库保持独立性(可能会被多个NDK模块使用,每个NDK模块使用了不同的hw_device_t和hw_module_t的子结构体),HAL程序库在的方法只能使用hw_device_t和hw_module_t作为参数类型。而如果不使用hw_device_t和hw_module_t的父类,就意味这无法添加这种设备函数指针(set_on和set_off)等成员。那么这个HAL程序库就成了中看不中用的“东西”了。光有逻辑代码,却无法向外部提供与其交互的接口。,讲师 李宁,调用LED驱动的HAL程序库(11),由于在led_module_t结构体除了hw_module变量外,没有任何其他的成员,因此,HAL_MODULE_INFO_SYM的类型可以直接定义成hw_module_t,代码如下:struct hw_module_t HAL_MODULE_INFO_SYM=tag:HARDWARE_MODULE_TAG,version_major:1,version_minor:0,id:LED_HARDWARE_MODULE_ID,name:Sample LED HAL Stub,author:Lining,methods:,讲师 李宁,调用LED驱动的HAL程序库(12),第2步:编写打开设备的open函数 设备的打开函数是HAL模块的入口点。在本例中是led_device_open函数。设备打开函数主要做如下3项工作。初始化hw_device_t的子结构体。除了设置也写必要的变量外,还需要设置操作硬件的函数指针(本例是close、set_on和set_off)。其中set_on和set_off在调用HAL模块的代码中要使用到。close有系统自动调用。在这一步与close、set_on和set_off惯量的函数还没有定义,可以先把函数名写上,或在定义了相关函数后再设置这些函数指针。打开设备文件。初始化寄存器。,讲师 李宁,调用LED驱动的HAL程序库(13),第3步:定义hw_module_methods_t结构体变量HAL模块需要hw_module_methods_t结构体的open函数指针变量指定open入口函数。第4步:定义HAL_MODULE_INFO_SYM变量 所有的HAL模块都必须有一个HAL_MODULE_INFO_SYM变量。该变量的类型一般为hw_module_t或其子结构体。该变量初始化了一些变量,其中id和methods成员最重要。id表示HAL模块中Android系统中的索引。使用HAL模块的程序并不是直接装载.so文件,而是通过这个id找到并装载HAL模块。methods变量的值需要设置在第3步定义的hw_module_methods_t结构体变量。当调用者通过id找到并装载HAL模块后,就会通过methods变量调用open入口函数来初始化设备。,讲师 李宁,调用LED驱动的HAL程序库(14),第5步:编写卸载设备的close函数当HAL模块被卸载后会调用close函数。在本例中是led_device_close函数。该函数需要在第2步的led_device_open函数中赋给hw_device_t的close成员变量。第6步:编写控制设备的函数根据设备类型和功能的不同,这一步编写的函数也有所不同。在本例中编写了两个控制函数(led_on和led_off),分别用来控制LED的开、关。led_on和led_off函数需要在第2步编写的led_device_open函数中赋给led_control_device_t.set_on和led_control_device_t.set_off变量。,讲师 李宁,编写调用HAL程序库的Service,调用HAL程序库涉及到一个非常重要的hw_get_module函数。该函数可以通过在leds_hal.h中定义的LED_HARDWARE_MODULE_ID宏(led_hal)查找LED HAL模块,并获得led_module_t结构体。然后调用函数来初始化LED驱动。并通过open函数返回led_control_device_t结构体。在led_control_device_t结构体中包含了在HAL模块中定义的控制LED驱动的函数指针(set_on和set_off)。为Service建立符号链接 ln-s/root/drivers/s3c6410_leds_hal/leds_hal_jni,讲师 李宁,HAL的存放路径和命名规则(1),HAL程序库(so文件)通常存放在/system/lib/hw目录。文件名中一般都有一个default。例如,文件是LED驱动的HAL程序库。那么这个存放目录和文件名是我们的唯一选择吗?在回答这个问题之前,需要先查看一下调用HAL程序库的核心函数hw_get_module的代码,因为正是这个函数利用HAL模块的ID找到了HAL程序库的.so文件。所以一切的秘密都会在这个函数的揭开。hw_get_module函数位于hardware.c文件中。hardware.c文件的完整路径如下:,讲师 李宁,HAL的存放路径和命名规则(2),在阅读完hardware.c文件的代码和注释后,可以得出如下结论,这些结论也恰好回到了本节开始提出的问题。HAL模块库文件的存放路径有两个:/system/lib/hw和/vendor/lib/hw。hw_get_module函数会先从/system/lib/hw目录根据库文件命名规则寻找库文件。如果/system/lib/hw目录没有库文件,hw_get_module会按同样的规则在/vendor/lib/hw目录中寻找。HAL模块库文件的命名规则是。其中ID功过hw_get_module函数的id参数指定。suffix(后缀)通过在属性文件中指定。hw_get_module会在Android系统的属性文件中根据variant_keys数组中定义的4个key依次查找suffix。如果未找到suffix,使用默认的suffix(default)。,讲师 李宁,HAL的存放路径和命名规则(3),在上面的几点多次提到了属性文件,那么这个属性文件到底是什么呢?实际上,Android系统的属性文件共有如下4个。/default.prop/system/build.prop/system/default.prop/data/local.prop,讲师 李宁,HAL的存放路径和命名规则(4),Android在启动时会自动装载这些属性文件。如果在多个属性文件中都定义了同一个Key和Value,那么只用第一个Key被获取。例如,在/default.prop文件中定义了的值为abc,而在/system/build.prop文件中定义了的值为xyz。那么hw_get_module函数会把/default.prop文件中的abc作为HAL模块库文件的后缀,而不会再读取/system/build.prop文件中的xyz。因此,HAL模块的库文件名是(假设ID是led_hal)。,讲师 李宁,HAL的存放路径和命名规则(5),4个属性文件名在如下文件定义了4个宏。在以后的Android版本中有可能增加新的属性文件。_system_properties.h 打开_system_properties.h文件后,就会在后面看到如下4个宏。#define PROP_PATH_RAMDISK_DEFAULT/default.prop#define PROP_PATH_SYSTEM_BUILD/system/build.prop#define PROP_PATH_SYSTEM_DEFAULT/system/default.prop#define PROP_PATH_LOCAL_OVERRIDE/data/local.prop,讲师 李宁,编写调用Service的Java库(1),LedHalService ledHalService=LedHalService.getInstance();ledHalService.setOn(0);/打开第1个LEDledHalService.setOn(1);/打开第2个LEDledHalService.setOff(2);/关闭第3个LEDledHalService.setOn(3);/打开第4个LED生成LedHalService.jar文件cd/root/drivers/s3c6410_leds_hal/leds_hal_service/bin/classesjar cvf././LedHalService.jar./mobile/android/leds/hal/service/LedHalService.class,讲师 李宁,编写调用Service的Java库(2),任何Android应用程序只要引用LedHalService.jar文件就可控制LED。不过在运行Android应用程序之前需要在开发板上安装如下3个程序库。LED驱动:/data/local/s3c6410_leds_hal.koHAL程序库:/system/lib/hw/Service程序库:/system/lib/led_hal_jni.so,讲师 李宁,测试LED驱动,

    注意事项

    本文(硬件抽象层(HAL).ppt)为本站会员(小飞机)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开