HAL 层是位于操作系统内核与硬件电路之间的接口层。硬件抽象化。隐藏了特定平台的硬件接口细节。
HAL能够向下屏蔽硬件驱动模块的实现细节。向上提供硬件访问服务。通过硬件抽象层,andriod系统通过如下两层来支持硬件设备备。
1. 第一层 在用户空间实现。
2.第二层 在内核空间实现。
andriod 系统中,推出HAL为了保护硬件提供商的知识产权,为了避开Linux的GPL束搏。将控制硬件的动作放到了andtriod HAL中,而Linux driver仅负责简单的交互作用。甚至将硬件寄存器空间直接映射到用户空间。基于apache 的license ,因此硬件厂商可以只提供二进制代码。
andriod 对硬件分两层来实现原因
1.Linux内核代码是遵循GPL1协议,在Linux中添加或者修改了代码,就必须公开。若andriod 系统使用的linux 系统一样。把对硬件的支持完全实现在硬件驱动模块中,那必须公开代码,损害了硬件厂商利益。
2.如果对硬件的支持完全在andriod系统用户空间中,这无法做到,因为只有内核空间才有特权操作硬件设备。因此这种方案就是分层实现。内核空间是硬件驱动模块的形式来支持,提供简单的硬件访问通道。用户空间以硬件抽象层模块的形式提供支持。
设备驱动分为内核空间和用户空间两部分:
- 内核空间主要负责硬件访问逻辑(GPL)
- 用户空间主要负责参数和访问流程控制(Apache License)
Android硬件驱动程序开发:与传统的Linux硬件驱动程序开发是一样的
Android硬件驱动程序验证
Android硬件抽象层模块开发
Android硬件访问服务开发:
HAL层的通用结构剖析
- 通用的321架构
HAL层的主要框架是由三个结构体,两个常量,一个函数构成,所有的硬件抽象模块都是必须遵循321架构,在此基础上扩展自有的功能。 -
三个结构体
//文件位置:hardware/libhardware/include/hardware/hardware.h
/**
* Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
* and the fields of this data structure must begin with hw_module_t
* followed by module specific information.
*/
typedef struct hw_module_t {
/** tag must be initialized to HARDWARE_MODULE_TAG */
uint32_t tag;
......
typedef struct hw_module_methods_t {
/** Open a specific device */
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);} hw_module_methods_t;
/**
* Every device data structure must begin with hw_device_t
* followed by module specific public methods and attributes.
*/
typedef struct hw_device_t {
/** tag must be initialized to HARDWARE_DEVICE_TAG */
uint32_t tag;
......
hw_module_methods_t是封装在hw_module_t里的,里面提供的一个open方法需要具体的实现模块去重载;hw_module_t里面有很多关于模块的信息需要在初始化的时候去填充,非常关键的一个就是重载hw_module_methods_t中的open函数;hw_device_t里主要是和硬件设备相关的一些操作,各硬件模块需要继承该结构体。
- 两个常量和一个函数 -
//文件位置:hardware/libhardware/include/hardware/hardware.h
/**
* Name of the hal_module_info
*/
#define HAL_MODULE_INFO_SYM HMI/**
* Name of the hal_module_info as a string
*/
#define HAL_MODULE_INFO_SYM_AS_STR "HMI"/**
* Get the module info associated with a module by id.
*
* @return: 0 == success, <0 == error and *module == NULL
*/
int hw_get_module(const char *id, const struct hw_module_t **module);
HAL_MODULE_INFO_SYM和HAL_MODULE_INFO_SYM_AS_STR与HAL的模块入口有关,在上层调用hw_get_module时,通过模块ID和对应的HMI(通过dlopen/dlsym进行映射)结构体找到模块入口,然后通过之前重载的open函数,就可以获得设备的操作接口(hw_device_t),之后就可以通过module访问模块实现的相关函数三、一个例子
编程的学习从HelloWorld开始,那嵌入式应该就是从点灯开始。
下面我们就先从一个简单的LED模块的例子,来全面的的理解下HAL的基础框架。
在前面提到了三个结构体,各实现模块需要去继承并客制化自己的操作接口。我们可以从图中看到LED模块遵循该准则,其中hw_module_methods_t是封装在hw_module_t里的,具体的关系图如下: