`
dengzhangtao
  • 浏览: 683358 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

android系统硬件抽象层(HAL)原理及实现之原理

 
阅读更多

Android系统硬件抽象层(HAL)原理

android开发过程中,我们经常看到HAL这个概念,这就android的硬件抽象层的(Hardwaere Abstraction Layer)缩写,它是Goolge应某些厂商不希望公开源码所添加的一个适配层,能以封闭源码的方式提供硬件驱动模块,目的就是把android framework层和linux kernel层隔离开来,使android系统不至于过度的依赖linux kernel层的实现,也就是说android framework可以不考虑linux kernel如何实现的情况下独立开发

      Android HAL层位于android系统和linuxkernel之间,如下图所示:

 

 

 

 

Android java应用层(app

 

Android java框架层(framework

 

 

 

Android本地框架层(native

 

 

硬件抽象层(HAL

 

硬件抽象层实现

 

驱动层(linuxkernel

在移植系统或添加新的模块时都需要androidHAL层进行修改或者添加实现,androidHAL层在android的源码位置:

hardware/libhardware/

hardware/libhardware_legacy/

hardware/xxxx/

有的还位与其他位置。AndroidHAL层的实现方式有几种方式:

1,hardware模块的方式

2,C/C++继承方式

3,直接调用驱动接口方式

4,直接接口方式

下面我从这几种方式作一下简单的分析

 

《一》首先分析一下hardware模块方式的实现,这种方式是一种不依赖编译时绑定的实现,它可以动态的加载硬件抽象层就是说可以通过ID来动态的打开(dlopen)一个硬件模块,然后找到符号(dlsym)进行调用。

 

Android native framework-(根据不同的ID)àlibhardware.so-(dlopen)->/system/hw/*.so->drivers

 

接下来分析一下HAL这个抽象的框架,具体的代码在源码的

hardware/libhardware/hardware.c

hardware/libhardware/include/hardware/hardware.h位置

来看看hardware.h这个头文件,我们可以发现在这个头文件中主要定义的三个结构体

 

struct hw_device_t

struct hw_module_t

struct hw_module_methods_t

hw_device_t:表示硬件设备,存储了各种硬件设备的公共属性和方法,如果需要移植或者添加新硬件,那么都需要使用该结构进行注册,其中的tag必须初始化。结构体hw_module_t在进行加载的时候用于判断属于哪个module

typedef struct hw_device_t {
uint32_t tag; //tag
需要被初始化为HARDWARE_DEV

uint32_t version; //hw_device_t的版本号

struct hw_module_t* module; //引用这个设备属于的硬件模块

uint32_t reserved[12]; //填充保留字节

int (*close)(struct hw_device_t* device); //关闭设备

} hw_device_t;

typedef struct hw_module_t {
       
 uint32_t tag; //tag需要被初始化为HARDWARE_MODULE_TAG

uint16_t version_major; //主版本号

uint16_t version_minor; //次版本号

const char *id; //模块标识符

const char *name; //模块名称

const char *author; //模块作者

struct hw_module_methods_t* methods; //模块方法

void* dso;  //模块的dso

uint32_t reserved[32-7]; //填充字节,为以后使用

} hw_module_t; 

hw_module_methods_t:该结构体用于定义操作设备的各种方法operations,这里只定义一个open方法。如果要执行打开设备等操作可以在JNI层使用“module->methods->open(module,LED_HARDWARE_MODULE_ID,(struct hw_device_t** )device);”

typedef struct hw_module_methods_t {
            int (*open)(const struct hw_module_t* module, const char* id,struct hw_device_t** device); //
打开设备的方法

} hw_module_methods_t;

 

其中struct hw_device_t表示一个硬件设备

Struct hw_module_t表示硬件模块的格式

Sttruct hw_module_methods_t表示模块的方法

(三个结构体可以看到hw_device_t包含hw_module_t, hw_module_t保含hw_module_methods_t,这是面向对象的思想的体现,呵呵呵)

在加载某个模块的时候会调用hw_get_module这个方法,这个方法就可以获得相应的HAL,代码如下所示:

int hw_get_module(const char *id, const struct hw_module_t **module)
{
    int status;
    int i;
    const struct hw_module_t *hmi = NULL;
    char prop[PATH_MAX];
    char path[PATH_MAX];

    /*
     * Here we rely on the fact that calling dlopen multiple times on
     * the same .so will simply increment a refcount (and not load
     * a new copy of the library).
     * We also assume that dlopen() is thread-safe.
     */

    /* Loop through the configuration variants looking for a module */
    for (i=0 ; i<HAL_VARIANT_KEYS_COUNT+1 ; i++) {
        if (i < HAL_VARIANT_KEYS_COUNT) {
     //
获取ro.hardware/ro.product.board/ro.board.platform/ro.archkey的值。
       if (property_get(variant_keys[i], prop, NULL) == 0) {

                continue;
            }
            snprintf(path, sizeof(path), "%s/%s.%s.so",
                    HAL_LIBRARY_PATH, id, prop);
        } else { //
如果没有动态加载的动态链接库,需要加载默认的模块
            snprintf(path, sizeof(path), "%s/%s.default.so",
                    HAL_LIBRARY_PATH, id);
        }
        if (access(path, R_OK)) {
            continue;
        }
        /* we found a library matching this id/variant */
        break;
    }

    status = -ENOENT;
    if (i < HAL_VARIANT_KEYS_COUNT+1) {
        /* load the module, if this fails, we're doomed, and we should not try
         * to load a different variant. */
        status = load(id, path, module);//
调用load()函数打开动态链接库
    }

    return status;
}

 

在该方法中可以看出,android系统通过系统的属性查找硬件,根据ID和找到的路径加载相应的.so库文件在hw_get_module中有一个重要的方法

Load

static int load(const char *id,const char *path,const struct hw_module_t **pHmi)
{
    int status;
    void *handle;
    struct hw_module_t *hmi;

/*
     * load the symbols resolving undefined symbols before
     * dlopen returns. Since RTLD_GLOBAL is not or'd in with
     * RTLD_NOW the external symbols will not be global
     */
    handle = dlopen(path, RTLD_NOW);//
打开动态库
    if (handle == NULL) {
        char const *err_str = dlerror();
        LOGE("load: module=%s\n%s", path, err_str?err_str:"unknown");
        status = -EINVAL;
        goto done;
    }

    /* Get the address of the struct hal_module_info. */
    const char *sym = HAL_MODULE_INFO_SYM_AS_STR;
    hmi = (struct hw_module_t *)dlsym(handle, sym););//
查找“HMI”这个导出符号,并获取其地址
    if (hmi == NULL) {
        LOGE("load: couldn't find symbol %s", sym);
        status = -EINVAL;
        goto done;
    }

 /* Check that the id matches */
    if (strcmp(id, hmi->id) != 0) {
        LOGE("load: id=%s != hmi->id=%s", id, hmi->id);
        status = -EINVAL;
        goto done;
    }

    hmi->dso = handle;

    /* success */
    status = 0;

    done:
    if (status != 0) {
        hmi = NULL;
        if (handle != NULL) {
            dlclose(handle);
            handle = NULL;
        }
    } else {
        LOGV("loaded HAL id=%s path=%s hmi=%p handle=%p",
                id, path, *pHmi, handle);
    }

    *pHmi = hmi;

    return status;
}

从上可以简单得出硬件的具体调用过程,大致是这样的

首先通过ID找到硬件模块

然后硬件模块得到methods打开设备(hw_device_t

再后调用设备的各个方法

最后使用完毕后通过设备的close方法关闭

 

《二》C/C++继承方式

这种方式最典型的有CAMERAAUDIO两个系统,这种方式是在android系统中定义了C++接口如camera中的CameraHardwareInterface.h,其中定义了操作camera的各个方法,这些方法有具体的实现者来实现,一般情况下硬件抽象层会被编译成动态或静态库,由本地框架调用或链接,具体在camera中分析

后两种方式在分析具体模块时再做具体分析

 

HAL层的原理就简单介绍到这里,接下来我会详细分析不同的具体的模块的实现

3
1
分享到:
评论

相关推荐

    图像处理实战指南:从边缘检测到水印嵌入的关键算法解析

    内容概要:本文详细介绍了多种图像处理技术的实际应用和实现方法,涵盖了边缘检测、分形维数计算、霍夫直线检测、伪彩色增强、PCA降维、图像配准以及水印嵌入等多个方面。每种技术不仅提供了具体的Python代码示例,还分享了作者在实践中积累的经验和技巧。例如,边缘检测部分强调了Sobel算子的正确使用方法及其注意事项;分形维数计算部分展示了如何通过盒计数法进行实现;霍夫直线检测部分讨论了参数选择的影响;伪彩色增强部分介绍了基于LUT的颜色映射方法;PCA降维部分讲解了人脸识别的具体步骤;图像配准部分探讨了SIFT算法的应用;水印嵌入部分则深入剖析了DCT域的方法。 适合人群:具有一定编程基础并希望深入了解图像处理技术的开发者和技术爱好者。 使用场景及目标:适用于需要快速掌握图像处理核心技术的研究人员、工程师和学生。目标是帮助读者理解并能够独立实现常见的图像处理任务,如边缘检测、特征提取、图像融合、降维、配准和水印嵌入等。 其他说明:文中提供的代码片段均经过实际验证,可以直接用于实验环境。此外,作者还分享了许多实用的小贴士,如避免常见错误、优化性能等,有助于提高读者的实际操作能力。

    生成式AI入门:商业与技术领导者的指南

    本书《What Is Generative AI》由Kyle Stratis撰写,旨在为商业和技术领导者提供生成式人工智能(Generative AI)的基础知识。生成式AI是一种能够创造新内容的技术,包括图像、文本和视频,与传统的判别式AI不同,后者主要用于分类和回归任务。书中介绍了生成式AI的历史、发展以及现代架构,如变分自编码器(VAE)、生成对抗网络(GAN)和Transformer模型,并探讨了其在商业和创意领域的应用。作者强调,尽管生成式AI在推动增长、增强创造力和简化运营方面具有巨大潜力,但实施时也面临着伦理、法律和技术挑战。本书旨在为读者提供必要的知识和见解,以便他们能够评估生成式AI的投资回报率,并在日常生活中、商业活动或创意工作中有效利用这项技术。

    伍德里奇计量经济学计算机习题解答与资源

    《伍德里奇计量经济学计算机习题解答与资源》为学习者提供全面的习题解答与实用资源,涵盖R语言实现,帮助巩固计量经济学理论知识并提升实操能力。适合自学或辅助课程学习,助你高效掌握数据分析与建模技巧。

    基于深度学习的行人检测系统(YoloV3+Tensorflow).zip

    基于深度学习的系统

    Asp.Net CRM客户关系管理系统:企业信息化进程中的高效解决方案

    内容概要:本文详细介绍了Asp.Net CRM客户关系管理系统的功能和实现细节。该系统不仅涵盖了客户信息管理、日程安排等功能,还展示了如何通过C#代码实现这些功能。此外,文章强调了系统的二次开发能力和扩展性,如通过创建新的数据库表和编写相应代码来满足特定行业需求。系统采用三层架构,将客户生命周期、销售流程、团队协同等功能模块有机结合,形成一个完整的业务协同平台。文中还探讨了销售漏斗的状态机实现、实时消息推送、动态加载模块等高级功能,突出了ASP.NET在企业级业务系统开发中的优势。 适合人群:对CRM系统开发感兴趣的软件工程师、项目经理和技术主管。 使用场景及目标:适用于希望提升客户管理和内部协作效率的企业,尤其是那些需要定制化解决方案的企业。通过实施该系统,企业可以更好地管理客户资源,优化销售流程,提高工作效率,最终增强市场竞争力。 其他说明:文章提供了大量实际代码示例,帮助读者深入理解系统的工作原理和实现方法。同时,强调了系统设计中的关键技术决策,如使用状态模式、依赖注入、实时通信等,使读者不仅能学到具体的技术实现,还能掌握系统设计的思想。

    流固耦合仿真技术:流固耦合网格划分.zip

    流固耦合仿真技术:流固耦合网格划分.zip

    natsort-4.0.4-py2.py3-none-any.whl

    该资源为natsort-4.0.4-py2.py3-none-any.whl,欢迎下载使用哦!

    基于Qt与C++的温度湿度传感器上位机开发:串口通信、数据记录与超时提醒

    内容概要:本文详细介绍了一款基于Qt和C++开发的温度湿度传感器上位机程序。该程序实现了串口通信获取传感器数据、数据记录与自动保存、超时提醒等功能。具体功能包括:通过QSerialPort进行串口通信,获取温度和湿度数据;封装独立的串口通信处理类,便于二次开发;提供控制台调试窗口,用于实时显示和发送数据;利用QSettings实现配置自动保存;通过QTimer实现超时提醒;以及使用QDateTime生成带有时间戳的文件名,确保数据安全保存。此外,文中还介绍了开发环境、代码结构和一些常见问题及其解决方案。 适合人群:具有一定C++和Qt基础的开发者,尤其是从事物联网、嵌入式开发的技术人员。 使用场景及目标:适用于需要开发温度湿度传感器上位机的应用场景,如智能家居、工业监控等。主要目标是帮助开发者理解和掌握如何通过Qt和C++实现传感器数据的采集、处理和展示。 其他说明:文中提供了详细的代码片段和解释,有助于读者更好地理解每个功能的具体实现方法。同时,文中还提到了一些常见的开发陷阱和优化建议,为实际项目开发提供了宝贵的实践经验。

    西门子S7-200PLC与MM420变频器三种控制方式详解及应用

    内容概要:本文详细介绍了西门子S7-200PLC(224XP型号)与MM420变频器之间的三种控制方式:数字量控制、模拟量控制以及USS通讯控制。首先,数字量控制通过PLC的开关量输出控制变频器的不同预设速度,涉及参数设置如P0701和P0702。其次,模拟量控制利用PLC自带的模拟量输出模块进行频率调节,需注意量程转换和参数P0756的设置。最后,USS通讯采用西门子专用协议实现复杂控制,强调了初始化参数、轮询机制和状态互锁的重要性。此外,文中还提供了关于MCGS触摸屏的应用技巧,如变量绑定和实时数据显示方法。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是熟悉西门子PLC和变频器产品的使用者。 使用场景及目标:适用于希望深入了解PLC与变频器联合控制系统的设计与实现的技术人员。主要目标是在实际工程项目中灵活运用这三种控制方式,提高系统的可靠性和效率。 其他说明:文中附带了详细的代码片段和调试建议,帮助读者更好地理解和实践相关技术。同时提醒读者关注参数设置的一致性和安全性,以避免潜在的风险。

    流变学仿真方法:流变学仿真结果分析.zip

    流变学仿真方法:流变学仿真结果分析.zip

    基于STM32F103RCT6的西门子PLC 224XP/226改造:双串口DMA与指令系统实现

    内容概要:本文详细介绍了将西门子PLC 224XP和226型号主控替换为STM32F103RCT6的改造项目。主要内容涵盖硬件选型、双串口DMA传输配置、PLC指令系统的实现、浮点运算处理、密码保护机制以及协议兼容等方面。文中提供了丰富的代码示例和技术细节,如GPIO复用配置、USART1和USART3的DMA环形缓冲配置、浮点数比较指令处理、三级密码验证状态机、S7协议读取请求处理、梯形图编译器的状态机构建等。 适合人群:具备嵌入式开发经验,熟悉STM32和PLC编程的技术人员。 使用场景及目标:适用于希望深入了解PLC改造项目的工程师,旨在掌握如何利用STM32实现高效稳定的PLC功能替代,提高工业控制系统性能。 其他说明:作者分享了许多实际开发中的经验和技巧,如DMA环形缓冲配置、浮点运算优化、协议兼容处理等,有助于读者更好地理解和应用相关技术。

    adnbvjasdbsdvbfs

    sdgasdfg

    口罩机自动化项目:基于三菱FX3U PLC与威纶触摸屏的详细解析及应用

    内容概要:本文深入剖析了一个完整的口罩机自动化项目,涵盖了从硬件选型、电路设计到软件编程的各个方面。主要内容包括三菱FX3U PLC的梯形图编程、威纶触摸屏的界面设计、伺服电机参数调整、安全回路设计以及详细的IO表规划。文中不仅提供了具体的代码实例和技术细节,还分享了许多实际调试过程中积累的经验教训,如伺服电机抖动问题的解决、急停按钮的正确连接方式、关键传感器的输入点分配等。此外,作者还强调了装配图和调试记录的重要性,指出这些资料对于理解和优化整个系统的性能至关重要。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是那些希望深入了解PLC编程和触摸屏应用的人群。 使用场景及目标:适用于正在开发或维护类似自动化设备的技术团队,帮助他们提高系统的稳定性和生产效率。通过对本文的学习,读者能够掌握如何将理论知识应用于实际项目中,避免常见的设计和调试误区。 其他说明:文章最后提供了一个完整的项目资料包下载链接,包含了所有相关文件和调试记录,方便读者进行实践操作。

    全开源淘客系统的Go-PHP-Vue技术栈实现与优化

    内容概要:本文深入探讨了一个全开源淘客系统的实现细节和技术优化。系统采用Go语言重构淘宝联盟API网关,处理商品搜索接口的核心逻辑,确保参数签名安全、HTTP请求稳定以及数据格式转换正确。数据库设计方面,使用MySQL存储佣金结算数据,利用JSON类型保存结算规则快照,防止规则变更影响历史数据。前端部分基于Vue.js构建佣金日历组件,强调数据驱动UI和事件冒泡处理交互。部署环节涉及SSL证书链的手动更新,确保API通信的安全性和稳定性。此外,系统还提供了详细的错误码设计、调试工具、订单同步服务、SDK封装、热更新通道等功能,旨在降低开发和运维难度,提高系统的可扩展性和易用性。 适合人群:具备一定编程基础的技术人员,尤其是对淘客系统感兴趣的开发者。 使用场景及目标:适用于希望搭建高效、稳定的淘客系统的个人或团队。主要目标是帮助用户理解淘客系统的架构设计和技术实现,提供实际操作指导,减少开发和运维中的常见问题。 其他说明:文中提到的系统不仅关注技术实现,还注重用户体验和系统稳定性,提供了丰富的调试工具和详细的文档支持。

    CursorUserSetup-x64-0.48.8

    CursorUserSetup-x64-0.48.8

    电子硬件基于2025年行业动态的课程设计项目资源汇总:涵盖物联网开发、电机控制及传感器融合系统

    内容概要:本文档为电子硬件课程设计提供了全面的项目资源,涵盖典型课程设计项目示例、开源项目资源库、开发工具与文档以及拓展学习平台。典型项目包括物联网综合开发平台(如ESP32主控+墨水屏交互系统)、电机驱动与控制项目(如STM32F4系列开发板的PWM调速算法)、传感器融合系统(如PM2.5检测仪)。开源项目资源库列举了多个项目的核心技术及其适用场景,如CD4047逆变器设计适用于电源系统课程设计。开发工具与文档部分介绍了EDA工具包、编程框架等,如重庆大学硬件综合设计实验包、STM32-V5开发套件。拓展学习平台则推荐了硬件开发社区和在线课程资源。最后给出了项目设计建议,包括开发流程和文档规范。; 适合人群:电子工程专业学生、电子硬件初学者、高校教师。; 使用场景及目标:①为电子硬件课程设计提供详细的项目参考,帮助学生完成课程作业;②为教师提供教学资源,辅助课堂教学;③为初学者提供学习路径,便于自学入门。; 其他说明:本文档结合了2025年最新行业动态和教学实践,确保提供的资源具有前沿性和实用性。文档强调了从需求分析到系统联调的完整开发流程,并对文档规范提出了具体要求,确保项目实施的规范性和可追溯性。

    2024300928刘君浩.rar

    2024300928刘君浩.rar

    MATLAB实现模拟退火算法解决带容量限制的车辆路径问题(CVRP)

    内容概要:本文详细介绍了如何利用MATLAB实现模拟退火(SA)算法来解决带容量限制的车辆路径问题(CVRP)。首先解释了CVRP的核心挑战,即在满足车辆载重量限制的情况下,规划最优运输路线以最小化总运输成本。文中提供了完整的MATLAB代码实现,涵盖了初始化解、邻域操作、成本计算以及退火过程等关键步骤。此外,还讨论了一些常见的调试陷阱和技术细节,如温度参数的选择、邻域操作的设计以及如何处理超载情况。最后,给出了可视化的路线展示方法,并分享了几点实战经验和改进建议。 适合人群:对运筹学、物流优化感兴趣的科研人员、学生以及从事相关领域的工程师。 使用场景及目标:适用于需要优化物流配送路线的实际应用场景,特别是在中小规模CVRP问题中表现出色。主要目标是帮助读者理解和掌握模拟退火算法的基本原理及其在CVRP问题中的具体应用。 其他说明:文中提到的代码可以直接用于实验环境,同时也鼓励读者在此基础上进一步探索和改进算法性能。对于更大规模的问题,建议结合其他启发式方法共同使用。

    基于组态王与三菱FX3U PLC的真空封装设备监控系统的实战应用

    内容概要:本文详细介绍了利用组态王软件和三菱FX3U PLC构建真空封装设备监控系统的具体实施过程和技术要点。主要内容涵盖设备监控界面的设计(如动态加载子画面)、报警处理模块(采用SQLite进行本地缓存)、用户权限管理系统(基于XML配置文件)以及真空度趋势预测等功能的实现方法。此外,还探讨了通信配置、工艺流程控制逻辑、数据记录与查询等方面的技术细节,并分享了一些实用的操作技巧和注意事项。 适合人群:从事工业自动化领域的工程师和技术人员,尤其是那些对组态王和PLC编程有一定了解的人群。 使用场景及目标:适用于需要搭建高效稳定的工业生产设备监控系统的场合,旨在提高生产效率、降低误操作风险并确保设备安全可靠地运行。 其他说明:文中提供了大量具体的代码片段作为实例,帮助读者更好地理解和掌握相关知识点。同时强调了在实际项目中应注意的问题,如避免过度依赖上位机处理业务逻辑等。

    一维抛物热传导方程的数值解法及其MATLAB实现

    内容概要:本文详细介绍了求解一维抛物热传导方程的各种经典数值方法,包括显式欧拉法、隐式欧拉法、Crank-Nicolson格式(即梯形公式)、二阶BDF格式以及不同的差分格式(如五点差分、九点差分和紧差分)。每种方法不仅给出了理论公式的推导,还提供了完整的MATLAB源码实现,并附有详细的代码解释和数值例子的数据图解分析。通过对不同方法的比较,展示了它们在稳定性和精度方面的优劣。 适合人群:具备一定数学和编程基础的学生、科研人员及工程师。 使用场景及目标:适用于需要解决热传导问题的研究项目,帮助使用者理解并选择合适的数值方法进行仿真计算,优化求解过程。 其他说明:文中强调了边界条件处理的重要性,并建议初学者从简单的Dirichlet边界条件入手练习。此外,还提到了一些常见的陷阱,如MATLAB矩阵索引与物理空间坐标的错位问题,提醒开发者注意这些问题以确保正确性。

Global site tag (gtag.js) - Google Analytics