新增LED設(shè)備--從上層到底層理解安卓架構(gòu)之HAL篇
硬件抽象層介紹
+
1)不是所有的硬件設(shè)備都有標(biāo)準(zhǔn)的Linux內(nèi)核接口,通過(guò)HAL層封裝了一套固定的向上接口,可以使得上層的開(kāi)發(fā)邏輯更清晰簡(jiǎn)單。HAL框架是固定的,開(kāi)發(fā)人員只需要按照框架開(kāi)發(fā)即可,無(wú)需關(guān)注與上層的交互上,將精力放在HAL層本身的實(shí)現(xiàn)上即可。
2)從商業(yè)角度,硬件廠商可以把一些核心的算法、調(diào)試參數(shù)、實(shí)現(xiàn)邏輯等放在HAL層而不是kenel層,kenel層只是簡(jiǎn)單與硬件做數(shù)據(jù)交互。這樣的好處是可以不用遵Linux的GPL開(kāi)源協(xié)議,保護(hù)自身的商業(yè)機(jī)密。
Hal架構(gòu)圖
模塊類型結(jié)構(gòu)體hw_module_t,設(shè)備類型結(jié)構(gòu)體hw_device_t,
兩個(gè)結(jié)構(gòu)體的詳細(xì)內(nèi)容可以參考源碼路徑:/hardware/libhardware/include/hardware/hardware.h。HAL層開(kāi)發(fā)主要工作是建立好自定義的結(jié)構(gòu)體,并實(shí)現(xiàn)hw_device_t的內(nèi)部的幾個(gè)關(guān)鍵函數(shù)。
頭文件hardware/libhardware/include/hardware/testled_hal.h
struct testled_module_t {struct hw_module_t common;};struct testled_device_t {struct hw_device_t common;int (*open)(void);int (*control)(int on);};
頭文件內(nèi)申明了led的兩個(gè)關(guān)鍵結(jié)構(gòu)體testled_module_t和testled_device_t,結(jié)構(gòu)體的實(shí)現(xiàn)在c文件中。
2)c文件 hardware/libhardware/modules/testled/testled_hal.c
//日志的標(biāo)簽
static int fd;int testled_hal_dev_close(struct hw_device_t *device){if(device != NULL){struct testled_device_t *temp = (struct testled_device_t *)device;free(temp);}close(fd);return 0;}int testled_hal_open_dev(void){ALOGD("--%s--", __func__);fd = open("/dev/test-led", O_RDWR);if(fd < 0){ALOGE("open failed : %s", strerror(errno));return fd;}return 0;}int testled_hal_control_dev(int on){ALOGD("--%s--", __func__);int ret;switch(on){case 0:ret = ioctl(fd, LED1CTRL_ON_CMD,0);break;case 1:ret = ioctl(fd, LED1CTRL_OFF_CMD,0);break;case 2:ret = ioctl(fd, LED2CTRL_ON_CMD,0);break;case 3:ret = ioctl(fd, LED2CTRL_OFF_CMD,0);break;default:break;}if(ret < 0){ALOGE("control failed : %s", strerror(errno));return ret;}return 0;}int testled_hal_module_open(const struct hw_module_t *module, const char *id,struct hw_device_t **device){ALOGD("--%s--", __func__);struct testled_device_t *led_dev = NULL;led_dev = (struct testled_device_t *)malloc(sizeof(struct testled_device_t));if (led_dev == NULL){ALOGE("malloc failed");return -1;}ALOGD("malloc success");//初始化device對(duì)象led_dev->common.tag = HARDWARE_DEVICE_TAG;led_dev->common.version = 1;led_dev->common.module = module;led_dev->common.close = testled_hal_dev_close;led_dev->open = testled_hal_open_dev;led_dev->control = testled_hal_control_dev;
//將當(dāng)前的led_dev傳遞給jni層
= (struct hw_device_t *)led_dev;return 0;}struct testled_device_t testled_hal_methods = {open : testled_hal_module_open,};struct testled_module_t HAL_MODULE_INFO_SYM = {common : {tag : HARDWARE_MODULE_TAG,version_major : 1,version_minor : 0,id : LED_HAL_MODULE_ID,name : "testled hal module",methods : &testled_hal_methods,},};
主要實(shí)現(xiàn)了hal結(jié)構(gòu)體中的close,open,control函數(shù),并將函數(shù)傳給結(jié)led_dev構(gòu)體。
common.close = testled_hal_dev_close;led_dev->open = testled_hal_open_dev;control = testled_hal_control_dev;
Android.mk hardware/libhardware/modules/testled/Android.mk
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := testled_hal.defaultLOCAL_MODULE_RELATIVE_PATH := hwLOCAL_SRC_FILES := testled_hal.cLOCAL_SHARED_LIBRARIES := liblog libcutilsLOCAL_MODULE_TAGS := optionalinclude $(BUILD_SHARED_LIBRARY)
將c文件編譯成模塊
hardware/libhardware/modules/Android.mk內(nèi)加入testled
三、編譯
模塊編譯
mmm hardware/libhardware/modules/ testled
在out/target/product/nanopc-t4/system/lib/hw/ 目錄下生生成test_led_hal.default.so
全部編譯后,test_led_hal.default.so在設(shè)備的/system/lib/hw路徑下,android frameworks中的JNI調(diào)用led設(shè)備時(shí),通過(guò)一系列轉(zhuǎn)換就會(huì)調(diào)用到這個(gè)庫(kù)內(nèi)部的函數(shù),從而調(diào)動(dòng)掉底層的led驅(qū)動(dòng)。
掃碼關(guān)注我們
看更多嵌入式案例
喜歡本篇內(nèi)容請(qǐng)給我們點(diǎn)個(gè)再看
免責(zé)聲明:本文內(nèi)容由21ic獲得授權(quán)后發(fā)布,版權(quán)歸原作者所有,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。文章僅代表作者個(gè)人觀點(diǎn),不代表本平臺(tái)立場(chǎng),如有問(wèn)題,請(qǐng)聯(lián)系我們,謝謝!





